Jump to content

Proper Way to Invert Colors


Recommended Posts

I've been playing around a bit with the various ways to invert images using AutoIt. A search of the forums has developed several good methods, some faster than others, many using various specialized modules to get the method to work.

I've been playing around with Malkey's script from this thread, and it's fast, but I've noticed it tends to drop information from images.

For example, here's the test image I used:

Posted Image

Here's Malkey's script I used:

#include <WinAPI.au3>
#include <GDIPlus.au3>
#include <GuiConstants.au3>
#include <WindowsConstants.au3>
;#include <Constants.au3>

; http://www.autoitscript.com/forum/index.php?s=&showtopic=77799&view=findpost&p=563657
; http://www.autoitscript.com/forum/index.php?s=&showtopic=86951&view=findpost&p=623855

Opt("GUIOnEventMode", 1);0=disabled, 1=OnEvent mode enabled

Local $Path = FileOpenDialog("Choose Image File", @ScriptDir & "", _
        "Images (*.gif;*.png;*.jpg;*.bmp)| All (*.*)")
If $Path <> "" Then
    _GDIPlus_Startup()
    Local $hImage = _GDIPlus_ImageLoadFromFile($Path)
Else
    Exit
EndIf
Local $iW, $iH
$iW = _GDIPlus_ImageGetWidth($hImage)
$iH = _GDIPlus_ImageGetHeight($hImage)

$hGui = GUICreate("B & W Negative Example", $iW, $iH)
GUISetOnEvent(-3, "_Exit")
GUISetState()

$hGraphicGUI = _GDIPlus_GraphicsCreateFromHWND($hGui)
$hBMPBuff = _GDIPlus_BitmapCreateFromGraphics($iW, $iH, $hGraphicGUI)
$hGraphic = _GDIPlus_ImageGetGraphicsContext($hBMPBuff)
;$hImage = _GDIPlus_ImageLoadFromFile ($FileLoad )
_GDIPlus_GraphicsDrawImage($hGraphic, $hImage, 0, 0)

GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
_GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)

Sleep(2000)

_GDIPlus_GraphicsDrawImageRectRectTrans($hGraphic, $hBMPBuff, 0, 0)
_GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)

Sleep(2000)

$hdc = _WinAPI_GetDC($hGui)
$hcdc = _WinAPI_CreateCompatibleDC($hdc)
$hcbmp = _WinAPI_CreateCompatibleBitmap($hdc, $iW, $iH)

_WinAPI_SelectObject($hcdc, $hcbmp)

_WinAPI_BitBlt($hcdc, 0, 0, $iW, $iH, $hdc, 0, 0, $NOTSRCERASE)

$gc = _GDIPlus_GraphicsCreateFromHDC($hdc)
$bmp = _GDIPlus_BitmapCreateFromHBITMAP($hcbmp)
_GDIPlus_GraphicsDrawImage($hGraphic, $bmp, 0, 0)

;$sFileName = @DesktopDir & "\GDIPlus_Image1.jpg"
;_GDIPlus_ImageSaveToFile($hBMPBuff, $sFileName)
;ShellExecute(@DesktopDir & "\GDIPlus_Image1.jpg")

_GDIPlus_GraphicsDispose($gc)
_GDIPlus_ImageDispose($bmp)

_WinAPI_DeleteObject($hcbmp)
GUIRegisterMsg(0xF, "MY_PAINT"); Register PAINT-Event 0x000F = $WM_PAINT (WindowsConstants.au3)
GUIRegisterMsg(0x85, "MY_PAINT"); $WM_NCPAINT = 0x0085 (WindowsConstants.au3)Restore after Minimize.
_GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)

While 1
    Sleep(100)
WEnd

Func _Exit()
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_GraphicsDispose($hGraphic)
    _GDIPlus_GraphicsDispose($hGraphicGUI)
    _WinAPI_DeleteObject($hBMPBuff)
    _WinAPI_ReleaseDC(0, $hdc)
    _WinAPI_DeleteDC($hcdc)
    _WinAPI_RedrawWindow(0, 0, 0, BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_ALLCHILDREN))
    _GDIPlus_Shutdown()
    Exit
EndFunc  ;==>_Exit

Func MY_PAINT($hWnd, $msg, $wParam, $lParam)
; Check, if the GUI with the Graphic should be repainted
    _GDIPlus_GraphicsDrawImage($hGraphicGUI, $hBMPBuff, 0, 0)
    _WinAPI_RedrawWindow($hGui, "", "", BitOR($RDW_INVALIDATE, $RDW_UPDATENOW, $RDW_FRAME)); , $RDW_ALLCHILDREN
    Return $GUI_RUNDEFMSG
EndFunc  ;==>MY_PAINT

Func _GDIPlus_GraphicsDrawImageRectRectTrans($hGraphics, $hImage, $iSrcX, $iSrcY, $iSrcWidth = "", $iSrcHeight = "", _
        $iDstX = "", $iDstY = "", $iDstWidth = "", $iDstHeight = "", $iUnit = 2, $nTrans = 1)
    Local $tColorMatrix, $x, $hImgAttrib, $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage)
    If $iSrcWidth = 0 Or $iSrcWidth = "" Then $iSrcWidth = $iW
    If $iSrcHeight = 0 Or $iSrcHeight = "" Then $iSrcHeight = $iH
    If $iDstX = "" Then $iDstX = $iSrcX
    If $iDstY = "" Then $iDstY = $iSrcY
    If $iDstWidth = "" Then $iDstWidth = $iSrcWidth
    If $iDstHeight = "" Then $iDstHeight = $iSrcHeight
    If $iUnit = "" Then $iUnit = 2
;;create color matrix data
    $tColorMatrix = DllStructCreate("float[5];float[5];float[5];float[5];float[5]")

; Grey shading
    $x = DllStructSetData($tColorMatrix, 1, 1, 1) * DllStructSetData($tColorMatrix, 1, 1, 2) * DllStructSetData($tColorMatrix, 1, 1, 3) * _
            DllStructSetData($tColorMatrix, 4, $nTrans, 4) * DllStructSetData($tColorMatrix, 5, 0.1, 1) * _
            DllStructSetData($tColorMatrix, 5, 0.1, 2) * DllStructSetData($tColorMatrix, 5, 0.1, 3) * DllStructSetData($tColorMatrix, 5, 1, 5)

    $hImgAttrib = DllCall($ghGDIPDll, "int", "GdipCreateImageAttributes", "ptr*", 0)
    $hImgAttrib = $hImgAttrib[1]
    DllCall($ghGDIPDll, "int", "GdipSetImageAttributesColorMatrix", "ptr", $hImgAttrib, "int", 1, _
            "int", 1, "ptr", DllStructGetPtr($tColorMatrix), "ptr", 0, "int", 0)
;;draw image into graphic object with alpha blend
    DllCall($ghGDIPDll, "int", "GdipDrawImageRectRectI", "hwnd", $hGraphics, "hwnd", $hImage, "int", $iDstX, "int", _
            $iDstY, "int", $iDstWidth, "int", $iDstHeight, "int", $iSrcX, "int", $iSrcY, "int", $iSrcWidth, "int", _
            $iSrcHeight, "int", $iUnit, "ptr", $hImgAttrib, "int", 0, "int", 0)
;;clean up
    DllCall($ghGDIPDll, "int", "GdipDisposeImageAttributes", "ptr", $hImgAttrib)
    Return
EndFunc  ;==>_GDIPlus_GraphicsDrawImageRectRectTrans
;

And here's what came about from the script:

Posted Image

Obviously, there's some data loss on the right side of the image. Is there a preferred method in AutoIt to do this kind of process, or is trial-and-error the only way to go?

Edited by ishldgetoutmore
Link to comment
Share on other sites

Will this help you?

;coded by UEZ
;thanks to Authenticity for GDIP.au3 and the great examples
#include <GDIPlus.au3>
#Include <Misc.au3>

$file = FileOpenDialog("Select image to load", @ScriptDir, "Images (*.jpg;*.png;*.bmp)")

If @error Then Exit

_GDIPlus_Startup()
$hImage = _GDIPlus_ImageLoadFromFile($file)
$scale_factor = 1.0
$iX = _GDIPlus_ImageGetWidth($hImage) * $scale_factor
$iY = _GDIPlus_ImageGetHeight($hImage) * $scale_factor

$hGUI = GUICreate("GDI+: Image to Negative Example", $iX, $iY)
GUISetState()

$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hGUI)

Global $hImageContext, $hBackImage
_Negative()

$dll = DllOpen("user32.dll")

While 1
    Switch GUIGetMsg()
        Case -3
            _GDIPlus_BitmapDispose($hImage)
            _GDIPlus_GraphicsDispose($hImageContext)
            _GDIPlus_BitmapDispose($hBackImage)
            _GDIPlus_GraphicsDispose($hGraphics)
            _GDIPlus_Shutdown()
            GUIDelete($hGUI)
            DllClose($dll)
    Exit
    EndSwitch
    If _IsPressed("4E", $dll) Then ;press n to negative image
        $hImage = _GDIPlus_BitmapCloneArea($hBackImage, 0, 0, $iX, $iY)
        _Negative()
    EndIf
    Sleep(100)
WEnd

Func _Negative()
    Local $tNegMatrix, $pNegMatrix
    If $hImage Then
        $hBackImage = _GDIPlus_BitmapCloneArea($hImage, 0, 0, $iX, $iY)
        $hImageContext = _GDIPlus_ImageGetGraphicsContext($hBackImage)
    $tNegMatrix = _GDIPlus_ColorMatrixCreateNegative()
    $pNegMatrix = DllStructGetPtr($tNegMatrix)
        $hIA = _GDIPlus_ImageAttributesCreate()
    _GDIPlus_ImageAttributesSetColorMatrix($hIA, 0, True, $pNegMatrix)
    _GDIPlus_GraphicsDrawImageRectRectIA($hImageContext, $hImage, 0, 0, $iX, $iY, 0, 0, $iX, $iY, $hIA)
        _GDIPlus_GraphicsDrawImageRectRect($hGraphics, $hBackImage, 0, 0, $iX, $iY, 0, 0, $iX, $iY)
        $tNegMatrix = 0
    EndIf
EndFunc

; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_ColorMatrixCreateNegative
; Description ...: Creates and initializes a negative color matrix
; Syntax.........: _GDIPlus_ColorMatrixCreateNegative()
; Parameters ....: None
; Return values .: Success  - $tagGDIPCOLORMATRIX structure
;   Failure     - 0
; Remarks .......: None
; Related .......: $tagGDIPCOLORMATRIX
; Link ..........; @@MsdnLink@@ ColorMatrix
; Example .......; No
; ===============================================================================================================================
Func _GDIPlus_ColorMatrixCreateNegative()
    Local $iI, $tCM
    $tCM = _GDIPlus_ColorMatrixCreateScale(-1, -1, -1, 1)
    For $iI = 1 To 4
        DllStructSetData($tCM, "m", 1, 20 + $iI)
    Next
    Return $tCM
EndFunc ;==>_GDIPlus_ColorMatrixCreateNegative

; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_ColorMatrixCreateScale
; Description ...: Creates and initializes a scaling color matrix
; Syntax.........: _GDIPlus_ColorMatrixCreateScale($nRed, $nGreen, $nBlue[, $nAlpha = 1])
; Parameters ....: $nRed - Red component scaling factor
;   $nGreen - Green component scaling factor
;   $nBlue - Blue component scaling factor
;   $nAlpha - Alpha component scaling factor
; Return values .: Success  - $tagGDIPCOLORMATRIX structure that contains a scaling color matrix
;   Failure     - 0
; Remarks .......: A scaling color matrix is used to multiply components of a color by multiplier factors
; Related .......: $tagGDIPCOLORMATRIX
; Link ..........; @@MsdnLink@@ ColorMatrix
; Example .......; No
; ===============================================================================================================================
Func _GDIPlus_ColorMatrixCreateScale($nRed, $nGreen, $nBlue, $nAlpha = 1)
    Local $tCM
    Local Const $tagGDIPCOLORMATRIX = "float m[25]"
    $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

; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_ImageAttributesSetColorMatrix
; Description ...: Sets or clears the color- and grayscale-adjustment matrices for a specified category
; Syntax.........: _GDIPlus_ImageAttributesSetColorMatrix($hImageAttributes[, $iColorAdjustType = 0[, $fEnable = False,[ $pClrMatrix = 0[, $pGrayMatrix = 0[, $iColorMatrixFlags = 0]]]]])
; Parameters ....: $hImageAttributes - Pointer to an ImageAttribute object
;   $iColorAdjustType - The category for which the color- and grayscale-adjustment matrices are set or cleared:
;   |0 - Color or grayscale adjustment applies to all categories that do not have adjustment settings of their own
;   |1 - Color or grayscale adjustment applies to bitmapped images
;   |2 - Color or grayscale adjustment applies to brush operations in metafiles
;   |3 - Color or grayscale adjustment applies to pen operations in metafiles
;   |4 - Color or grayscale adjustment applies to text drawn in metafiles
;   $fEnable            - If True, the specified matrices (color, grayscale or both) adjustments for the specified
;   +category are applied; otherwise the category is cleared
;   $pClrMatrix      - Pointer to a $tagGDIPCOLORMATRIX structure that specifies a color-adjustment matrix
;   $pGrayMatrix         - Pointer to a $tagGDIPCOLORMATRIX structure that specifies a grayscale-adjustment matrix
;   $iColorMatrixFlags - Type of image and color that will be affected by the adjustment matrices:
;   |0 - All color values (including grays) are adjusted by the same color-adjustment matrix
;   |1 - Colors are adjusted but gray shades are not adjusted.
;   +A gray shade is any color that has the same value for its red, green, and blue components
;   |2 - Colors are adjusted by one matrix and gray shades are adjusted by another matrix
; Return values .: Success  - True
;   Failure     - False and either:
;   |@error and @extended are set if DllCall failed
;   |$GDIP_STATUS contains a non zero value specifying the error code
; Remarks .......: None
; Related .......: _GDIPlus_ColorMatrixCreate, $tagGDIPCOLORMATRIX
; Link ..........; @@MsdnLink@@ GdipSetImageAttributesColorMatrix
; Example .......; No
; ===============================================================================================================================
Func _GDIPlus_ImageAttributesSetColorMatrix($hImageAttributes, $iColorAdjustType = 0, $fEnable = False, $pClrMatrix = 0, $pGrayMatrix = 0, $iColorMatrixFlags = 0)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipSetImageAttributesColorMatrix", "hwnd", $hImageAttributes, "int", $iColorAdjustType, "int", $fEnable, "ptr", $pClrMatrix, "ptr", $pGrayMatrix, "int", $iColorMatrixFlags)

    If @error Then Return SetError(@error, @extended, False)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[0] = 0
EndFunc ;==>_GDIPlus_ImageAttributesSetColorMatrix

; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_GraphicsDrawImageRectRectIA
; Description ...: Draws an image
; Syntax.........: _GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hImage, $nSrcX, $nSrcY, $nSrcWidth, $nSrcHeight, $nDstX, $nDstY, $nDstWidth, $nDstHeight[, $hImageAttributes = 0[, $iUnit = 2]])
; Parameters ....: $hGraphics - Pointer to a Graphics object
;   $hImage     - Pointer to an Image object
;   $iSrcX  - The X coordinate of the upper left corner of the source image
;   $iSrcY  - The Y coordinate of the upper left corner of the source image
;   $iSrcWidth - Width of the source image
;   $iSrcHeight - Height of the source image
;   $iDstX  - The X coordinate of the upper left corner of the destination image
;   $iDstY  - The Y coordinate of the upper left corner of the destination image
;   $iDstWidth - Width of the destination image
;   $iDstHeight - Height of the destination image
;   $hImageAttributes - Pointer to an ImageAttributes object that specifies the color and size attributes of the image to be drawn
;   $iUnit   - Unit of measurement:
;   |0 - World coordinates, a nonphysical unit
;   |1 - Display units
;   |2 - A unit is 1 pixel
;   |3 - A unit is 1 point or 1/72 inch
;   |4 - A unit is 1 inch
;   |5 - A unit is 1/300 inch
;   |6 - A unit is 1 millimeter
; Return values .: Success  - True
;   Failure     - False and either:
;   |@error and @extended are set if DllCall failed
;   |$GDIP_STATUS contains a non zero value specifying the error code
; Remarks .......: None
; Related .......: None
; Link ..........; @@MsdnLink@@ GdipDrawImageRectRect
; Example .......; No
; ===============================================================================================================================
Func _GDIPlus_GraphicsDrawImageRectRectIA($hGraphics, $hImage, $nSrcX, $nSrcY, $nSrcWidth, $nSrcHeight, $nDstX, $nDstY, $nDstWidth, $nDstHeight, $hImageAttributes = 0, $iUnit = 2)
    Local $aResult = DllCall($ghGDIPDll, "int", "GdipDrawImageRectRect", "hwnd", $hGraphics, "hwnd", $hImage, "float", $nDstX, "float", _
            $nDstY, "float", $nDstWidth, "float", $nDstHeight, "float", $nSrcX, "float", $nSrcY, "float", $nSrcWidth, "float", _
            $nSrcHeight, "int", $iUnit, "hwnd", $hImageAttributes, "int", 0, "int", 0)

    If @error Then Return SetError(@error, @extended, False)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[0] = 0
EndFunc ;==>_GDIPlus_GraphicsDrawImageRectRectIA

; #FUNCTION# ====================================================================================================================
; Name...........: _GDIPlus_ImageAttributesCreate
; Description ...: Creates an ImageAttributes object
; Syntax.........: _GDIPlus_ImageAttributesCreate()
; Parameters ....: None
; Return values .: Success  - Pointer to a new ImageAttribute object
;   Failure     - 0 and either:
;   |@error and @extended are set if DllCall failed
;   |$GDIP_STATUS contains a non zero value specifying the error code
; Remarks .......: After you are done with the object, call _GDIPlus_ImageAttributesDispose to release the object resources
; Related .......: _GDIPlus_ImageAttributesDispose
; Link ..........; @@MsdnLink@@ GdipCreateImageAttributes
; Example .......; No
; ===============================================================================================================================
Func _GDIPlus_ImageAttributesCreate()
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipCreateImageAttributes", "int*", 0)

    If @error Then Return SetError(@error, @extended, 0)
    $GDIP_STATUS = $aResult[0]
    Return $aResult[1]
EndFunc ;==>_GDIPlus_ImageAttributesCreate

BR,

UEZ

PS: it is a fast hack :mellow:

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!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Link to comment
Share on other sites

First off, "Cool!"

Secondly, is there someplace in the _GDIPlus_ImageAttributesSetColorMatrix where I could set the result to grayscale? Because that looks awesome! And fast, too!

I need to do some serious searching online and find someplace where the various parts of GDIPlus are explained for dumb people like myself. Because I can tell it's very powerful, yet its nuances elude me. :mellow:

Link to comment
Share on other sites

Gray-scaling this image produces the following image (which may not be to your likely):

Posted Image

You can try GDIP.au3 UDF to play with different toys. _GDIPlus_ColorMatrix* functions should be self-explanatory. If they aren't, consult MSDN GDI+ Classes to farther explore the ColorMatrix class.

Additionally, there is a little tool written originally by Sjaak Priester that I've find to be a perfect way to demonstrate the ColorMatrix class capabilities.

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