⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpngparser.cls

📁 AeroSuite--一组非常漂亮的VISTA控件集
💻 CLS
📖 第 1 页 / 共 5 页
字号:
    ReDim IDATdata(0 To streamLength \ 2&)  ' array to hold compressed data; start with arbritrary length
    bCRCchecks = zValidateZLIBversion()     ' verify we can use zLIB
    
    Do ' read & pre-process the png file
    
        ' Chunks consist of 4 bytes for the length of the chunk
        '                 + n bytes for the chunk
        '                 + 4 bytes for a CRC value
        If FileNumber = 0& Then
            CopyMemory gpLong, pngStream(ptrArray), 4& ' length of the current chunk
        Else
            'Get FileNumber, , gpLong ' number of bytes for the chunk
            ReadFile FileNumber, gpLong, 4&, readRtn, ByVal 0&
        End If
        ChunkLen = iparseReverseLong(gpLong) ' longs are big endian, need little endian for Windows
        
        ' track position of pointer in the file
        ptrLoc = ptrLoc + ChunkLen + 12& ' 12 = 4byte name + 4byte CRC + 4byte chunk count
        If ptrLoc > streamLength Then
            ' corrupted file; abort
            lError = 1&
            Exit Do
        End If
        
        ' read chunk name & chunk data, read CRC separately
        If FileNumber = 0& Then
            If bCRCchecks = True Then CopyMemory crc32value, pngStream(ptrArray + ChunkLen + 8&), 4&
        Else
            ReDim pngStream(0 To ChunkLen + 3&)
            'Get FileNumber, , pngStream
            'Get FileNumber, , gpLong             ' read the CRC value (big endian)
            ReadFile FileNumber, pngStream(0), ChunkLen + 4&, readRtn, ByVal 0&
            ReadFile FileNumber, gpLong, 4&, readRtn, ByVal 0&
            If bCRCchecks = True Then crc32value = gpLong
        End If
        CopyMemory ChunkName, pngStream(ptrArray + 4&), 4& ' extract the chunk name
        
        If ChunkLen < 1& Then
            ' should never be <0; however can be zero at anytime
            If ChunkName = chnk_IEND Then Exit Do
        Else
            
            ' each of the chunk parsing routines will be in a separate function.
            ' This is so that they can easily be modified without affecting any
            ' of the other code. Additionally, it is possible that chunk types will
            ' increase as PNG continues to evolve. Except IDAT, all chunks
            ' are in their own routines
            Select Case ChunkName
            
            Case chnk_IDAT ' UCase chunk names are critical - CRC check
                ' compressed, filtered image data
                On Error Resume Next
                ' error? what error? all precautions taken in zChunk_IHDR function
                ' However; no predicting "Out of Memory" errors
                If Not crc32value = 0& Then
                    lError = Not (zCheckCRCvalue(VarPtr(pngStream(ptrArray + 4&)), ChunkLen + 4&, crc32value))
                End If
                If lError = 0& Then
                    gpLong = lenIDAT + ChunkLen ' size of array needed
                    If gpLong > UBound(IDATdata) Then ' test length & increment/buffer if needed
                        ReDim Preserve IDATdata(0 To gpLong + streamLength \ 4&)
                    End If
                    CopyMemory IDATdata(lenIDAT), pngStream(ptrArray + 8&), ChunkLen ' & append the new data
                    lenIDAT = gpLong  ' cache number of compressed bytes so far
                    If Err Then
                        lError = 1&
                        Exit Do
                    End If
                End If
                On Error GoTo 0
            
            Case chnk_PLTE ' UCase chunk names are critical - CRC check
                lError = zChunk_PLTE(ChunkLen, ptrArray + 4&, crc32value)
            
            Case chnk_tRNS ' simple transparency option
                ' CRC checked 'cause if invalid, we could generate an out of bounds
                ' error in one of the other routines that reference this array
                lError = zChunk_tRNS(ChunkLen, ptrArray + 4&, crc32value)
                
            Case chnk_IHDR ' UCase chunk names are critical - CRC check
                ' Note: the zChunk_IHDR routine also calculates uncompressed size
                lError = zChunk_IHDR(ChunkLen, ptrArray + 4&, uncmprssSize, crc32value)
                
            Case chnk_IEND ' UCase chunk names are critical - CRC check
                ' should CRC check for corrupted file; but why? we're at end of image
                Exit Do
                
            End Select
            If Not lError = 0& Then Exit Do
    
        End If
        If FileNumber = 0& Then ptrArray = ptrArray + ChunkLen + 12& ' move to next position in the array
    Loop

