Func _WinAPI_CompressBitmapBits($hBitmap, ByRef $pBuffer, $iCompression = 0, $iQuality = 100)
Local $Size[2], $Count, $Format, $Length, $Mime, $Ret, $hDC, $hSv, $hMem, $tBits, $tInfo, $tData, $pData, $Error = 1
Local $hSource = 0, $hImage = 0, $hToken = 0, $pEncoder = 0, $pStream = 0, $tParam = 0
Local $tDIB = DllStructCreate($tagDIBSECTION)
If Not __DLL('gdiplus.dll') Then
Return SetError(3, 0, 0)
EndIf
Do
Switch $iCompression
Case 0
$Mime = 'image/png'
Case 1
$Mime = 'image/jpeg'
Case Else
ExitLoop
EndSwitch
While $hBitmap
If Not _WinAPI_GetObject($hBitmap, DllStructGetSize($tDIB), DllStructGetPtr($tDIB)) Then
ExitLoop 2
EndIf
If (DllStructGetData($tDIB, 'bmBitsPixel') = 32) And (Not DllStructGetData($tDIB, 'biCompression')) Then
ExitLoop
EndIf
If $hSource Then
ExitLoop 2
EndIf
$hSource = _WinAPI_CreateDIB(DllStructGetData($tDIB, 'bmWidth'), DllStructGetData($tDIB, 'bmHeight'))
If @error Then
ExitLoop 2
EndIf
$hDC = _WinAPI_CreateCompatibleDC(0)
$hSv = _WinAPI_SelectObject($hDC, $hSource)
If _WinAPI_DrawBitmap($hDC, 0, 0, $hBitmap) Then
$hBitmap = $hSource
Else
$hBitmap = 0
EndIf
_WinAPI_SelectObject($hDC, $hSv)
_WinAPI_DeleteDC($hDC)
WEnd
If Not $hBitmap Then
ExitLoop
EndIf
For $i = 0 To 1
$Size[$i] = DllStructGetData($tDIB, $i + 2)
Next
$tBits = DllStructCreate('byte[' & ($Size[0] * $Size[1] * 4) & ']')
If Not _WinAPI_GetBitmapBits($hBitmap, DllStructGetSize($tBits), DllStructGetPtr($tBits)) Then
ExitLoop
EndIf
$tData = DllStructCreate('uint;ptr;int;int')
DllStructSetData($tData, 1, 1)
$Ret = DllCall('gdiplus.dll', 'uint', 'GdiplusStartup', 'ptr*', 0, 'ptr', DllStructGetPtr($tData), 'ptr', 0)
If (@error) Or ($Ret[0]) Then
ExitLoop
EndIf
If _WinAPI_IsAlphaBitmap($hBitmap) Then
$Format = 0x0026200A
Else
$Format = 0x00022009
EndIf
$hToken = $Ret[1]
$Ret = DllCall('gdiplus.dll', 'uint', 'GdipCreateBitmapFromScan0', 'int', $Size[0], 'int', $Size[1], 'uint', $Size[0] * 4, 'uint', $Format, 'ptr', DllStructGetPtr($tBits), 'ptr*', 0)
If (@error) Or ($Ret[0]) Then
ExitLoop
EndIf
$hImage = $Ret[6]
$Ret = DllCall('gdiplus.dll', 'uint', 'GdipGetImageEncodersSize', 'uint*', 0, 'uint*', 0)
If (@error) Or ($Ret[0]) Then
ExitLoop
EndIf
$Count = $Ret[1]
$tData = DllStructCreate('byte[' & $Ret[2] & ']')
If @error Then
ExitLoop
EndIf
$pData = DllStructGetPtr($tData)
$Ret = DllCall('gdiplus.dll', 'uint', 'GdipGetImageEncoders', 'uint', $Count, 'uint', $Ret[2], 'ptr', $pData)
If (@error) Or ($Ret[0]) Then
ExitLoop
EndIf
For $i = 1 To $Count
$tInfo = DllStructCreate('byte[16];byte[16];ptr[5];dword[4];ptr[2]', $pData)
If Not StringInStr(_WinAPI_WideCharToMultiByte(DllStructGetData($tInfo, 3, 5)), $Mime) Then
$pData += DllStructGetSize($tInfo)
Else
$pEncoder = $pData
ExitLoop
EndIf
Next
If Not $pEncoder Then
ExitLoop
EndIf
Switch $iCompression
Case 0
; Nothing
Case 1
$tParam = DllStructCreate('dword;byte[16];dword;dword;ptr;ulong')
DllStructSetData($tParam, 1, 1)
DllStructSetData($tParam, 3, 1)
DllStructSetData($tParam, 4, 4)
DllStructSetData($tParam, 5, DllStructGetPtr($tParam, 6))
DllStructSetData($tParam, 6, $iQuality)
$Ret = DllCall('ole32.dll', 'uint', 'CLSIDFromString', 'wstr', '{1D5BE4B5-FA4A-452D-9CDD-5DB35105E7EB}', 'ptr', DllStructGetPtr($tParam, 2))
If (@error) Or ($Ret[0]) Then
$tParam = 0
EndIf
EndSwitch
$pStream = _WinAPI_CreateStreamOnHGlobal()
$Ret = DllCall('gdiplus.dll', 'uint', 'GdipSaveImageToStream', 'ptr', $hImage, 'ptr', $pStream, 'ptr', $pEncoder, 'ptr', DllStructGetPtr($tParam))
If (@error) Or ($Ret[0]) Then
ExitLoop
EndIf
$hMem = _WinAPI_GetHGlobalFromStream($pStream)
$Ret = DllCall('kernel32.dll', 'ulong_ptr', 'GlobalSize', 'ptr', $hMem)
If (@error) Or (Not $Ret[0]) Then
ExitLoop
EndIf
$Length = $Ret[0]
$Ret = DllCall('kernel32.dll', 'ptr', 'GlobalLock', 'ptr', $hMem)
If (@error) Or (Not $Ret[0]) Then
ExitLoop
EndIf
$pBuffer = __HeapReAlloc($pBuffer, $Length, 1)
If Not @error Then
If _WinAPI_MoveMemory($pBuffer, $Ret[0], $Length) Then
$Error = 0
EndIf
EndIf
Until 1
If $pStream Then
_WinAPI_ReleaseStream($pStream)
EndIf
If $hImage Then
DllCall('gdiplus.dll', 'uint', 'GdipDisposeImage', 'ptr', $hImage)
EndIf
If $hToken Then
DllCall('gdiplus.dll', 'none', 'GdiplusShutdown', 'ptr', $hToken)
EndIf
If $hSource Then
_WinAPI_DeleteObject($hSource)
EndIf
If $Error Then
Return SetError(1, 0, 0)
EndIf
Return $Length
EndFunc ;==>_WinAPI_CompressBitmapBits