Jump to content
Sign in to follow this  

Change image pixel colors

Recommended Posts


What im trying to do is change the color of an image.

If the image below had alternating black and white boxes, how do I go about detecting the white pixels and changing them to black ones?

__ __




Share this post

Link to post
Share on other sites

Detecting a pixel color is easy using PixelGetColor()

For changing the image I think you need to read the documentation for GDIplus in the helpfile. I have no experience with that.

Share this post

Link to post
Share on other sites

Thanks Tvern, pointed me in the right direction for the first part :(

Alright, so I have the image saved to my desktop, just a 200x200 box with alternating black/white boxes in it.

I can use the _GDIPlus_GraphicsDrawImage function to capture and save the image to,


How do I scan each pixel of the image and change the color if not black?,

Do While Not currentPixelColor = 0x000000

currentPixelColor = 0xFFFFFF

currentPixel[index-1] = currentPixel[index-1] +1


I realise that isn't right.. but hopefully it helps to explain what I'm trying to do. I wouldn't be suprised if I have wrong logic.

Feel free to point out anything.

Edited by meowbits

Share this post

Link to post
Share on other sites

This is modified from here - 1 year old today. Edit: tomorrow.

Two regular expressions added :-

$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.

The second RegExpReplace replaces slight shades of white.

#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


Func _Main()
    $fname = FileOpenDialog("Select image", @DesktopCommonDir, "All images (*.jpg;*.png;*.gif;*.bmp;)", 1, "boxTest.jpg")
    If $fname = "" Then Exit
    $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)

    ; Create a GUI for the zoomed image
    $hGUI2 = GUICreate("Ctrl + Left click to save image", $iX + 5, $iY, 0, 400)
    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)" , "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, "(FF0000FF|0000AAFF|FFFFFFFF)", "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
        If _IsPressed("01") And _IsPressed("11") Then ;Left click + Ctrl key to save image
            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")
    Until GUIGetMsg() = $GUI_EVENT_CLOSE

    ; Release resources
EndFunc ;==>_Main

; ========= _ImageColorRegExpReplace($hImage, $iColSrch, $iColNew,$iCount = 0) =====================
; $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)
EndFunc ;==>MY_PAINT
Edited by Malkey

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