|
9#
楼主 |
发表于 2015-6-27 19:39:48
|
只看该作者
Private Sub InitializeMatrix()
' a quick look up table for bit shifting & palette calculations
ReDim pow2x8(0 To 7)
' using copymemory vs doing the 2^n calculations 8 times
CopyMemory pow2x8(0), 134480385, &H4
CopyMemory pow2x8(4), -2143281136, &H4 ' Array(1,2,4,8,16,32,64,128)
' initialize interlacing matrix, used in the ConvertPNGtoBMP routine and
' also used to calculate the uncompressed size of the compressed PNG data
' Non-interlaced images are considered Pass#8, where interlaced images always
' contain 7 passes (1 thru 7).
' determines what row, in the interlaced image, the current pass begins at
ReDim MatrixRow(1 To 8)
CopyMemory MatrixRow(1), 262144, &H4
CopyMemory MatrixRow(5), 65538, &H4 'Array(0, 0, 4, 0, 2, 0, 1, 0)
' determines what column, in the interlaced image, the current pass begins at
ReDim MatrixCol(1 To 8)
CopyMemory MatrixCol(1), 33555456, &H4
CopyMemory MatrixCol(5), 256&, &H4 'Array(0, 4, 0, 2, 0, 1, 0, 0)
' determines the row interval of the current pass
ReDim MatrixRowAdd(1 To 8)
CopyMemory MatrixRowAdd(1), 67635208, &H4
CopyMemory MatrixRowAdd(5), 16908804, &H4 'Array(8, 8, 8, 4, 4, 2, 2, 1)
' determines the column interval of the current pass
ReDim MatrixColAdd(1 To 8)
CopyMemory MatrixColAdd(1), 67373064, &H4
CopyMemory MatrixColAdd(5), 16843266, &H4 'Array(8, 8, 4, 4, 2, 2, 1, 1)
' 1st 7 elements of next 2 arrays used for pixellated interlaced images
' determines the width of each pixellated pixel for the current pass
ReDim MatrixCX(1 To 8)
CopyMemory MatrixCX(1), 33817608, &H4
CopyMemory MatrixCX(5), 16843010, &H4 'Array(8, 4, 4, 2, 2, 1, 1, 1)
' determines the height of each pixellated pixel for the current pass
MatrixCY() = MatrixColAdd() 'Array(8, 8, 4, 4, 2, 2, 1, 1)
End Sub
Private Sub Class_Terminate()
ClearMemoryVariables ' clean up
Set cPNGimage = Nothing
End Sub
Private Function ClearMemoryVariables()
' // LaVolpe, Dec 15
' Function simply zero's out some key variables for reuse of class & loading other files
If Not cPNGimage Is Nothing Then
' no need to exectute lines if no png was previously loaded
Erase png_Comments() ' compressed text
Erase png_Palette() ' palette data
Erase png_TransSimple() ' simple transparency data
Erase png_LastModified() ' modified date in byte format
Erase png_Chromaticity() ' Chromaticity information
Erase png_Physical() ' aspect ratio/physical pixel size information
Erase png_Offsets() ' image offset information
png_sRGB = 0 ' use of standard RGB color space
Erase pow2x8() ' bit shifting look up table
Erase MatrixCol()
Erase MatrixColAdd()
Erase MatrixCX()
Erase MatrixCY()
Erase MatrixRow()
Erase MatrixRowAdd()
cPNGimage.CleanUp_ALL ' destroy any resources used/created
End If
c_TransColor = -1 ' cached transparent color
png_WinBKG = -1 ' cached pNG suggested window bkg color
c_Overrides = 0 ' class wide options
c_AlphaColor = -1 ' cached alpha color replacement value
End Function
Private Function ConvertVBSysColor(inColor As Long) As Long
On Error GoTo ExitRoutine
If inColor < 0 Then
' vb System colors (i.e, vbButton face) are negative & contain the &HFF& value
ConvertVBSysColor = GetSysColor(inColor And &HFF&)
Else
ConvertVBSysColor = inColor
End If
Exit Function
ExitRoutine:
ConvertVBSysColor = inColor
End Function
Private Function ConvertPNGtoBMP(rawBytes() As Byte, ByVal scanPass As Byte, _
scanCY As Long, rBPRow As Long, startOffset As Long)
' // LaVolpe, Dec 1 thru 10 - Added from Scratch
' 19 Dec -- rewrote to simplify. More & more options made the routine too disorganized
' added the bNeedAlpha, bNeedBGR, bPackByte flags to categorize needed actions
' This routine (quite big due to various conversion issues) will convert
' PNG bits/bytes to BMP bits/bytes. Common issues to deal with include the
' byte-aligned PNG data may not be the same width as DWord-aligned BMP data. Also,
' BMPs do not support 48bpp nor 2bpp bitmaps. And the biggie: PNGs are RGB
' while DIBs are BGR; otherwise, displaying PNGs would be super quick.
' rawBytes() are the png scanline bytes
' scanPass() is a valid number btwn 1-8 (8 indicates non-interlaced)
' scanCY is number of scanlines (btwn 1 and image height)
' rBPRow is the number of bytes per scanline of the rayBytes array (byte aligned)
' startOffset() is used for scanner-type progression & indicates destination row to begin with
' When no interlacing options are used, this is called once per PNG
' When non-scanner type interlacing is used, called 7 times
' When scanner type interlacing is used, called Height\16+1 times
Dim rRow As Long, rColumn As Long ' current row/column of the png image
Dim dRow As Long, dColumn As Long ' current row/column of destination bitmap
Dim dIndex As Long ' position of dRow in the destBytes() array
Dim dBitPP As Byte, dBytePP As Byte ' nr of bits/bytes per pixel of bitmap
Dim rBytePP As Byte ' nr of bytes per pixel in png image
Dim sub8ptr As Byte ' used to count bits within a byte, for 1,2,4 bpp pngs
Dim tColor As Long ' color value when copying 3 or 4 bytes to a 3 or 4 byte array
Dim bBlockTransfer As Boolean ' special quick copy flag
Dim blockCX As Long, blockCY As Long, blkIndex As Long
'^^ counter/variables for pixelated interlacing
Dim alphaModifyer As Long, pIndex As Long ' alpha related variables
Dim destBytes() As Byte, workBytes() As Byte ' placeholders for DIB bits (DMA)
Dim TSA As SafeArray1D, TSA_w As SafeArray1D ' array overlays for DIB bits (DMA)
Dim wRowWidth As Long, dRowWidth As Long ' DWord aligned width of bitmap scanline/row
Dim bNeedBGR As Boolean, bPackByte As Boolean, bNeedAlpha As Boolean
'^^ categorized pixel actions
On Error GoTo err_h
' use direct memory access (DMA) to reference the DIB pixel data
With TSA
.cDims = 1 ' Number of dimensions
.cbElements = 1 ' Size of data elements
.pvData = cPNGimage.PngDataPtr ' Data address
.rgSABound.lLbound = 0 ' Low bound of array
.rgSABound.cElements = cPNGimage.PngDataSize ' Nr of Elements
End With
CopyMemory ByVal VarPtrArray(destBytes), VarPtr(TSA), 4
' determine the bits/bytes of the png and bitmap images
GetDepthInfo dBitPP, dBytePP, 0, rBytePP
' get location of BMP scanline we are processing from PNG scanline
If startOffset Then dRow = startOffset Else dRow = MatrixRow(scanPass)
dRowWidth = (UBound(destBytes) + 1) \ png_Height
If dBitPP < 24 Then
' special case when processing 1, 4 and 8 bpp, non-alpha PNGs
' doesn't apply when converting RGB to BGR is in effect (bpp>8) and
' only applies when png & bitmap bits-per-pixel are same
' Can apply to interlaced images too if on the last pass cause every adjacent
' pixel in image's scanline is provided in that pass
bBlockTransfer = (dBitPP = png_BitDepth And scanPass > 6)
' ^^ note: when scanPass=8 then PNG is non-interlaced
End If
|
|