Sign in to follow this  
Followers 0
Andreik

Bitmap processing using raw code

15 posts in this topic

#1 ·  Posted (edited)

I'm trying to process a bitmap (extract red, green, blue channels) using raw machine code but I encounter a problem. The image looks different as would be applied a zoom effect. Here is my code:

#include <GDIPlus.au3>

$sPath = FileOpenDialog("Open",@ScriptDir,"Images (*.bmp;*.png;*.jpeg;*.jpg)",1)
If Not @error Then
    GetChannel($sPath,@ScriptDir & "red.bmp",0)
    GetChannel($sPath,@ScriptDir & "green.bmp",1)
    GetChannel($sPath,@ScriptDir & "blue.bmp",2)
EndIf

Func GetChannel($sInput,$sOutput,$iChannel)
    Local $bCode

    Switch $iChannel
        Case 0  ; Red
            $bCode = '0x8B7424048B4C24088B0666B80000890683C604E2F3B801000000C3'
        Case 1 ; Green
            $bCode = '0x8B7424048B4C24088B06C1E808B400C1E008890683C604E2EFB801000000C3'
        Case 2 ; Blue
            $bCode = '0x8B7424048B4C24088B0688C2B800000000C1E810B4FFC1E01088D0890683C604E2E6B801000000C3'
    EndSwitch

    _GDIPlus_Startup()
    Local $hImage = _GDIPlus_ImageLoadFromFile($sInput)
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)

    Local $hHBitmap = _WinAPI_CreateBitmap($iWidth,$iHeight,1,32)
    Local $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
    _WinAPI_DeleteObject($hHBitmap)

    Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsDrawImage($hContext,$hImage,0,0)
    _GDIPlus_GraphicsDispose($hContext)
    _GDIPlus_ImageDispose($hImage)

    Local $hImage = _GDIPlus_BitmapCloneArea($hBitmap,0,0,$iWidth,$iHeight,$GDIP_PXF32ARGB)
    _GDIPlus_BitmapDispose($hBitmap)

    Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage,0,0,$iWidth,$iHeight,$GDIP_ILMWRITE,$GDIP_PXF32ARGB)
    Local $iStride = DllStructGetData($tBitmapData,"Stride")
    Local $iScan0 = DllStructGetData($tBitmapData,"Scan0")
    Local $tPixelData = DllStructCreate("dword Data[" & (Abs($iStride * $iHeight)) & "]",$iScan0)
    Local $tCodeBuffer = DllStructCreate("byte Code[" & BinaryLen($bCode) & "]")
    DllStructSetData($tCodeBuffer,"Code",$bCode)

    Local $aRet = DllCall("user32.dll", "ptr","CallWindowProcW","ptr",DllStructGetPtr($tCodeBuffer), _
                                        "ptr",DllStructGetPtr($tPixelData),"int",$iWidth * $iHeight,"int",0,"int",0)

    _GDIPlus_BitmapUnlockBits($hImage,$tBitmapData)
    _GDIPlus_ImageSaveToFile($hImage,$sOutput)
    _GDIPlus_BitmapDispose($hImage)
    _GDIPlus_Shutdown()
EndFunc

For blue channel, for example, I used this code:

mov esi,dword[esp+4]    ; PixelData 
mov ecx,dword[esp+8]    ; Width * Height (pixels number)    
NextPixel:              
mov eax,[esi]           ; mov in eax one pixel
mov dl,al               ; save blue color in dl
mov eax,0               ; eax = 0
shr eax,16              ; shift eax 16 bits to right
mov ah,255              ; mov in ah alpha channel
shl eax,16              ; shift eax 16 bits to left
mov al,dl               ; mov in al blue color
mov [esi],eax           ; save pixel
add esi,4               ; esi += 4
loop NextPixel          ; if ecx> 0 them jump to next pixel; ecx -= 1
mov eax,1               ; eax = 1
ret                     ; return

Just select an image to see about what I am talking about. Have anyone any idea why is this strange behavior?

LE: Seems to work correctly with bitmaps but wrong with jpegs, so the problem could be somewhere in using GDI+.

Edited by Andreik

When the words fail... music speaks

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

bmps and jpgs are working for me.

600 x 600.bmp

600 x 600.jpg

are resulting in 600x600 red, green, blue bmps that look identical aside from the shading.

32bit Windows XP

64bit chip

I tried to help. I'm sure this will be nice for me to have in the future thanks.

edit: tested gif, bmp, jpg, png success