ExitRoutine:
    ' clean up
    If Not FileNumber = 0& Then
        'Close #FileNumber
        Erase pngStream()
    End If
    
    If lenIDAT = 0& Or Not lError = 0& Then  ' invalid png image
        If Err Then Err.Clear
    Else

        ' process the compressed data
        Call PostLoadPNG(IDATdata(), lenIDAT, uncmprssSize)
    End If

End Function

Private Function PostLoadPNG(IDATdata() As Byte, lenIDAT As Long, uncmprssSize As Long) As Boolean

    ' Purpose: Uncompress compressed bytes and send to the un-filtering routines
    Dim RawPNGdata() As Byte
    Dim bUncompressed As Boolean
    Dim lRtn As Long

    On Error Resume Next
    ' we need to uncompress our PNG file
    ReDim RawPNGdata(0 To uncmprssSize - 1&)
    
    ' if zLIB is available, let it uncompress; faster than pure VB
    If Not m_ZLIBver = 0& Then   ' tested/set in LoadPNG routine
        bUncompressed = zInflate(VarPtr(RawPNGdata(0)), VarPtr(uncmprssSize), VarPtr(IDATdata(0)), lenIDAT)
    End If

    If Not bUncompressed Then
        ' either zLib returned an error or it wasn't available, uncompress by hand
        bUncompressed = vbDecompress(RawPNGdata(), IDATdata(), uncmprssSize)
        If Err Then Err.Clear
    End If
    Erase IDATdata()
    
    If Not bUncompressed Then
        ' failed to uncompress & shouldn't happen 'cause if I calculated uncmprssSize
        ' wrong, then other calculations in this routine are wrong too
        ' See: CalcUncompressedWidth
        Exit Function
    End If

    Call InitializePalette  ' if PNG is palettized, create palette
    cHost.InitializeDIB m_Width, m_Height    ' create 32bpp DIB to hold PNG
    
    ' call function to begin converting PNG to Bitmap
    If m_Interlacing = 0& Then
        lRtn = UnfilterNI(RawPNGdata()) ' non-interlaced image
    Else
        lRtn = UnfilterInterlaced(RawPNGdata()) ' interlaced image
    End If

    ' return results
    If lRtn = 0& Then
        cHost.DestroyDIB ' failure decoding the PNG
    Else
        If m_ColorType > clrPalette Then
            cHost.Alpha = True
        ElseIf Not m_TransColor = -1& Then
            cHost.Alpha = True
        Else
            cHost.Alpha = False
        End If
        cHost.ImageType = imgPNG
        PostLoadPNG = True
    End If

End Function

Private Function CalcUncompressedWidth() As Long

    Dim uncompressedWidth As Long, iBitPP As Byte
    Dim Pass As Long, passWidth As Long, passHeight As Long

    On Error GoTo NoLoad

    InitializeMatrix    ' build the interlacing matrix; also used for non-interlaced too

    ' get the actual bits per pixel the png is using
    ' (i.e., 16bitdepth png @ ColorType 6 = 64bits per pixel)
    GetDepthInfo 0, 0, iBitPP, 0
    
    If m_Interlacing = 0& Then ' no interlacing
        ' uncompressed width will be byte aligned width + 1 for filter byte
        ' multiplied by the height
        passWidth = GetBytesPerPixel(m_Width, iBitPP)
        uncompressedWidth = passWidth * m_Height + m_Height
    Else
        ' interlaced will also be byte aligned but per scanline width
        ' Each of the 7 passes can have different widths + 1 filter byte per line
        For Pass = 1& To 7&
            ' calculate number of pixels per scan line
            passWidth = m_Width \ m_MatrixDat(Pass, MatrixColAdd) - (m_Width Mod m_MatrixDat(Pass, MatrixColAdd) > m_MatrixDat(Pass, MatrixCol))
            ' determine number of bytes needed for each scanline
            passWidth = GetBytesPerPixel(passWidth, iBitPP)
            ' calculate number of rows for this scan's pass
            passHeight = m_Height \ m_MatrixDat(Pass, MatrixRowAdd) - (m_Height Mod m_MatrixDat(Pass, MatrixRowAdd) > m_MatrixDat(Pass, MatrixRow))
            ' now get the total bytes needed for the entire pass,
            ' adding 1 filter byte for each line in the pass:  i.e., + passHeight
            uncompressedWidth = uncompressedWidth + passWidth * passHeight + passHeight
        Next
        
    End If
    
    CalcUncompressedWidth = uncompressedWidth

