Jump to content

pixelsearch on image


faustf
 Share

Recommended Posts

the  code is inside the link

<childish rant removed>

;
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <Misc.au3>
; http://www.autoitscript.com/forum/index.php?s=&showtopic=91755&view=findpost&p=663576
Opt('MustDeclareVars', 1)

Global $width, $height, $hGUI1, $hGUI2, $hImage, $hImage2, $hGraphic1, $hGraphic2, $iX, $iY, $fname

_Main()

Func _Main()
    $fname = FileOpenDialog("Select image", @DesktopCommonDir, "All images (*.jpg;*.png;*.gif;*.bmp;)", 1, "boxTest.jpg")
    If $fname = "" Then Exit
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile($fname)
    $iX = _GDIPlus_ImageGetWidth($hImage)
    $iY = _GDIPlus_ImageGetHeight($hImage)

    ; Create a GUI for the original image
    $hGUI1 = GUICreate("Original", $iX + 5, $iY, 0, 0)
    GUISetState()

    ; Create a GUI for the zoomed image
    $hGUI2 = GUICreate("Ctrl + Left click to save image", $iX + 5, $iY, 0, 400)
    GUISetState()
    GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    ; Initialize GDI+ library and load image

    ; Draw original image
    $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND($hGUI1)
    _GDIPlus_GraphicsDrawImage($hGraphic1, $hImage, 0, 0)

    ; ====== Examples calling _ImageColorRegExpReplace() =========================
    ; Note colour format hex 0xBBGGRRAA - Blue, Green, Red, Alpha (transparency)

    $hImage2 = _ImageColorRegExpReplace($hImage, "(FF577678", "000000FF"); Change white to black.
   ; $hImage2 = _ImageColorRegExpReplace($hImage, "(?i)([E-F][0-9A-F]){3}FF", "000000FF"); Change almost white to black.

    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(000000FF)" , "FFFFFFFF" ); Change black to white
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(FFFFFFFF)" , "FFFFFF00" ); Change white to transparent
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(([E-F][0-9A-F]){3})(FF)" , "${1}00" ); Change near to white to transparent
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(577678)", "000000FF"); Change blue, off red, white to black

    ;Swap red and blue channels on half the image. Image is 400x300 = 120,000 pixels. Number of pixels to replace is 60,000.
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})(FF)", "${3}${2}${1}${4}", 60000)

    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(([0-9A-F]){6})(FF)" , "0000FFFF" ); Change near to white to transparent

    ;==============================================================================================

    ; Draw RegExpReplace image
    $hGraphic2 = _GDIPlus_GraphicsCreateFromHWND($hGUI2)
    _GDIPlus_GraphicsDrawImage($hGraphic2, $hImage2, 0, 0)
    ;$hImage3 = _GDIPlus_BitmapCreateFromHBITMAP ($hImage2)
    ConsoleWrite("$hImage2 " & $hImage2 & @CRLF)


    ; Clean up screen shot file
    ;FileDelete(@MyDocumentsDir & "\GDIPlus_Image.jpg")

    ; Loop until user exits
    Do
        If _IsPressed("01") And _IsPressed("11") Then ;Left click + Ctrl key to save image
            Do
            Until Not _IsPressed("01")
            Local $PathFile = FileSaveDialog("Choose a name.", @ScriptDir & "\", "Images (*.bmp;*.jpg;*.png;*.gif)|All files (*.*)", 16, "ColourModify.png")
            If Not @error Then
                _GDIPlus_ImageSaveToFile($hImage2, @ScriptDir & "\ColMod.png")
                ShellExecute(@ScriptDir & "\ColMod.png")
            EndIf
        EndIf
        Sleep(10)
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    ; Release resources
    _GDIPlus_GraphicsDispose($hGraphic1)
    _GDIPlus_GraphicsDispose($hGraphic2)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_ImageDispose($hImage2)
    _GDIPlus_Shutdown()
EndFunc ;==>_Main

; ========= _ImageColorRegExpReplace($hImage, $iColSrch, $iColNew,$iCount = 0) =====================
;Paramerers:-
; $hImage - Handle to a Bitmap object
; $iColSrch - A regular expression pattern to compare the colours to in 0xBBGGRRAA hex colour format.
; $iColNew - The colour which will replace the regular expression matching colour.Also in 0xBBGGRRAA hex colour format.
; $iCount - [optional] The number of times to execute the replacement in the image. The default is 0. Use 0 for global replacement.
; Note :- Colour format in hex 0xBBGGRRAA
;
Func _ImageColorRegExpReplace($hImage, $iColSrch, $iColNew, $iCount = 0)
    Local $Reslt, $stride, $format, $Scan0, $iIW, $iIH, $hBitmap1
    Local $v_BufferA, $AllPixels, $sREResult1, $sResult

    $iIW = _GDIPlus_ImageGetWidth($hImage)
    $iIH = _GDIPlus_ImageGetHeight($hImage)

    $hBitmap1 = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iIW, $iIH, $GDIP_PXF32ARGB)

    ; Locks a portion of a bitmap for reading or writing
    $Reslt = _GDIPlus_BitmapLockBits($hBitmap1, 0, 0, $iIW, $iIH, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB)

    ;Get the returned values of _GDIPlus_BitmapLockBits ()
    $width = DllStructGetData($Reslt, "width")
    $height = DllStructGetData($Reslt, "height")
    $stride = DllStructGetData($Reslt, "stride")
    $format = DllStructGetData($Reslt, "format")
    $Scan0 = DllStructGetData($Reslt, "Scan0")

    $v_BufferA = DllStructCreate("byte[" & $height * $width * 4 & "]", $Scan0) ; Create DLL structure for all pixels
    $AllPixels = DllStructGetData($v_BufferA, 1)
    ;ConsoleWrite("$AllPixels, raw data, first 9 colours = " & StringRegExpReplace($AllPixels, "(.{98})(.*)", "\1") & @CRLF)

    ; Searches on this string - $sREResult1 whch has the prefix "0x" removed and a space put between pixels 8 characters long.
    $sREResult1 = StringRegExpReplace(StringTrimLeft($AllPixels, 2), "(.{8})", "\1 ")
    ;ConsoleWrite("$sREResult1 first 9 colours = " & StringRegExpReplace($sREResult1, "(.{81})(.*)", "\1") & @CRLF)

    If StringInStr($iColNew, "0x") > 0 Then $iColNew = StringReplace($iColNew, "0x", ""); Remove "0x" not needed

    ; StringRegExpReplace performed and white spaces removed
    $sResult = StringStripWS(StringRegExpReplace($sREResult1, $iColSrch, $iColNew, $iCount), 8)

    ; Replace "0x" prefix and set modified data back to DLL structure, $v_BufferA
    DllStructSetData($v_BufferA, 1, "0x" & $sResult)
    _GDIPlus_BitmapUnlockBits($hBitmap1, $Reslt) ; releases the locked region

    Return $hBitmap1
EndFunc ;==>_ImageColorRegExpReplace

Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGUI1 Then _GDIPlus_GraphicsDrawImageRect($hGraphic1, $hImage, 0, 0, $width, $height)
    If $hWnd = $hGUI2 Then _GDIPlus_GraphicsDrawImageRect($hGraphic2, $hImage2, 0, 0, $width, $height)
    Return $GUI_RUNDEFMSG
EndFunc ;==>MY_PAINT
;

 

Edited by JLogan3o13
Link to comment
Share on other sites

You are missing a parenthesis ")".  Look carefully the code I gave you.  You need to have the right balance of parenthesis.  Also there is not a color with 00000000, well it exists but I don't believe no one is using it. As the alpha part is 00, it is rarely use unless you want to create some transparency effect.  The code you found is right. 

I was not trying to be rude when I asked you to provide code.  But after few decades of programming, I know that computers are rarely wrong but humans ? Not so sure...

Link to comment
Share on other sites

This _ImageColorRegExpReplace() function matches and replaces raw pixels from an image file in the raw hex format of BBGGRRAA.  Where B,G,R,and A (Blue, Green, Red, and Alpha) represent the four  8 bit colour channels with 0 to 0xFF hexadecimal values (0 - 255).  (eg 0000FFFF is fully opaque red)

When using _GDIPlus_ functions, the hex colour format is 0xAARRGGBB.  Where 0xFFFF0000 is fully opaque red.  

To view transparency in an image, I found loading the image into GIMP (GNU Image Manipulation Program) is excellent as a diagonal checker board pattern background indicates the transparency within the image.

This following script produces a test image "ColorHLines1.png" which, if used, makes changes made by the example _ImageColorRegExpReplace() functions easier to see.

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>
#include <Array.au3>
#include <GDIPlus.au3>

Local $sReturnFileName = @ScriptDir & "\ColorHLines1.png"

If FileExists($sReturnFileName) Then FileDelete($sReturnFileName)
_ImageFileCreate($sReturnFileName)
;ShellExecute($sReturnFileName)


Func _ImageFileCreate($sFileName)
    Local $aArray = [["0xFF000000", "Black"], _
            ["0xFFFFFFFF", "White"], _
            ["0x80FF0000", "Red"], _ ; <-- Alpha channel 0x80 partly transparent.
            ["0xFF00FF00", "Green / Lime"], _
            ["0xFF0000FF", "Blue"], _
            ["0xFFFFFF00", "Yellow"], _
            ["0xFF00FFFF", "Cyan / Aqua"], _
            ["0xFFFF00FF", "Magenta / Fuchsia"], _
            ["0x00FFFFFF", "Fully transparent"], _
            ["0x01FFFFFF", "Mostlly transparent"]]
    _GDIPlus_Startup()
    Local $hPen
    Local $iLW = 60, _ ; Width of coloured line in image
            $iWidth = 400, _
            $iHeight = $iLW * UBound($aArray), _
            $hImage = _GDIPlus_BitmapCreateFromScan0($iWidth, $iHeight), _
            $hGfx = _GDIPlus_ImageGetGraphicsContext($hImage), _
            $hGUI = GUICreate("Test", $iWidth, $iHeight, 20, 20)
    GUISetState()
    _GDIPlus_GraphicsSetSmoothingMode($hGfx, 0)

    For $i = 0 To UBound($aArray) - 1
        $hPen = _GDIPlus_PenCreate($aArray[$i][0], $iLW) ;change the pen size accordingly
        _GDIPlus_GraphicsDrawLine($hGfx, 0, $iLW / 2 + ($iLW * ($i)), $iWidth, $iLW / 2 + ($iLW * ($i)), $hPen)
        _AddText2Img($hImage, $aArray[$i][0] & " " & $aArray[$i][1], 80, 6 + ($iLW * ($i)))
    Next

    Local $hCanvas = _GDIPlus_GraphicsCreateFromHWND($hGUI)
    $hBrush = _GDIPlus_HatchBrushCreate(4, 0x10000000, 0x00000000)
    _GDIPlus_GraphicsFillRect($hCanvas, 0, 0, $iWidth, $iHeight, $hBrush)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDrawImageRect($hCanvas, $hImage, 0, 0, $iWidth, $iHeight)
    _GDIPlus_ImageSaveToFile($hImage, $sFileName)
    Do
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    _GDIPlus_PenDispose($hPen)
    _GDIPlus_GraphicsDispose($hGfx)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
EndFunc   ;==>_ImageFileCreate

; By UEZ:  https://www.autoitscript.com/forum/topic/196831-need-help-adding-text-atop-a-gdi-object/?do=findComment&comment=1411659
Func _AddText2Img($hImage, $sText, $iX = 50, $iY = 3, $sFontName = "Comic Sans MS", $fSize = 12, $iColor = 0xFF000000)
    Local Const $hBrushW = _GDIPlus_BrushCreateSolid(0xFFFFFFFF)
    Local Const $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage)
    _GDIPlus_GraphicsSetSmoothingMode($hGraphic, 4)
    _GDIPlus_GraphicsSetTextRenderingHint($hGraphic, 3)
    Local Const $hBrush = _GDIPlus_BrushCreateSolid($iColor)
    Local Const $hFormat = _GDIPlus_StringFormatCreate()
    _GDIPlus_StringFormatSetAlign($hFormat, 1) ; Center text horizontally
    Local Const $hFamily = _GDIPlus_FontFamilyCreate($sFontName)
    Local Const $hFont = _GDIPlus_FontCreate($hFamily, $fSize)
    Local Const $aDim = _GDIPlus_ImageGetDimension($hImage)
    Local Const $tLayout = _GDIPlus_RectFCreate($iX, $iY, 245, 25)
    _GDIPlus_GraphicsFillRect($hGraphic, DllStructGetData($tLayout, 1), DllStructGetData($tLayout, 2), DllStructGetData($tLayout, 3), DllStructGetData($tLayout, 4), $hBrushW)
    ;ConsoleWrite(DllStructGetData($tLayout, 1) & "  " & DllStructGetData($tLayout, 2) & "  " & DllStructGetData($tLayout, 3) & "  " & DllStructGetData($tLayout, 4) & @CRLF)
    _GDIPlus_GraphicsDrawStringEx($hGraphic, $sText, $hFont, $tLayout, $hFormat, $hBrush)
    _GDIPlus_FontDispose($hFont)
    _GDIPlus_FontFamilyDispose($hFamily)
    _GDIPlus_StringFormatDispose($hFormat)
    _GDIPlus_BrushDispose($hBrush)
    _GDIPlus_GraphicsDispose($hGraphic)
EndFunc   ;==>_AddText2Img

 

And, this script again with a modified missing closing bracket correction;

Added "ColorHLines1.png" file; and,

Added  new _ImageColorRegExpReplace() examples that find and replace all colours that are not  the 'not colours'.

;
#include <GuiConstantsEx.au3>
#include <GDIPlus.au3>
#include <ScreenCapture.au3>
#include <Misc.au3>
; http://www.autoitscript.com/forum/index.php?s=&showtopic=91755&view=findpost&p=663576
Opt('MustDeclareVars', 1)

Global $width, $height, $hGUI1, $hGUI2, $hImage, $hImage2, $hGraphic1, $hGraphic2, $iX, $iY, $fname

_Main()

Func _Main()
    $fname = "ColorHLines1.png" ; FileOpenDialog("Select image", @DesktopCommonDir, "All images (*.jpg;*.png;*.gif;*.bmp;)", 1, "boxTest.jpg")
    ; $fname = FileOpenDialog("Select image", @DesktopCommonDir, "All images (*.jpg;*.png;*.gif;*.bmp;)", 1, "boxTest.jpg")
    If $fname = "" Then Exit
    _GDIPlus_Startup()
    $hImage = _GDIPlus_ImageLoadFromFile($fname)
    $iX = _GDIPlus_ImageGetWidth($hImage)
    $iY = _GDIPlus_ImageGetHeight($hImage)

    ; Create a GUI for the original image
    $hGUI1 = GUICreate("Original", $iX + 5, $iY, 0, 0)
    GUISetState()

    ; Create a GUI for the zoomed image
    $hGUI2 = GUICreate("Ctrl + Left click to save image", $iX + 5, $iY, 0, 400)
    GUISetState()
    GUIRegisterMsg(0xF, "MY_PAINT") ; Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
    ; Initialize GDI+ library and load image

    ; Draw original image
    $hGraphic1 = _GDIPlus_GraphicsCreateFromHWND($hGUI1)
    _GDIPlus_GraphicsDrawImage($hGraphic1, $hImage, 0, 0)

    ; ====== Examples calling _ImageColorRegExpReplace() =========================
    ; Note colour format hex 0xBBGGRRAA - Blue, Green, Red, Alpha (transparency)

    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(FFFFFFFF)", "000000FF"); Change white to black.
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(?i)([E-F][0-9A-F]){3}FF", "000000FF"); Change almost white to black.

    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(000000FF)" , "FFF;FFFFF" ); Change black to white
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(FFFFFFFF)", "FFFFFF00") ; Change white to transparent
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(([E-F][0-9A-F]){3})(FF)" , "${1}00" ); Change near to white to transparent
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(FF0000FF|0000AAFF|FFFFFFFF)", "000000FF"); Change blue, off red, white to black

    ;Swap red and blue channels on half the image. Image is 400x600 = 240,000 pixels. Number of pixels to replace is half, 120,000.
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})(FF)", "${3}${2}${1}${4}", 120000)

    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(([0-9A-F]){6})(FF)" , "0000FFFF" ); Change near to white to transparent

    ; ------ Not colours added to these examples --------
    $hImage2 = _ImageColorRegExpReplace($hImage, "(?!FFFFFFFF)\b.{8}\b" , "000000FF" ); Change any colour not white to black

    ; Change any colour not white, or any pixel that does nt have FF in the Blue and the Alpha channels, to black.
    ;$hImage2 = _ImageColorRegExpReplace($hImage, "(?!FFFFFFFF|FF[0-9A-F]{4}FF)\b.{8}\b" , "000000FF" ) ; White, blue, cyan, and magenta are not replaced with black.

    ;==============================================================================================

    ; Draw RegExpReplace image
    $hGraphic2 = _GDIPlus_GraphicsCreateFromHWND($hGUI2)
    _GDIPlus_GraphicsDrawImage($hGraphic2, $hImage2, 0, 0)
    ;$hImage3 = _GDIPlus_BitmapCreateFromHBITMAP ($hImage2)
    ConsoleWrite("$hImage2 " & $hImage2 & @CRLF)


    ; Clean up screen shot file
    ;FileDelete(@MyDocumentsDir & "\GDIPlus_Image.jpg")

    ; Loop until user exits
    Do
        If _IsPressed("01") And _IsPressed("11") Then ;Left click + Ctrl key to save image
            Do
            Until Not _IsPressed("01")
            Local $PathFile = FileSaveDialog("Choose a name.", @ScriptDir & "\", "Images (*.bmp;*.jpg;*.png;*.gif)|All files (*.*)", 16, "ColourModify.png")
            If Not @error Then
                _GDIPlus_ImageSaveToFile($hImage2, @ScriptDir & "\ColMod.png")
                ShellExecute(@ScriptDir & "\ColMod.png")
            EndIf
        EndIf
        Sleep(10)
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    ; Release resources
    _GDIPlus_GraphicsDispose($hGraphic1)
    _GDIPlus_GraphicsDispose($hGraphic2)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_ImageDispose($hImage2)
    _GDIPlus_Shutdown()
EndFunc   ;==>_Main

; ========= _ImageColorRegExpReplace($hImage, $iColSrch, $iColNew,$iCount = 0) =====================
;Paramerers:-
; $hImage - Handle to a Bitmap object
; $iColSrch - A regular expression pattern to compare the colours to in 0xBBGGRRAA hex colour format.
; $iColNew - The colour which will replace the regular expression matching colour.Also in 0xBBGGRRAA hex colour format.
; $iCount - [optional] The number of times to execute the replacement in the image. The default is 0. Use 0 for global replacement.
; Note :- Colour format in hex 0xBBGGRRAA
;
Func _ImageColorRegExpReplace($hImage, $iColSrch, $iColNew, $iCount = 0)
    Local $Reslt, $stride, $format, $Scan0, $iIW, $iIH, $hBitmap1
    Local $v_BufferA, $AllPixels, $sREResult1, $sResult

    $iIW = _GDIPlus_ImageGetWidth($hImage)
    $iIH = _GDIPlus_ImageGetHeight($hImage)

    $hBitmap1 = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iIW, $iIH, $GDIP_PXF32ARGB)

    ; Locks a portion of a bitmap for reading or writing
    $Reslt = _GDIPlus_BitmapLockBits($hBitmap1, 0, 0, $iIW, $iIH, BitOR($GDIP_ILMREAD, $GDIP_ILMWRITE), $GDIP_PXF32ARGB)

    ;Get the returned values of _GDIPlus_BitmapLockBits ()
    $width = DllStructGetData($Reslt, "width")
    $height = DllStructGetData($Reslt, "height")
    $stride = DllStructGetData($Reslt, "stride")
    $format = DllStructGetData($Reslt, "format")
    $Scan0 = DllStructGetData($Reslt, "Scan0")

    $v_BufferA = DllStructCreate("byte[" & $height * $width * 4 & "]", $Scan0) ; Create DLL structure for all pixels
    $AllPixels = DllStructGetData($v_BufferA, 1)
    ;ConsoleWrite("$AllPixels, raw data, first 9 colours = " & StringRegExpReplace($AllPixels, "(.{98})(.*)", "\1") & @CRLF)

    ; Searches on this string - $sREResult1 whch has the prefix "0x" removed and a space put between pixels 8 characters long.
    $sREResult1 = StringRegExpReplace(StringTrimLeft($AllPixels, 2), "(.{8})", "\1 ")
    ;ConsoleWrite("$sREResult1 first 9 colours = " & StringRegExpReplace($sREResult1, "(.{81})(.*)", "\1") & @CRLF)

    If StringInStr($iColNew, "0x") > 0 Then $iColNew = StringReplace($iColNew, "0x", "") ; Remove "0x" not needed

    ; StringRegExpReplace performed and white spaces removed
    $sResult = StringStripWS(StringRegExpReplace($sREResult1, $iColSrch, $iColNew, $iCount), 8)

    ; Replace "0x" prefix and set modified data back to DLL structure, $v_BufferA
    DllStructSetData($v_BufferA, 1, "0x" & $sResult)
    _GDIPlus_BitmapUnlockBits($hBitmap1, $Reslt) ; releases the locked region

    Return $hBitmap1
EndFunc   ;==>_ImageColorRegExpReplace

Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
    If $hWnd = $hGUI1 Then _GDIPlus_GraphicsDrawImageRect($hGraphic1, $hImage, 0, 0, $width, $height)
    If $hWnd = $hGUI2 Then _GDIPlus_GraphicsDrawImageRect($hGraphic2, $hImage2, 0, 0, $width, $height)
    Return $GUI_RUNDEFMSG
EndFunc   ;==>MY_PAINT
;

Remember to save the modified image hold down the "Ctrl" key  and press the left mouse button while hovering over the modified image.  The save file dialog window should appear.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...