Edited by Xandy

Share this post


Link to post
Share on other sites

For me too some of them but not all. Can be seen two cases:

#1

Original:

Posted Image

Any channel

Posted Image

#2

Original

Posted Image

Any channel

Posted Image

I have Win XP x64 but I don't think this is the problem.


When the words fail... music speaks

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

about the asm code;

you don't decrease ecx and test when you process the last pixel

'shl' means shift left not rotate it shift the bits to the left and add zeros to the right

better use 'rol' and 'ror'

'loop' is slow better use a conditional jmp with ecx

Kind Regards

jpam

edit;

sorry 'loop' decrements ecx

Edited by jpam

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Thanks jpam for feedback. Actually I wanted to say shift not rotate and I was aware at them but the main problem seems remain.

Edited by Andreik

When the words fail... music speaks

Share this post


Link to post
Share on other sites

#6 ·  Posted (edited)

At color integrity, bmps good, jpgs bad. Maybe you can over come this problem. I don't know how jpgs compress. When I use a transparent color key (C++/SDL). I cannot use jpg or my solid colors will become a blend of similar colors. The lesson for me was to always use bmp for source pixel information.

Edited by Xandy

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Here another method using GDI+ library only:

#include <screencapture.au3>
Opt("MustDeclareVars", 1)

_GDIPlus_Startup()

Global Const $iW = @DesktopWidth / 3
Global Const $iH = @DesktopHeight / 2
Global Const $hGUI = GUICreate("", @DesktopWidth, $iH)

Global Const $hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)
Global Const $hBmp = _ScreenCapture_Capture("", 0, 0, $iW, $iH, False)

Global Const $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBmp)

Global Const $hIA_Red = _GDIPlus_ImageAttributesCreate()
Global Const $hIA_Green = _GDIPlus_ImageAttributesCreate()
Global Const $hIA_Blue = _GDIPlus_ImageAttributesCreate()

Global $tColorMatrix_Red =  _GDIPlus_ColorMatrixCreateScale(1.0, 0.0, 0.0 )
Global Const $pColorMatrix_Red = DllStructGetPtr($tColorMatrix_Red)
_GDIPlus_ImageAttributesSetColorMatrix($hIA_Red, 0, True, $pColorMatrix_Red)

Global $tColorMatrix_Green =  _GDIPlus_ColorMatrixCreateScale(0.0, 1.0, 0.0 )
Global Const $pColorMatrix_Green = DllStructGetPtr($tColorMatrix_Green)
_GDIPlus_ImageAttributesSetColorMatrix($hIA_Green, 0, True, $pColorMatrix_Green)

Global $tColorMatrix_Blue =  _GDIPlus_ColorMatrixCreateScale(0.0, 0.0, 1.0 )
Global Const $pColorMatrix_Blue = DllStructGetPtr($tColorMatrix_Blue)
_GDIPlus_ImageAttributesSetColorMatrix($hIA_Blue, 0, True, $pColorMatrix_Blue)

GUISetState()

_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hBitmap, 0, 0, $iW, $iH, 0, 0, $iW, $iH, $hIA_Red)
_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hBitmap, 0, 0, $iW, $iH, $iW, 0, $iW, $iH, $hIA_Green)
_GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hBitmap, 0, 0, $iW, $iH, $iW * 2, 0, $iW, $iH, $hIA_Blue)

Do
Until GUIGetMsg() = 0xFFFFFFFD

_GDIPlus_ImageAttributesDispose($hIA_Red)
_GDIPlus_ImageAttributesDispose($hIA_Green)
_GDIPlus_ImageAttributesDispose($hIA_Blue)
_WinAPI_DeleteObject($hBmp)
_GDIPlus_ImageDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()

Exit

Func _GDIPlus_ImageAttributesCreate()
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateImageAttributes", "int*", 0)
    If @error Then Return SetError(@error, @extended, 0)
    Return $aResult[1]
EndFunc   ;==>_GDIPlus_ImageAttributesCreate

Func _GDIPlus_ImageAttributesDispose($hImageAttributes)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipDisposeImageAttributes", "hwnd", $hImageAttributes)
    If @error Then Return SetError(@error, @extended, False)
    Return $aResult[0] = 0
EndFunc   ;==>_GDIPlus_ImageAttributesDispose

Func _GDIPlus_ImageAttributesSetColorMatrix($hImageAttributes, $iColorAdjustType = 0, $fEnable = False, $pClrMatrix = 0, $pGrayMatrix = 0, $iColorMatrixFlags = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipSetImageAttributesColorMatrix", "handle", $hImageAttributes, "int", $iColorAdjustType, "int", $fEnable, "ptr", $pClrMatrix, "ptr", $pGrayMatrix, "int", $iColorMatrixFlags)
    If @error Then Return SetError(@error, @extended, False)
    Return $aResult[0] = 0
EndFunc   ;==>_GDIPlus_ImageAttributesSetColorMatrix

Func _GDIPlus_ColorMatrixCreateScale($nRed, $nGreen, $nBlue, $nAlpha = 1)
    Local Const $tagGDIPCOLORMATRIX = "float m[25];"
    Local $tCM
    $tCM = DllStructCreate($tagGDIPCOLORMATRIX)
    DllStructSetData($tCM, "m", $nRed, 1)
    DllStructSetData($tCM, "m", $nGreen, 7)
    DllStructSetData($tCM, "m", $nBlue, 13)
    DllStructSetData($tCM, "m", $nAlpha, 19)
    DllStructSetData($tCM, "m", 1, 25)
    Return $tCM
EndFunc   ;==>_GDIPlus_ColorMatrixCreateScale

Func _GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hImage, $nSrcX, $nSrcY, $nSrcWidth, $nSrcHeight, $nDstX, $nDstY, $nDstWidth, $nDstHeight, $hImageAttributes = 0, $iUnit = 2)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawImageRectRect", "handle", $hGraphics, "handle", $hImage, "float", $nDstX, "float", _
            $nDstY, "float", $nDstWidth, "float", $nDstHeight, "float", $nSrcX, "float", $nSrcY, "float", $nSrcWidth, "float", _
            $nSrcHeight, "int", $iUnit, "handle", $hImageAttributes, "int", 0, "int", 0)
    If @error Then Return SetError(@error, @extended, False)
    Return $aResult[0] = 0
EndFunc   ;==>_GDIPlus_GraphicsDrawImageRectRectIA

And your code shortened:

#include <GDIPlus.au3>

$sPath = FileOpenDialog("Open",@ScriptDir,"Images (*.bmp;*.png;*.jpeg;*.jpg)",1)
If Not @error Then
    GetChannel($sPath,@ScriptDir & "red.bmp",0)
    GetChannel($sPath,@ScriptDir & "green.bmp",1)
    GetChannel($sPath,@ScriptDir & "blue.bmp",2)
EndIf

Func GetChannel($sInput,$sOutput,$iChannel)
    Local $bCode

    Switch $iChannel
        Case 0  ; Red
            $bCode = '0x8B7424048B4C24088B0666B80000890683C604E2F3B801000000C3'
        Case 1 ; Green
            $bCode = '0x8B7424048B4C24088B06C1E808B400C1E008890683C604E2EFB801000000C3'
        Case 2 ; Blue
            $bCode = '0x8B7424048B4C24088B0688C2B800000000C1E810B4FFC1E01088D0890683C604E2E6B801000000C3'
    EndSwitch

    _GDIPlus_Startup()
    Local $hImage = _GDIPlus_ImageLoadFromFile($sInput)
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)

    Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage,0,0,$iWidth,$iHeight,$GDIP_ILMWRITE,$GDIP_PXF32ARGB)
    Local $iStride = DllStructGetData($tBitmapData,"Stride")
    Local $iScan0 = DllStructGetData($tBitmapData,"Scan0")
    Local $tPixelData = DllStructCreate("dword Data[" & (Abs($iStride * $iHeight)) & "]",$iScan0)
    Local $tCodeBuffer = DllStructCreate("byte Code[" & BinaryLen($bCode) & "]")
    DllStructSetData($tCodeBuffer,"Code",$bCode)

    Local $aRet = DllCall("user32.dll", "ptr","CallWindowProcW","ptr",DllStructGetPtr($tCodeBuffer), _
                                        "ptr",DllStructGetPtr($tPixelData),"int",$iWidth * $iHeight,"int",0,"int",0)

    _GDIPlus_BitmapUnlockBits($hImage,$tBitmapData)
    _GDIPlus_ImageSaveToFile($hImage,$sOutput)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
EndFunc

Br,

UEZ

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

#9 ·  Posted (edited)

See if changing,

Local $tPixelData = DllStructCreate("dword Data[" & (Abs($iStride * $iHeight)) & "]",$iScan0)

to

Local $tPixelData = DllStructCreate("byte Data[" & (Abs($iStride * $iHeight * 4)) & "]", $iScan0)

makes a difference.

Edit: I am referring to the first script in the first post.

Edited by Malkey

Share this post


Link to post
Share on other sites

Hi,

if you want to "filter" colors from a pixel, use the AND/OR/XOR -Assemblerinstructions

Your filtercode could be written this way:

Func _asm()
    _("use32")
    _("mov esi,[esp+4]")    ;pointer to bitmap
    _("mov ecx,[esp+8]")    ;number of pixel=loopcounter and adresscounter
    _("sub ecx,1")        ;we count from 0 to NumberOfPixel-1
    _("schleife:")        ;loop until ecx=0
    _("mov eax,[esi+ecx*4]");read pixel at address
    _("")
    _("and eax,0xFFFF0000") ;AARRGGBB, so Alpha and red channel are filtered
    ;   _("and eax,0x00FF0000");AARRGGBB, only red channel is filtered
    ;   _("or eax,0xFF000000");if you want alpha=255
    _("")
    _("mov [esi+ecx*4],eax");write pixel to address
    _("sub ecx,1")        ;decrement counter
    _("jnz schleife")      ;jump if counter is NotZero
    _("ret")
EndFunc            ;==>_asm

I would make a function with a colorfilter-parameter..

mov ebx,[esp+12]   ;Filtercode i.E. 0x000000FF for blue
....
and eax,ebx  ;filters ebx
...

If you want to develop Assemblercode with AutoIt you can easily use AssembleIt, now with Debugger and a integrated function to generate the CallWindowProc()-code

#include <GDIPlus.au3>
#include <assembleit.au3>
$sPath = FileOpenDialog("Open",@ScriptDir,"Images (*.bmp;*.png;*.jpeg;*.jpg)",1)
If Not @error Then
    GetChannel($sPath,@ScriptDir & "\red.bmp",0)
    GetChannel($sPath,@ScriptDir & "\green.bmp",1)
    GetChannel($sPath,@ScriptDir & "\blue.bmp",2)
EndIf
shellexecute("red.bmp")
Func _asm()
    _("use32")
;   _("org " & FasmGetBasePtr($Fasm)) ;für den debugger
_("mov esi,[esp+4]")
_("mov ecx,[esp+8]")
_("sub ecx,1")
_("schleife:")
_("mov eax,[esi+ecx*4]");read pixel
_("")
;   _asmdbg_()
_("and eax,0xFFFF0000");AARRGGBB, so Alpha and red channel are filtered
_("")
_("mov [esi+ecx*4],eax");write pixel
_("sub ecx,1")
_("jnz schleife")
_("ret")
endfunc
Func GetChannel($sInput,$sOutput,$iChannel)
    Local $bCode
    Switch $iChannel
        Case 0  ; Red
            $bCode = '0x8B7424048B4C24088B0666B80000890683C604E2F3B801000000C3'
        Case 1 ; Green
            $bCode = '0x8B7424048B4C24088B06C1E808B400C1E008890683C604E2EFB801000000C3'
        Case 2 ; Blue
            $bCode = '0x8B7424048B4C24088B0688C2B800000000C1E810B4FFC1E01088D0890683C604E2E6B801000000C3'
    EndSwitch
    _GDIPlus_Startup()
    Local $hImage = _GDIPlus_ImageLoadFromFile($sInput)
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)
    Local $hHBitmap = _WinAPI_CreateBitmap($iWidth,$iHeight,1,32)
    Local $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)
    _WinAPI_DeleteObject($hHBitmap)
    Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsDrawImage($hContext,$hImage,0,0)
    _GDIPlus_GraphicsDispose($hContext)
    _GDIPlus_ImageDispose($hImage)
    Local $hImage = _GDIPlus_BitmapCloneArea($hBitmap,0,0,$iWidth,$iHeight,$GDIP_PXF32ARGB)
    _GDIPlus_BitmapDispose($hBitmap)
    Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage,0,0,$iWidth,$iHeight,$GDIP_ILMWRITE,$GDIP_PXF32ARGB)
    Local $iStride = DllStructGetData($tBitmapData,"Stride")
    Local $iScan0 = DllStructGetData($tBitmapData,"Scan0")
    Local $tPixelData = DllStructCreate("dword Data[" & (Abs($iStride * $iHeight)) & "]",$iScan0)
    Local $tCodeBuffer = DllStructCreate("byte Code[" & BinaryLen($bCode) & "]")
    DllStructSetData($tCodeBuffer,"Code",$bCode)
;$_ASSEMBLEIT_FLAG=0  ;uncomment to generate CallWindowProc()-code
$return = _assembleit("int", "_asm", "ptr",DllStructGetPtr($tPixelData),"int",$iWidth * $iHeight)
    ;Local $aRet = DllCall("user32.dll", "ptr","CallWindowProcW","ptr",DllStructGetPtr($tCodeBuffer), "ptr",DllStructGetPtr($tPixelData),"int",$iWidth * $iHeight,"int",0,"int",0)
    _GDIPlus_BitmapUnlockBits($hImage,$tBitmapData)
    _GDIPlus_ImageSaveToFile($hImage,$sOutput)
    _GDIPlus_BitmapDispose($hImage)
    _GDIPlus_Shutdown()
EndFunc

Share this post


Link to post
Share on other sites

Thanks guys! Combining all suggestions:

Func GetChannel($sInput,$sOutput,$iChannel)
    Local $bCode

    Switch $iChannel
        Case 0
            $bCode = '0x8B7424048B4C240885C9741081260000FF0083C6044985C975F2EB07B800000000EB05B801000000C3'
        Case 1
            $bCode = '0x8B7424048B4C240885C97410812600FF000083C6044985C975F2EB07B800000000EB05B801000000C3'
        Case 2
            $bCode = '0x8B7424048B4C240885C974108126FF00000083C6044985C975F2EB07B800000000EB05B801000000C3'
        Case 3
            $bCode = '0x8B7424048B4C240885C97410812600FFFF0083C6044985C975F2EB07B800000000EB05B801000000C3'
        Case 4
            $bCode = '0x8B7424048B4C240885C974108126FFFF000083C6044985C975F2EB07B800000000EB05B801000000C3'
        Case 5
            $bCode = '0x8B7424048B4C240885C974108126FF00FF0083C6044985C975F2EB07B800000000EB05B801000000C3'
    EndSwitch

    _GDIPlus_Startup()
    Local $hImage = _GDIPlus_ImageLoadFromFile($sInput)
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)

    Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage,0,0,$iWidth,$iHeight,$GDIP_ILMWRITE,$GDIP_PXF32ARGB)
    Local $iStride = DllStructGetData($tBitmapData,"Stride")
    Local $iScan0 = DllStructGetData($tBitmapData,"Scan0")
    Local $tPixelData = DllStructCreate("dword Data[" & (Abs($iStride * $iHeight)) & "]",$iScan0)
    Local $tCodeBuffer = DllStructCreate("byte Code[" & BinaryLen($bCode) & "]")
    DllStructSetData($tCodeBuffer,"Code",$bCode)

    Local $aRet = DllCall("user32.dll", "ptr","CallWindowProcW","ptr",DllStructGetPtr($tCodeBuffer), _
                                        "ptr",DllStructGetPtr($tPixelData),"int",$iWidth * $iHeight,"int",0,"int",0)

    _GDIPlus_BitmapUnlockBits($hImage,$tBitmapData)
    _GDIPlus_ImageSaveToFile($hImage,$sOutput)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()

    Return ($aRet[0] = 1)
EndFunc

When the words fail... music speaks

Share this post


Link to post
Share on other sites

Really nice script! Glad to be able to add my 2 cents too ;)...

#include <GDIPlus.au3>
#include <Memory.au3>

$sFile = StringLeft(@AutoItExe, StringInStr(@AutoItExe, "", 0, -1)) & "ExamplesGUImerlin.gif"
_GetChannel($sFile, @ScriptDir & "merlin.bmp", 4)