NoLoad:
End Function

Private Sub InitializeMatrix()
        
    ' a quick look up table for bit shifting operations
    If m_ColorType = clrGrayScale Or m_ColorType = clrPalette Then
        Dim i As Integer
        ReDim pow2x8(0 To 8)
        pow2x8(0) = 1&
        For i = 1& To 8&
            pow2x8(i) = pow2x8(i - 1&) * 2&
        Next
    End If
    ReDim m_MatrixDat(1 To 8, MatrixRow To MatrixColAdd)
    ' for rendering progressive display:
    '   - change 2D elements above: MatrixRow to MatrixPixelWidth
    '   - unrem final array element assignments below
    
    ' 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
    CopyMemory m_MatrixDat(1, MatrixRow), 262144, 4&
    CopyMemory m_MatrixDat(5, MatrixRow), 65538, 4&  'Array(0, 0, 4, 0, 2, 0, 1, 0)
    ' determines what column in the interlaced image, the current pass begins at
    CopyMemory m_MatrixDat(1, MatrixCol), 33555456, 4&
    CopyMemory m_MatrixDat(5, MatrixCol), 256&, 4& 'Array(0, 4, 0, 2, 0, 1, 0, 0)
    ' determines the row interval of the current pass
    CopyMemory m_MatrixDat(1, MatrixRowAdd), 67635208, 4&
    CopyMemory m_MatrixDat(5, MatrixRowAdd), 16908804, 4& 'Array(8, 8, 8, 4, 4, 2, 2, 1)
    ' determines the column interval of the current pass
    CopyMemory m_MatrixDat(1, MatrixColAdd), 67373064, 4&
    CopyMemory m_MatrixDat(5, MatrixColAdd), 16843266, 4& '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 (Used only when progressive display rendering)
    'CopyMemory m_MatrixDat(1, MatrixPixelWidth), 33817608, 4&
    'CopyMemory m_MatrixDat(5, MatrixPixelWidth), 16843010, 4& 'Array(8, 4, 4, 2, 2, 1, 1, 1)
    ' determines the height of each pixellated pixel for the current pass
    'CopyMemory m_MatrixDat(1, MatrixPixelHeight), m_MatrixDat(1, MatrixColAdd), &H8 'Array(8, 8, 4, 4, 2, 2, 1, 1)

End Sub


Private Function ConvertPNGtoBMP_NonPalette(rawBytes() As Byte, ByVal scanPass As Byte, _
                    ByVal scanCY As Long, ByVal rBPRow As Long, _
                    Optional ByVal startOffset As Long = 0) As Boolean

' Routine processes only non-paletted, non-16bit PNG data

' 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)

    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 rBytePP As Byte ' nr of bytes per pixel in png image
    Dim destPos As Long, rgbIncrR As Long, rgbIncrG As Long
    
    Dim destBytes() As Byte ' placeholders for DIB bits (DMA)
    Dim tSA As SafeArray  ' array overlays for DIB bits (DMA)
    
    On Error GoTo err_h
    
    ' use direct memory access (DMA) to reference the DIB pixel data
    With tSA
        .cDims = 2                          ' Number of dimensions
        .cbElements = 1                     ' Size of data elements
        .pvData = cHost.BitsPointer         ' Data address
        .rgSABound(0).cElements = m_Height
        .rgSABound(1).cElements = m_Width * 4& ' Nr of Elements
    End With
    CopyMemory ByVal VarPtrArray(destBytes), VarPtr(tSA), 4&

    ' determine the bits/bytes of the png and bitmap images
    GetDepthInfo 0, 0, 0, rBytePP

    ' get location of BMP scanline we are processing from PNG scanline
    If startOffset = 0& Then

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -