Quantcast
Channel: VBForums - CodeBank - Visual Basic 6 and earlier
Viewing all articles
Browse latest Browse all 1470

[VB6] In memory convert to JPEG using WIC

$
0
0
This uses Windows Imaging Component to convert a bitmap (a 32-bit DIB) to a JPEG stream purely in memory.

Paste the following code in a .bas module:

Code:

Option Explicit

Private Declare Function SHCreateMemStream Lib "shlwapi" Alias "#12" (pInit As Any, ByVal cbInit As Long) As stdole.IUnknown
Private Declare Function IStream_Size Lib "shlwapi" (ByVal pStream As stdole.IUnknown, uiSize As Any) As Long
Private Declare Function IStream_Reset Lib "shlwapi" (ByVal pStream As stdole.IUnknown) As Long
Private Declare Function IStream_Read Lib "shlwapi" (ByVal pStream As stdole.IUnknown, pvBuf As Any, ByVal cbSize As Long) As Long
'--- WIC
Private Declare Function WICCreateImagingFactory_Proxy Lib "windowscodecs" (ByVal SDKVersion As Long, ppIImagingFactory As stdole.IUnknown) As Long
Private Declare Function IWICImagingFactory_CreateStream_Proxy Lib "windowscodecs" (ByVal pFactory As stdole.IUnknown, ppIWICStream As stdole.IUnknown) As Long
Private Declare Function IWICImagingFactory_CreateEncoder_Proxy Lib "windowscodecs" (ByVal pFactory As stdole.IUnknown, guidContainerFormat As Any, pguidVendor As Any, ppIEncoder As stdole.IUnknown) As Long
Private Declare Function IWICImagingFactory_CreateBitmapFromMemory_Proxy Lib "windowscodecs" (ByVal pFactory As stdole.IUnknown, ByVal uiWidth As Long, ByVal uiHeight As Long, pixelFormat As Any, ByVal cbStride As Long, ByVal cbBufferSize As Long, pbBuffer As Any, ppIBitmap As stdole.IUnknown) As Long
Private Declare Function IWICStream_InitializeFromIStream_Proxy Lib "windowscodecs" (ByVal pIWICStream As stdole.IUnknown, ByVal pIStream As stdole.IUnknown) As Long
Private Declare Function IWICBitmapEncoder_Initialize_Proxy Lib "windowscodecs" (ByVal pIEncoder As stdole.IUnknown, ByVal pIStream As stdole.IUnknown, ByVal cacheOption As Long) As Long
Private Declare Function IWICBitmapEncoder_CreateNewFrame_Proxy Lib "windowscodecs" (ByVal pIEncoder As stdole.IUnknown, ppIFrameEncode As stdole.IUnknown, ppIEncoderOptions As stdole.IUnknown) As Long
Private Declare Function IWICBitmapEncoder_Commit_Proxy Lib "windowscodecs" (ByVal pIEncoder As stdole.IUnknown) As Long
Private Declare Function IWICBitmapFrameEncode_Initialize_Proxy Lib "windowscodecs" (ByVal pIFrameEncode As stdole.IUnknown, ByVal pIEncoderOptions As stdole.IUnknown) As Long
Private Declare Function IWICBitmapFrameEncode_SetSize_Proxy Lib "windowscodecs" (ByVal pIFrameEncode As stdole.IUnknown, ByVal uiWidth As Long, ByVal uiHeight As Long) As Long
Private Declare Function IWICBitmapFrameEncode_WriteSource_Proxy Lib "windowscodecs" (ByVal pIFrameEncode As stdole.IUnknown, ByVal pIBitmapSource As stdole.IUnknown, pWicRect As Any) As Long
Private Declare Function IWICBitmapFrameEncode_Commit_Proxy Lib "windowscodecs" (ByVal pIFrameEncode As stdole.IUnknown) As Long
Private Declare Function IPropertyBag2_Write_Proxy Lib "windowscodecs" (ByVal pPropBag As stdole.IUnknown, ByVal cProperties As Long, pBag As Any, pvarValue As Variant) As Long

Private m_pWicFactory          As stdole.IUnknown

Public Function WicConvertToJpeg(baOutput() As Byte, ByVal lWidth As Long, ByVal lHeight As Long, baInput() As Byte, ByVal lQuality As Long) As Boolean
    Const WINCODEC_SDK_VERSION1  As Long = &H236&
    Const WINCODEC_SDK_VERSION2  As Long = &H237&
    Const WICBitmapEncoderNoCache As Long = 2
    Dim aGUID(0 To 3)  As Long
    Dim pBitmap        As stdole.IUnknown
    Dim pWicStream      As stdole.IUnknown
    Dim pStream        As stdole.IUnknown
    Dim pEncoder        As stdole.IUnknown
    Dim pFrame          As stdole.IUnknown
    Dim pPropBag        As stdole.IUnknown
    Dim cSize          As Currency
    Dim aBag(0 To 7)    As Long
   
    On Error GoTo EH
    If m_pWicFactory Is Nothing Then
        If WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION2, m_pWicFactory) < 0 Then
            If pvCheckHResult(WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION1, m_pWicFactory)) < 0 Then
                GoTo QH
            End If
        End If
    End If
    '--- GUID_WICPixelFormat32bppPBGRA
    aGUID(0) = &H6FDDC324
    aGUID(1) = &H4BFE4E03
    aGUID(2) = &H773D85B1
    aGUID(3) = &H10C98D76
    If pvCheckHResult(IWICImagingFactory_CreateBitmapFromMemory_Proxy(m_pWicFactory, lWidth, lHeight, aGUID(0), lWidth * 4, UBound(baInput) + 1, baInput(0), pBitmap)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IWICImagingFactory_CreateStream_Proxy(m_pWicFactory, pWicStream)) < 0 Then
        GoTo QH
    End If
    Set pStream = SHCreateMemStream(ByVal 0, 0)
    If pvCheckHResult(IWICStream_InitializeFromIStream_Proxy(pWicStream, pStream)) < 0 Then
        GoTo QH
    End If
    '--- GUID_ContainerFormatJpeg
    aGUID(0) = &H19E4A5AA
    aGUID(1) = &H4FC55662
    aGUID(2) = &H5817C0A0
    aGUID(3) = &H57108E02
    If pvCheckHResult(IWICImagingFactory_CreateEncoder_Proxy(m_pWicFactory, aGUID(0), ByVal 0, pEncoder)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IWICBitmapEncoder_Initialize_Proxy(pEncoder, pWicStream, WICBitmapEncoderNoCache)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IWICBitmapEncoder_CreateNewFrame_Proxy(pEncoder, pFrame, pPropBag)) < 0 Then
        GoTo QH
    End If
    aBag(3) = StrPtr("ImageQuality")
    If pvCheckHResult(IPropertyBag2_Write_Proxy(pPropBag, 1, aBag(0), CSng(lQuality) / 100!)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IWICBitmapFrameEncode_Initialize_Proxy(pFrame, pPropBag)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IWICBitmapFrameEncode_SetSize_Proxy(pFrame, lWidth, lHeight)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IWICBitmapFrameEncode_WriteSource_Proxy(pFrame, pBitmap, ByVal 0)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IWICBitmapFrameEncode_Commit_Proxy(pFrame)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IWICBitmapEncoder_Commit_Proxy(pEncoder)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IStream_Size(pStream, cSize)) < 0 Then
        GoTo QH
    End If
    cSize = cSize * 10000
    If pvCheckHResult(IStream_Reset(pStream)) < 0 Then
        GoTo QH
    End If
    If cSize > 0 Then
        ReDim baOutput(0 To cSize - 1) As Byte
        If pvCheckHResult(IStream_Read(pStream, baOutput(0), cSize)) < 0 Then
            GoTo QH
        End If
    Else
        baOutput = vbNullString
    End If
    '--- success
    WicConvertToJpeg = True
QH:
    Exit Function
EH:
    Debug.Print Err.Description
End Function

Private Function pvCheckHResult(ByVal hResult As Long) As Long
    If hResult < 0 Then
        Err.Raise hResult
    End If
    pvCheckHResult = pvCheckHResult
End Function

Here is the sample Form1 that exercises the WicConvertToJpeg function above

Code:

Option Explicit

Private Declare Function DeleteFile Lib "kernel32" Alias "DeleteFileA" (ByVal lpFileName As String) As Long

Private Sub Form_Load()
    Dim lWidth          As Long
    Dim lHeight        As Long
    Dim baBitmap()      As Byte
    Dim baJpeg()        As Byte
   
    If Not WicLoadPicture("d:\temp\aaa.bmp", lWidth, lHeight, baBitmap) Then
        GoTo QH
    End If
    If Not WicConvertToJpeg(baJpeg, lWidth, lHeight, baBitmap, 80) Then
        GoTo QH
    End If
    WriteBinaryFile "d:\temp\aaa.jpg", baJpeg
QH:
End Sub

Public Sub WriteBinaryFile(sFile As String, baBuffer() As Byte)
    Dim nFile          As Integer
   
    Call DeleteFile(sFile)
    nFile = FreeFile
    Open sFile For Binary Access Write Shared As nFile
    If UBound(baBuffer) >= 0 Then
        Put nFile, , baBuffer
    End If
    Close nFile
End Sub

The test code above needs another .bas module with the WicLoadPicture function

Code:

Option Explicit