Func _GetChannel($sInput, $sOutput, $iChannel = 0)

    Local $bCode = '0x8B7424048B4C240885C974108126', $b_GDI_Running = True
    Switch $iChannel
        Case 0
            $bCode &= '0000FF00' ; Red
        Case 1
            $bCode &= '00FF0000' ; Green
        Case 2
            $bCode &= 'FF000000' ; Blue
        Case 3
            $bCode &= '00FFFF00' ; Yellow
        Case 4
            $bCode &= 'FFFF0000' ; Cyan
        Case 5
            $bCode &= 'FF00FF00' ; Magenta
    EndSwitch
    $bCode &= '83C6044985C975F2EB07B800000000EB05B801000000C3'

    If Not $giGDIPRef Then
        $b_GDI_Running = False
        _GDIPlus_Startup()
    EndIf

    Local $hImage = _GDIPlus_ImageLoadFromFile($sInput)
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)

    Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iWidth, $iHeight, $GDIP_ILMWRITE, $GDIP_PXF32ARGB)
    Local $iStride = DllStructGetData($tBitmapData, "Stride")
    Local $iScan0 = DllStructGetData($tBitmapData, "Scan0")
    Local $tPixelData = DllStructCreate("dword Data[" & (Abs($iStride * $iHeight)) & "]", $iScan0)

    Local $pCodeBuffer = _MemVirtualAlloc(0, BinaryLen($bCode), $MEM_COMMIT, $PAGE_EXECUTE_READWRITE) ; Allocate memory to prevent DEP issues

    Local $tCodeBuffer = DllStructCreate("byte Code[" & BinaryLen($bCode) & "]", $pCodeBuffer)
    DllStructSetData($tCodeBuffer, "Code", $bCode)

    Local $aRet = DllCall("user32.dll", "ptr", "CallWindowProcW", "ptr", DllStructGetPtr($tCodeBuffer), _
            "ptr", DllStructGetPtr($tPixelData), "int", $iWidth * $iHeight, "int", 0, "int", 0)

    _MemVirtualFree($pCodeBuffer, BinaryLen($bCode), $MEM_DECOMMIT)

    _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
    _GDIPlus_ImageSaveToFile($hImage, $sOutput)
    _GDIPlus_ImageDispose($hImage)

    If Not $b_GDI_Running Then _GDIPlus_Shutdown()

    Return ($aRet[0] = 1)
EndFunc   ;==>_GetChannel

Share this post


Link to post
Share on other sites

Why CallWindowProc and not DllCallAddress?


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

No important reason, just because on this PC I have the old version of AutoIt and DllCallAddress it's available just for Beta version. ;)

Using DllCallAddress & KaFu additions:

Global Const $CH_RED = '0000FF00'
Global Const $CH_GREEN = '00FF0000'
Global Const $CH_BLUE = 'FF000000'
Global Const $CH_YELLOW = '00FFFF00'
Global Const $CH_CYAN = 'FFFF0000'
Global Const $CH_MAGENTA = 'FF00FF00'

Func GetChannel($sInput,$sOutput,$sChannel)
    Local $b_GDI_Running
    Local $bCode = '0x8B7424048B4C240885C974108126' & $sChannel & '83C6044985C975F2EB07B800000000EB05B801000000C3'
    Local $iSize = BinaryLen($bCode)

    If Not $giGDIPRef Then
        $b_GDI_Running = False
        _GDIPlus_Startup()
    EndIf

    Local $hImage = _GDIPlus_ImageLoadFromFile($sInput)
    Local $iWidth = _GDIPlus_ImageGetWidth($hImage)
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage)

    Local $tBitmapData = _GDIPlus_BitmapLockBits($hImage,0,0,$iWidth,$iHeight,$GDIP_ILMWRITE,$GDIP_PXF32ARGB)
    Local $iStride = DllStructGetData($tBitmapData,"Stride")
    Local $iScan0 = DllStructGetData($tBitmapData,"Scan0")
    Local $tPixelData = DllStructCreate("dword Data[" & (Abs($iStride * $iHeight)) & "]",$iScan0)
    Local $pCodeBuffer = _MemVirtualAlloc(0,$iSize,$MEM_COMMIT,$PAGE_EXECUTE_READWRITE)
    Local $tCodeBuffer = DllStructCreate("byte Code[" & $iSize & "]",$pCodeBuffer)
    DllStructSetData($tCodeBuffer,"Code",$bCode)

    Local $aRet = DllCallAddress("int:cdecl",$pCodeBuffer,"ptr",DllStructGetPtr($tPixelData),"int",$iWidth * $iHeight)

    _MemVirtualFree($pCodeBuffer,$iSize,$MEM_DECOMMIT)
    _GDIPlus_BitmapUnlockBits($hImage,$tBitmapData)
    _GDIPlus_ImageSaveToFile($hImage,$sOutput)
    _GDIPlus_ImageDispose($hImage)

    If Not $b_GDI_Running Then _GDIPlus_Shutdown()

    Return ($aRet[0] = 1)
EndFunc
Edited by Andreik

When the words fail... music speaks

Share this post


Link to post
Share on other sites

Aha.

DllCallAddress is standard AutoIt function since 3.3.8.0.


♡♡♡

.

eMyvnE

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0