|
Private Function UnfilterNI(FilteredData() As Byte, _
tgtDC As Long, tgtWindow As Long, dcX As Long, dcY As Long, AlphaBlend As Byte) As Boolean
' // LaVolpe, Dec 1 thru 10 - completely rewritten to remove excess large array usage
' http://www.w3.org/TR/PNG/#9-table91
Dim UnFiltered() As Byte, Row As Long
Dim BPRow As Long, lBpp As Byte, dBpp As Byte, stepVal As Byte
Dim lastLineBlt As Long
Const fauxInterlace As Long = 16
'^^ tried other values ranging from 4 to 32 and 16 is best performance
GetDepthInfo dBpp, 0, lBpp, stepVal
BPRow = GetBytesPerPixel(png_Width, lBpp) + 1
ReDim UnFiltered(0 To (BPRow - 1) * png_Height - 1)
For Row = 0 To png_Height - 1
Select Case FilteredData(BPRow * Row)
Case 0 'None
CopyMemory UnFiltered(BPRow * Row - Row), FilteredData(BPRow * Row + 1), BPRow - 1
Case 1 'Sub
DecodeFilter_Sub FilteredData, UnFiltered, Row, BPRow, stepVal
Case 2 'Up
DecodeFilter_Up FilteredData, UnFiltered, Row, BPRow
Case 3 'Average
DecodeFilter_Avg FilteredData, UnFiltered, Row, BPRow, stepVal
Case 4 'Paeth
DecodeFilter_Paeth FilteredData, UnFiltered, Row, BPRow, stepVal
Case Else ' invalid filter type
Exit Function
End Select
If Row Mod fauxInterlace = 0 Then
If Row Then
RaiseEvent Progress(Row * 100 \ png_Height)
lastLineBlt = Row
If ConvertPNGtoBMP(UnFiltered(), 8, Row, BPRow - 1, Row - fauxInterlace) = False Then Exit Function
If (c_Overrides And pdScanner) = pdScanner Then _
cPNGimage.DisplayInterlaced tgtDC, tgtWindow, dcX, dcY, Row - fauxInterlace, fauxInterlace, (Row = png_Height), True, c_AlphaColor, AlphaBlend
End If
End If
Next Row
RaiseEvent Progress(100)
If lastLineBlt < fauxInterlace Then
If ConvertPNGtoBMP(UnFiltered(), 8, png_Height, BPRow - 1, 0) = False Then Exit Function
If (c_Overrides And pdScanner) = pdScanner Then _
cPNGimage.DisplayInterlaced tgtDC, tgtWindow, dcX, dcY, 0, png_Height, True, True, c_AlphaColor, AlphaBlend
Else
Row = png_Height - lastLineBlt
If Row > 1 Then
If ConvertPNGtoBMP(UnFiltered(), 8, png_Height, BPRow - 1, png_Height - Row) = False Then Exit Function
End If
If (c_Overrides And pdScanner) = pdScanner Then _
cPNGimage.DisplayInterlaced tgtDC, tgtWindow, dcX, dcY, png_Height - Row, Row, True, True, c_AlphaColor, AlphaBlend
End If
UnfilterNI = True
End Function
Private Function ValidateDLLExists() As Boolean
' function ensures DLLs of interest exist in user's system path
' side note: DLL filename is not case-sensitive, call names are!
Dim lb As Long, pa As Long, sRtn As String
Dim I As Integer, sDLL As String, sCall As String
For I = 1 To 2
Select Case I
Case 1
sDLL = "zlibvb.dll": sCall = "uncompress"
Case 2
sDLL = "ws2_32.dll": sCall = "htonl"
End Select
'attempt to open the DLL to be checked
lb = LoadLibrary(sDLL)
'if so, retrieve the address of one of the function calls
If lb Then pa = GetProcAddress(lb, sCall)
If pa = 0 Then ' nope, don't got it; can't run project
If Len(sRtn) Then sRtn = sRtn & vbCrLf
sRtn = sRtn & sDLL
Else ' got it, free references
FreeLibrary lb
lb = 0
pa = 0
End If
Next
If Len(sRtn) Then
sRtn = "Following DLL(s) not found in your system path:" & vbCrLf & sRtn
MsgBox sRtn, vbExclamation + vbOKOnly, "Missing Library"
Else
ValidateDLLExists = True
End If
End Function
Private Function zChunk_bKGD(Buffer() As Byte, bufLen As Long, crcValue As Long) As String
'http://www.w3.org/TR/PNG/#11bKGD
If crcValue Then
If ntohl(crcValue) <> Zcrc32(0, Buffer(0), bufLen + 4) Then Exit Function
End If
On Error Resume Next
Select Case png_ColorType
Case 2, 6 ' true color with/without transparency
png_WinBKG = Buffer(5) Or Buffer(7) * 256& Or Buffer(9) * 65536
Case 3 ' grayscale or paletted
png_WinBKG = GetPaletteValue(0, Buffer(4))
Case 0, 4 ' grayscale with/without transparency
png_WinBKG = GetPaletteValue(0, Buffer(5))
End Select
If Err Then
png_WinBKG = -1 ' no suggested window background color
Err.Clear
End If
End Function
Private Function zChunk_IHDR(Buffer() As Byte, bufLen As Long, crcValue As Long, cmprSize As Long) As String
'http://www.w3.org/TR/PNG/#11IHDR
' IHDR structure
' Width As Long << cannot be negative
' Height As Long << cannot be negative
' BitDepth As Byte << must be 1,2,4,8,16
' ColorType As Byte << must be 0,2,3,4,6
' Compression As Byte << must be zero
' Filter As Byte << must be zero
' Interlacing As Byte << must be zero or one
On Error Resume Next
If ntohl(crcValue) = Zcrc32(0, Buffer(0), bufLen + 4) Then
Dim lRtn As Long, sReturn As String
CopyMemory png_Width, Buffer(4), 4
png_Width = ntohl(png_Width)
CopyMemory png_Height, Buffer(8), 4
png_Height = ntohl(png_Height)
If png_Width < 1 Or png_Height < 1 Then
sReturn = "Corrupted Image Header. Cannot continue."
Else
If Buffer(14) > 0 Then
sReturn = "Invalid Compression Flag in Header. Cannot continue."
Else
If Buffer(15) > 0 Then
sReturn = "Invalid Filter Flag in Header. Cannot continue."
Else
png_BitDepth = Buffer(12)
Select Case png_BitDepth
Case 1, 2, 4, 8, 16
' it is a valid bit depth
png_ColorType = Buffer(13)
Select Case png_ColorType
Case 0, 2, 3, 4, 6
' it is a valid color type
png_Interlacing = Buffer(16)
If png_Interlacing > 1 Then
sReturn = "Invalid Interlacing Flag in Header. Cannot continue."
End If
Case Else
sReturn = "Invalid Color Type Flag in Header. Cannot continue."
End Select
Case Else
sReturn = "Invalid Bit Depth Flag in Header. Cannot continue."
End Select
End If ' Filter flag
End If ' Compression flag
End If ' Dimensions
If sReturn = "" Then
' check for png sizes that would cause overflow errors in other calculations...
' This has 2 basic checks
' check DWord width alignment * height first are within bounds
lRtn = ((((png_Width * 32) + &H1F) And Not &H1F&) \ &H8) * png_Height
' see if uncompress png data is too long
If Not Err Then cmprSize = CalcUncompressedWidth()
If cmprSize = 0 Then
If Err Then Err.Clear
' either the dWord aligned bytes required for the bitmap
' are too large (Long value) or the size of the total
' uncompressed pixel array is too large (Long value).
' Image is way too big to process anyway! would require GBs of memory
sReturn = "Image is too large to process. Cannot continue."
End If
End If
Else ' error; CRC validation failed; corrupt file
sReturn = "Corrupted Image Header (bad CRC). Cannot continue."
End If
zChunk_IHDR = sReturn
End Function
Private Function zChunk_PLTE(Buffer() As Byte, bufLen As Long, crcValue As Long) As String
' http://www.w3.org/TR/PNG/#11PLTE
If png_ColorType = 0 Or png_ColorType = 4 Then Exit Function
'^^ per specs, palettes shall not appear for those color types
' Since we can ignore the palette, we won't trigger a critcal error
If ntohl(crcValue) = Zcrc32(0, Buffer(0), bufLen + 4) Then
' per png specs, palette must be divisible by 3
If (bufLen \ 3) * 3 = bufLen Then
ReDim png_Palette(bufLen - 1)
CopyMemory png_Palette(0), Buffer(4), bufLen
Else ' error
zChunk_PLTE = "Invalid Palette. Cannot continue."
End If
Else ' error; CRC validation failed; corrupt file
zChunk_PLTE = "Invalid Palette (bad CRC). Cannot continue."
End If
End Function
|
|