'--- WIC
Private Declare Function WICCreateImagingFactory_Proxy Lib "windowscodecs" (ByVal SDKVersion As Long, ppIImagingFactory As stdole.IUnknown) As Long
Private Declare Function IWICImagingFactory_CreateDecoderFromFilename_Proxy Lib "windowscodecs" (ByVal pFactory As stdole.IUnknown, ByVal wzFilename As Long, pguidVendor As Any, ByVal dwDesiredAccess As Long, ByVal lMetadataOptions As Long, ppIDecoder As stdole.IUnknown) As Long
Private Declare Function IWICImagingFactory_CreateFormatConverter_Proxy Lib "windowscodecs" (ByVal pFactory As stdole.IUnknown, ppIFormatConverter As stdole.IUnknown) As Long
Private Declare Function IWICBitmapDecoder_GetFrame_Proxy Lib "windowscodecs" (ByVal pThis As stdole.IUnknown, ByVal lIndex As Long, ppIBitmapFrame As stdole.IUnknown) As Long
Private Declare Function IWICBitmapSource_CopyPixels_Proxy Lib "windowscodecs" (ByVal pThis As stdole.IUnknown, prc As Any, ByVal cbStride As Long, ByVal cbBufferSize As Long, pbBuffer As Any) As Long
Private Declare Function IWICBitmapSource_GetSize_Proxy Lib "windowscodecs" (ByVal pThis As stdole.IUnknown, puiWidth As Long, puiHeight As Long) As Long
Private Declare Function IWICFormatConverter_Initialize_Proxy Lib "windowscodecs" (ByVal pThis As stdole.IUnknown, ByVal pISource As stdole.IUnknown, dstFormat As Any, ByVal lDither As Long, ByVal pIPalette As stdole.IUnknown, ByVal dblAlphaThresholdPercent As Double, ByVal lPaletteTranslate As Long) As Long

Private m_pWicFactory          As stdole.IUnknown

Public Function WicLoadPicture( _
            sFileName As String, _
            lWidth As Long, _
            lHeight As Long, _
            baOutput() As Byte) As Boolean
    Const WINCODEC_SDK_VERSION1 As Long = &H236&
    Const WINCODEC_SDK_VERSION2 As Long = &H237&
    Const GENERIC_READ          As Long = &H80000000
    Dim pDecoder        As stdole.IUnknown
    Dim pFrame          As stdole.IUnknown
    Dim pConverter      As stdole.IUnknown
    Dim aGUID(0 To 3)  As Long
   
    If m_pWicFactory Is Nothing Then
        If WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION2, m_pWicFactory) < 0 Then
            If pvCheckHResult(WICCreateImagingFactory_Proxy(WINCODEC_SDK_VERSION1, m_pWicFactory)) < 0 Then
                GoTo QH
            End If
        End If
    End If
    If pvCheckHResult(IWICImagingFactory_CreateDecoderFromFilename_Proxy(m_pWicFactory, StrPtr(sFileName), ByVal 0, GENERIC_READ, 0, pDecoder)) < 0 Or pDecoder Is Nothing Then
        GoTo QH
    End If
    If pvCheckHResult(IWICBitmapDecoder_GetFrame_Proxy(pDecoder, 0, pFrame)) < 0 Or pFrame Is Nothing Then
        GoTo QH
    End If
    If pvCheckHResult(IWICBitmapSource_GetSize_Proxy(pFrame, lWidth, lHeight)) < 0 Then
        GoTo QH
    End If
    If pvCheckHResult(IWICImagingFactory_CreateFormatConverter_Proxy(m_pWicFactory, pConverter)) < 0 Or pConverter Is Nothing Then
        GoTo QH
    End If
    '--- GUID_WICPixelFormat32bppPBGRA
    aGUID(0) = &H6FDDC324
    aGUID(1) = &H4BFE4E03
    aGUID(2) = &H773D85B1
    aGUID(3) = &H10C98D76
    If pvCheckHResult(IWICFormatConverter_Initialize_Proxy(pConverter, pFrame, aGUID(0), 0, Nothing, 0#, 0)) < 0 Then
        GoTo QH
    End If
    ReDim baOutput(0 To lWidth * lHeight * 4 - 1) As Byte
    If pvCheckHResult(IWICBitmapSource_CopyPixels_Proxy(pConverter, ByVal 0&, lWidth * 4, lWidth * lHeight * 4, baOutput(0))) < 0 Then
        GoTo QH
    End If
    '--- success
    WicLoadPicture = True
QH:
End Function

Private Function pvCheckHResult(ByVal hResult As Long) As Long
    If hResult < 0 Then
        Err.Raise hResult
    End If
    pvCheckHResult = pvCheckHResult
End Function

Posted all this code with all API declares to be searchable in the forums as WIC is quite apocryphal technology here.

cheers,
</wqw>

Viewing all articles
Browse latest Browse all 1470

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>