Jump to content

Change image pixel colors

Recommended Posts

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
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
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
  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...