Jump to content

Find most frequent pixel color (solved)


Recommended Posts

I'm trying to remove the background of some screenshots but I can't figure out how to find the most frequent color, as that should be the background to remove.

Right now, I'm just getting the pixel color at -5 from the bottom right corner of the image for the background color which works for now, but I'd prefer to find and remove the most frequent.

 

Any ideas?

This is what I have so far.

#include <ScreenCapture.au3>

_TransparentBackground(0, 0, 500, 300)

Func _TransparentBackground($x = 0, $y = 0, $w = @DesktopWidth, $h = @DesktopHeight)    ;Change the most common color (usually background) to transparent?
    _GDIPlus_Startup()
    Local $hHBitmap = _ScreenCapture_Capture("", $x, $y, $w - 1, $h - 1)
    Local $hBmp = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)

    Local $hBitmap_Result = _GDIPlus_BitmapCreateFromScan0($w, $h)
    Local $hBitmap_Result_Ctxt = _GDIPlus_ImageGetGraphicsContext($hBitmap_Result)

    Local $hIA = _GDIPlus_ImageAttributesCreate()

;How do I find the background color (Most Frequent Color)?  This is working for me but not ideal...
    $iPixel = "0x" & Hex(PixelGetColor($x + $w - 5, $y + $h - 5))
    ConsoleWrite("Pixel Color = " & $iPixel & @CRLF)
    
    _GDIPlus_ImageAttributesSetColorKeys($hIA, 1, True, $iPixel, $iPixel)
    _GDIPlus_GraphicsDrawImageRectRect($hBitmap_Result_Ctxt, $hBmp, 0, 0, $w, $h, 0, 0, $w, $h, $hIA)
    _GDIPlus_ImageSaveToFile($hBitmap_Result, @ScriptDir & "\TransPtResult.png")

    _GDIPlus_ImageAttributesDispose($hIA)
    _GDIPlus_GraphicsDispose($hBitmap_Result_Ctxt)
    _GDIPlus_BitmapDispose($hBitmap_Result)
    _GDIPlus_BitmapDispose($hBmp)
    _WinAPI_DeleteObject($hHBitmap)
    _GDIPlus_Shutdown()

    ShellExecute(@ScriptDir & "\TransPtResult.png") ;For testing, will be used for OCR

EndFunc

Thanks,

Mike

Link to comment
Share on other sites

Here what I would do to find the most common pixel color :

#include <ScreenCapture.au3>
#include <Array.au3>

Opt ("MustDeclareVars", 1)

CountPixels (100,100,200,200)

Func CountPixels ($Left=0,$Top=0,$Right=-1,$Bottom=-1)
Local $hBitmap, $hImage, $BitmapData, $Width, $Height, $Scan, $Pos = 0

  _GDIPlus_Startup ()
  $hBitmap = _ScreenCapture_Capture ("",$Left,$Top,$Right,$Bottom,False)
  $hImage = _GDIPlus_BitmapCreateFromHBITMAP ($hBitmap)
  _WinAPI_DeleteObject ($hBitmap)

  $Width = _GDIPlus_ImageGetWidth($hImage)
  $Height = _GDIPlus_ImageGetHeight($hImage)
  $BitmapData = _GDIPlus_BitmapLockBits ($hImage, 0, 0, $Width, $Height, $GDIP_ILMREAD, $GDIP_PXF32RGB)
  $Scan = DllStructGetData($BitmapData, "Scan0")

  Local $tPixel = DllStructCreate("int[" & $Width * $Height & "]", $Scan)

  Local $aPixel[0][2], $p, $i, $c = 0

  For $row = 0 To $Height-1
    For $col = 0 To $Width-1
      $Pos += 1
      $p = BitAnd(DllStructGetData($tPixel,1,$Pos),0xFFFFFF)
      $i = _ArraySearch ($aPixel,$p,0,0,0,0,1,0)
      if $i < 0 then
        $c += 1
        Redim $aPixel[$c][2]
        $aPixel[$c-1][0] = $p
        $aPixel[$c-1][1] = 1
      else
        $aPixel[$i][1] += 1
      endif        
    Next
  Next
  _ArrayDisplay ($aPixel)
    
  _GDIPlus_BitmapUnlockBits($hImage, $BitmapData)
  _GDIPlus_ImageDispose($hImage)
  _GDIPlus_Shutdown()

EndFunc

Untested...

Edited by Nine
Link to comment
Share on other sites

Thanks Nine, the _GDIPlus_BitmapLockBits that you used gave me the hint that I was looking for.

Once I was able to get all the pixels, I ended up using Scripting.Dictionary to drastically speed up the search.  Here is my finished sample script.  Now for me to work it into my main script.

#include <ScreenCapture.au3>
#include <Array.au3>


$iTimer = TimerInit()
$aUnique = _CommonColorSD(50, 100, 200, 200)
$iMaxIndex=_ArrayMaxIndex($aUnique,1,1,-1,1)
ConsoleWrite("Max Pixel Color = " & $aUnique[$iMaxIndex][0] & ", Count = " & $aUnique[$iMaxIndex][1] & @CRLF)
$iTime = TimerDiff($iTimer)
ConsoleWrite("ColorA time = (" & $iTime & ")" & @CRLF)
_ArrayDisplay($aUnique, '_countUniqueElements')
;Max Pixel Color = 2039583, Count = 31054
;ColorA time = (716.606813754679)



Func _CommonColorSD($x = 0, $y = 0, $iW = @DesktopWidth, $iH = @DesktopHeight)  ;Change the most common color (usually background) to transparent?
    Local $oDict = ObjCreate("Scripting.Dictionary")
    _GDIPlus_Startup()
    Local $hHBitmap = _ScreenCapture_Capture("", $x, $y, $iW - 1, $iH - 1)
    Local $hBmp = _GDIPlus_BitmapCreateFromHBITMAP($hHBitmap)

    Local $hBitmap = _GDIPlus_BitmapCreateFromScan0($iW, $iH)
    Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsDrawImageRect($hContext, $hBmp, 0, 0, $iW, $iH)

    Local $tBitmapData = _GDIPlus_BitmapLockBits($hBitmap, 0, 0, $iW, $iH, BitOR($GDIP_ILMWRITE, $GDIP_ILMREAD), $GDIP_PXF32ARGB) ;locks a portion of a bitmap for reading and writing. More infor at http://msdn.microsoft.com/en-us/library/windows/desktop/ms536298(v=vs.85).aspx
    Local $iScan0 = DllStructGetData($tBitmapData, "Scan0") ;get scan0 (pixel data) from locked bitmap
    Local $tPixel = DllStructCreate("int[" & $iW * $iH & "];", $iScan0)
    Local $iPixel, $iRowOffset

    $iCount = 0
    For $iY = 0 To $iH - 1
        $iRowOffset = $iY * $iW + 1
        For $iX = 0 To $iW - 1  ;get each pixel in each line and row
            $iPixel = BitAnd(DllStructGetData($tPixel, 1, $iRowOffset + $iX), 0xFFFFFF) ;This gets the normal Windows pixel color.  Without BitAnd it returns Decimal Windows Color :( blah...
            If $oDict.Exists($iPixel) Then
                $oDict.Item($iPixel) = $oDict.Item($iPixel) + 1
            Else
                $oDict.Add($iPixel, 1)
            EndIf
        Next
    Next

    _GDIPlus_BitmapUnlockBits($hBitmap, $tBitmapData) ;unlocks a portion of a bitmap that was locked by _GDIPlus_BitmapLockBits
    ConsoleWrite("Count = " & $iCount & @CRLF)

    Local $iUniq = $oDict.Count
    Local $aRet[$iUniq][2]
    For $i = 0 To $iUniq - 1
        $aRet[$i][0] = $oDict.Keys[$i]
        $aRet[$i][1] = $oDict.Items[$i]
    Next

    Return $aRet

EndFunc

 

Link to comment
Share on other sites

@BigDaddyO After revisiting your code, I have found a way to get the 2D array up faster (about 40x) :

$p = 0
  For $vKeys in $oDict
    $aPixel[$p][0] = $vKeys
    $aPixel[$p][1] = $oDict.item ($vKeys)
    $p += 1
  Next

Thanks again for that nice discovery ...

Link to comment
Share on other sites

@Nine  I found that you can speed it up even more by not using an array and simply doing a compare while looping through the $oDict

Using one of my larger captures, my original loop took (135276.2844)ms

Your updated For In loop took (2437.6408)ms

This new For In loop took (864.1878)ms

$iMax = 0
        For $vKeys in $oDict
            If $oDict.Item($vKeys) > $iMax Then
                $iMax = $oDict.Item($vKeys)
                $iPixel = $vKeys
            EndIf
        Next

 

Now to speed up loading the pixels into the scripting dictionary as this large screen capture it taking (120661.1699)ms!

Link to comment
Share on other sites

48 minutes ago, BigDaddyO said:

So, the BitAnd when pulling each pixel is totally unnecessary.  I switched to capturing the raw Windows binary colors and only do the BitAND on the one pixel color I identify as Max and it dropped from 120 seconds down to 6 seconds runtime!  

Really ? Congrats.  I never thought that BITAND would be so gluttonous  :lol:

Link to comment
Share on other sites

I am now able to identify the background pixel color (most common) and I can replace those pixels with transparent.  I'd also like to be able to replace those background pixels with a specified color but I'm not able to get that working.  I know I need to use _GDIPlus_ImageAttributesSetRemapTable instead of _GDIPlus_ImageAttributesSetColorKeys and I thought I did it correctly, but it's not working.

In the example below, the 3rd one is supposed to change the background to White 0xFFFFFF but it's not working.  _GDIPlus_ImageAttributesSetRemapTable is not returning an error so I'm not sure what else to try.

Any ideas on this?

;Testing the replace pixel color
#include <ScreenCapture.au3>

;Capture an un-modified screenshot to use as a base for visually verifying changes
_ScreenCapture_Capture("C:\TEMP\Raw.jpg", 100, 50, 700, 550, False)

;This one works!
Swap_Background(100, 50, 700, 550, "C:\TEMP\Enlarged_No_Mod.Tiff", 3, 0, 0, 0, 0)       ;Just capture a screenshot and enlarge to Scale 3, save as TIFF

;This one works!
Swap_Background(100, 50, 700, 550, "C:\TEMP\Enlarged_Transparent.Tiff", 3, 0, 0, 0, 0, -1)  ;Capture a screenshot, Make background transparent, scale 3, save as TIFF

;This one doesnt change background to White!
Swap_Background(100, 50, 700, 550, "C:\TEMP\Enlarged_White.Tiff", 3, 0, 0, 0, 0, -1, 0xFFFFFF)  ;Capture a screenshot, Make background WHITE, Scale 3, save as TIFF


Func Swap_Background($x1, $y1, $x2, $y2, $sOutImage = "", $scale = 1, $left_indent = 0, $top_indent = 0, $right_indent = 0, $bottom_indent = 0, $Background = 0, $Replacement = -1)

    Local $hBitmap, $hwnd, $hDC, $hBMP, $hImage1, $hGraphic, $CLSID, $tParams, $pParams, $tData, $hImage2, $pos[4], $screenpos[4], $pos[4]
    Local $iPixel = 0
    Local $Ext = StringUpper(StringMid($sOutImage, StringInStr($sOutImage, ".", 0, -1) + 1))
    Local $giTIFColorDepth = 24
    Local $giTIFCompression = $GDIP_EVTCOMPRESSIONNONE

    $hTimerCapt = TimerInit()
    $hBitmap = _ScreenCapture_Capture("", $x1, $y1, $x2, $y2, False)
    _GDIPlus_Startup()
    ConsoleWrite("Captured initial screenshot to analyze in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)
    If $Background = -1 Then        ;Find the most common pixel color (background)
        $hTimerCapt = TimerInit()
        Local $hBmpClr = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
        Local $hBitmap0 = _GDIPlus_BitmapCreateFromScan0($x2 - $x1, $y2 - $y1)
        Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap0)
        _GDIPlus_GraphicsDrawImageRect($hContext, $hBmpClr, 0, 0, $x2 - $x1, $y2 - $y1)
        Local $tBitmapData = _GDIPlus_BitmapLockBits($hBitmap0, 0, 0, $x2 - $x1, $y2 - $y1, BitOR($GDIP_ILMWRITE, $GDIP_ILMREAD), $GDIP_PXF32ARGB) ;locks the bitmap for reading and writing. More infor at http://msdn.microsoft.com/en-us/library/windows/desktop/ms536298(v=vs.85).aspx
        Local $iScan0 = DllStructGetData($tBitmapData, "Scan0") ;get scan0 (pixel data) from locked bitmap
        Local $tPixel = DllStructCreate("int[" & ($x2 - $x1) * ($y2 - $y1) & "];", $iScan0)
        Local $iPixelr, $iRowOffset

        Local $oDict = ObjCreate("Scripting.Dictionary")    ;Create the Dictionary to store unique Pixel color counts
        For $iY = 0 To ($y2 - $y1) - 1
            $iRowOffset = $iY * ($x2 - $x1) + 1
            For $iX = 0 To ($x2 - $x1) - 1  ;get each pixel in each line and row
                $iPixelr = DllStructGetData($tPixel, 1, $iRowOffset + $iX)
                If $oDict.Exists($iPixelr) Then
                    $oDict.Item($iPixelr) = $oDict.Item($iPixelr) + 1
                Else
                    $oDict.Add($iPixelr, 1)
                EndIf
            Next
        Next
        ;Clear up memory usage
        _GDIPlus_BitmapUnlockBits($hBitmap0, $tBitmapData) ;unlocks a portion of a bitmap that was locked by _GDIPlus_BitmapLockBits
        _GDIPlus_GraphicsDispose($hContext)
        _GDIPlus_BitmapDispose($hBitmap0)
        _GDIPlus_BitmapDispose($hBmpClr)
        ConsoleWrite("Finished identifying all Image colors in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

        $hTimerCapt = TimerInit()
        $iMax = 0
        For $vKeys in $oDict
            If $oDict.Item($vKeys) > $iMax Then
                $iMax = $oDict.Item($vKeys)
                $iPixel = $vKeys
            EndIf
        Next
        ConsoleWrite("Pre BitAND Pixel = (" & $iPixel & ")" & @CRLF)
        $iPixel = BitAnd($iPixel, 0xFFFFFF) ;This switches the Decimal Windows Color into normal Windows pixel color.
        ConsoleWrite("Finished identifying main color Converted to (" & $iPixel & ") in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

    ElseIf $Background = 0 Then     ;Dont remove any pixels from the image (Default)
        $iPixel = ""
    Else                            ;If a Value was entered for $Background, assume it was a pixel color to remove
        $iPixel = $Background
    EndIf

    ; Convert the image to a bitmap
    $hImage2 = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)

    $hwnd = _WinAPI_GetDesktopWindow()
    $hDC = _WinAPI_GetDC($hwnd)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDC, (($x2 - $x1) * $scale) - ($right_indent * $scale), (($y2 - $y1) * $scale) - ($bottom_indent * $scale))

    _WinAPI_ReleaseDC($hwnd, $hDC)
    $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage1)

If $Replacement = -1 Then
    ;Setup the Transparency details
    $hTimerCapt = TimerInit()
    Local $hIA = _GDIPlus_ImageAttributesCreate()
    _GDIPlus_ImageAttributesSetColorKeys($hIA, 1, True, $iPixel, $iPixel)
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hImage2, 0 - $left_indent, 0 - $top_indent, ($x2 - $x1) + $left_indent, ($y2 - $y1) + $top_indent, 0 - ($left_indent * $scale), 0 - ($top_indent * $scale), (($x2 - $x1) * $scale) + $left_indent, (($y2 - $y1) * $scale) + $top_indent, $hIA)
    ConsoleWrite("Finished changing main color to Transparent in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

Else    ;A color was identified, need to replace the background $iPixel with $Replacement
    $hTimerCapt = TimerInit()
    ConsoleWrite("Replacing (" & $iPixel & ") with (" & $Replacement & ")" & @CRLF)
    Local $aRemapTable[2][2]
            $aRemapTable[0][0] = 1
            $aRemapTable[1][0] = $iPixel
            $aRemapTable[1][1] = $Replacement
    Local $hIA = _GDIPlus_ImageAttributesCreate()
    _GDIPlus_ImageAttributesSetRemapTable($hIA, $aRemapTable, 1)
    If @error Then ConsoleWrite("Error on RemapTable: (" & @error & ") @extended = (" & @extended & ")" & @CRLF)

    _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hImage2, 0 - $left_indent, 0 - $top_indent, ($x2 - $x1) + $left_indent, ($y2 - $y1) + $top_indent, 0 - ($left_indent * $scale), 0 - ($top_indent * $scale), (($x2 - $x1) * $scale) + $left_indent, (($y2 - $y1) * $scale) + $top_indent, $hIA)
    ConsoleWrite("Finished swapping main color (" & $aRemapTable[1][0] & ") with (" & $aRemapTable[1][1] & ") in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

EndIf

    $hTimerCapt = TimerInit()
    $CLSID = _GDIPlus_EncodersGetCLSID($Ext)

    ; Set TIFF parameters
    $tParams = _GDIPlus_ParamInit(2)
    $tData = DllStructCreate("int ColorDepth;int Compression")
    DllStructSetData($tData, "ColorDepth", $giTIFColorDepth)
    DllStructSetData($tData, "Compression", $giTIFCompression)
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOLORDEPTH, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "ColorDepth"))
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOMPRESSION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Compression"))
    If IsDllStruct($tParams) Then $pParams = DllStructGetPtr($tParams)

    ; Save TIFF and cleanup
    _GDIPlus_ImageSaveToFileEx($hImage1, $sOutImage, $CLSID, $pParams)
    _GDIPlus_ImageDispose($hImage1)
    _GDIPlus_ImageDispose($hImage2)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_DeleteObject($hBMP)
    _GDIPlus_Shutdown()
    ConsoleWrite("Generated the Scaled TIFF image in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

EndFunc

 

Thanks,

Mike

Edited by BigDaddyO
Link to comment
Share on other sites

Finally figured out swapping the color with a specific color.

Turns out the GDI stuff uses 8 character aRGB not just normal 6 character RGB that you find in most google searches.  the first 2 characters are for Transparency.  00 is totally transparent and FF = not transparent at all.

So, now this sample will create 4 images.  A basic capture, a Capture scaled up 3x, a Capture Scaled up 3x with a transparent background, a Capture scaled up 3x with a white background.

;Testing the replace pixel color
#include <ScreenCapture.au3>

;Capture an un-modified screenshot to use as a base for visually verifying changes
_ScreenCapture_Capture("C:\TEMP\Raw.jpg", 100, 50, 700, 550, False)


;Should I check OCR to see if it works better with greyscale?  _GDIPlus_BitmapConvertFormat()
;Need to convert the specified Pixel color into a Negative number like I get from the Pixel Search for this to change to!

;Capture a screenshot and enlarge to Scale 3, save as TIFF
Swap_Background(100, 50, 700, 550, "C:\TEMP\Enlarged_No_Mod.Tiff", 3, 0, 0, 0, 0)

;Make background transparent!
; Scale = 3, the image will be 3x the size which is usefull for OCR
Swap_Background(100, 50, 700, 550, "C:\TEMP\Enlarged_Transparent.Tiff", 3, 0, 0, 0, 0, -1)

;Change background to White! could use 0x00000000 to make background transparent!
; Make background WHITE (Must use aRGB code, where first FF = transparency, remaining 6 FF are pulled from normal windows spy or color picker
;       Could use this for setting background to transparent by using 0x00FFFFFF or 0x00000000
; Scale = 3, the image will be 3x the size which is usefull for OCR
Swap_Background(100, 50, 700, 550, "C:\TEMP\Enlarged_White.Tiff", 3, 0, 0, 0, 0, True, 0xFFFFFFFF)



Func Swap_Background($x1, $y1, $x2, $y2, $sOutImage = "", $scale = 1, $left_indent = 0, $top_indent = 0, $right_indent = 0, $bottom_indent = 0, $Background = False, $NewColor = True)
    ConsoleWrite("$NewColor = " & hex($NewColor) & ", True Hex = " & Hex(True) & @CRLF)
    $hTimerFull = TimerInit()

    Local $hBitmap, $hwnd, $hDC, $hBMP, $hImage1, $hGraphic, $CLSID, $tParams, $pParams, $tData, $hImage2, $pos[4], $screenpos[4], $pos[4]
    Local $iPixel = 0
    Local $Ext = StringUpper(StringMid($sOutImage, StringInStr($sOutImage, ".", 0, -1) + 1))
    Local $giTIFColorDepth = 24
    Local $giTIFCompression = $GDIP_EVTCOMPRESSIONNONE

    $hTimerCapt = TimerInit()
    $hBitmap = _ScreenCapture_Capture("", $x1, $y1, $x2, $y2, False)
    _GDIPlus_Startup()
    ConsoleWrite("Captured initial screenshot to analyze in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)
    If $Background = True Then        ;Find the most common pixel color (background)
        $hTimerCapt = TimerInit()
        Local $hBmpClr = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)
        Local $hBitmap0 = _GDIPlus_BitmapCreateFromScan0($x2 - $x1, $y2 - $y1)
        Local $hContext = _GDIPlus_ImageGetGraphicsContext($hBitmap0)
        _GDIPlus_GraphicsDrawImageRect($hContext, $hBmpClr, 0, 0, $x2 - $x1, $y2 - $y1)
        Local $tBitmapData = _GDIPlus_BitmapLockBits($hBitmap0, 0, 0, $x2 - $x1, $y2 - $y1, BitOR($GDIP_ILMWRITE, $GDIP_ILMREAD), $GDIP_PXF32ARGB)  ;locks the bitmap for reading and writing, returns aRGB (first 2 are transpancy, FF for not transparent 00 for full transparent). More infor at http://msdn.microsoft.com/en-us/library/windows/desktop/ms536298(v=vs.85).aspx
        Local $iScan0 = DllStructGetData($tBitmapData, "Scan0") ;get scan0 (pixel data) from locked bitmap
        Local $tPixel = DllStructCreate("int[" & ($x2 - $x1) * ($y2 - $y1) & "];", $iScan0)
        Local $iPixelr, $iRowOffset

        Local $oDict = ObjCreate("Scripting.Dictionary")    ;Create the Dictionary to store unique Pixel color counts
        For $iY = 0 To ($y2 - $y1) - 1
            $iRowOffset = $iY * ($x2 - $x1) + 1
            For $iX = 0 To ($x2 - $x1) - 1  ;get each pixel in each line and row
                $iPixelr = DllStructGetData($tPixel, 1, $iRowOffset + $iX)
                If $oDict.Exists($iPixelr) Then
                    $oDict.Item($iPixelr) = $oDict.Item($iPixelr) + 1
                Else
                    $oDict.Add($iPixelr, 1)
                EndIf
            Next
        Next
        ;Clear up memory usage
        _GDIPlus_BitmapUnlockBits($hBitmap0, $tBitmapData) ;unlocks a portion of a bitmap that was locked by _GDIPlus_BitmapLockBits
        _GDIPlus_GraphicsDispose($hContext)
        _GDIPlus_BitmapDispose($hBitmap0)
        _GDIPlus_BitmapDispose($hBmpClr)
        ConsoleWrite("Finished identifying all Image colors in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

        $hTimerCapt = TimerInit()
        $iMax = 0
        For $vKeys in $oDict
            If $oDict.Item($vKeys) > $iMax Then
                $iMax = $oDict.Item($vKeys)
                $iPixel = $vKeys
            EndIf
        Next
        ConsoleWrite("Pre BitAND Pixel = (" & $iPixel & ") - Post BitAND Pixel = (" & BitAnd($iPixel, 0xFFFFFFFF) & ")" & @CRLF)
;~         $iPixel = BitAnd($iPixel, 0xFFFFFF) ;This switches the Decimal Windows Color into normal Windows pixel color.
        ConsoleWrite("Finished identifying main color Converted to (" & $iPixel & ") in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

    ElseIf $Background = False Then     ;Dont remove any pixels from the image (Default)
        $iPixel = ""
    Else                            ;If a Value was entered for $Background, assume it was a pixel color to remove
        $iPixel = $Background
    EndIf

    ; Convert the image to a bitmap
    $hImage2 = _GDIPlus_BitmapCreateFromHBITMAP($hBitmap)

    $hwnd = _WinAPI_GetDesktopWindow()
    $hDC = _WinAPI_GetDC($hwnd)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDC, (($x2 - $x1) * $scale) - ($right_indent * $scale), (($y2 - $y1) * $scale) - ($bottom_indent * $scale))

    _WinAPI_ReleaseDC($hwnd, $hDC)
    $hImage1 = _GDIPlus_BitmapCreateFromHBITMAP($hBMP)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hImage1)

If hex($NewColor) = hex(True) Then  ;8 digit color codes (aRGB) always seem to return as -1 which seem to match True?!? just using Hex to match so it works properly.
    ;Setup the Transparency details
    $hTimerCapt = TimerInit()
    Local $hIA = _GDIPlus_ImageAttributesCreate()
    _GDIPlus_ImageAttributesSetColorKeys($hIA, 1, True, $iPixel, $iPixel)
    _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hImage2, 0 - $left_indent, 0 - $top_indent, ($x2 - $x1) + $left_indent, ($y2 - $y1) + $top_indent, 0 - ($left_indent * $scale), 0 - ($top_indent * $scale), (($x2 - $x1) * $scale) + $left_indent, (($y2 - $y1) * $scale) + $top_indent, $hIA)
    ConsoleWrite("Finished changing main color to Transparent in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

ElseIf hex($NewColor) = hex(False) Then ;Dont mess with the background color
    ;;;

Else    ;A color was identified, need to replace the background $iPixel with $Replacement
    $hTimerCapt = TimerInit()
    ConsoleWrite("Replacing (" & $iPixel & ") with (" & $NewColor & ")" & @CRLF)
    Local $aRemapTable[2][2]
            $aRemapTable[0][0] = 1
            $aRemapTable[1][0] = $iPixel
            $aRemapTable[1][1] = $NewColor
    Local $hIA = _GDIPlus_ImageAttributesCreate()
    _GDIPlus_ImageAttributesSetRemapTable($hIA, $aRemapTable, 1)
    If @error Then ConsoleWrite("Error on RemapTable: (" & @error & ") @extended = (" & @extended & ")" & @CRLF)

    _GDIPlus_GraphicsDrawImageRectRect($hGraphic, $hImage2, 0 - $left_indent, 0 - $top_indent, ($x2 - $x1) + $left_indent, ($y2 - $y1) + $top_indent, 0 - ($left_indent * $scale), 0 - ($top_indent * $scale), (($x2 - $x1) * $scale) + $left_indent, (($y2 - $y1) * $scale) + $top_indent, $hIA)
    ConsoleWrite("Finished swapping main color (" & $aRemapTable[1][0] & ") with (" & $aRemapTable[1][1] & ") in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

EndIf

    $hTimerCapt = TimerInit()
    $CLSID = _GDIPlus_EncodersGetCLSID($Ext)

    ; Set TIFF parameters
    $tParams = _GDIPlus_ParamInit(2)
    $tData = DllStructCreate("int ColorDepth;int Compression")
    DllStructSetData($tData, "ColorDepth", $giTIFColorDepth)
    DllStructSetData($tData, "Compression", $giTIFCompression)
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOLORDEPTH, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "ColorDepth"))
    _GDIPlus_ParamAdd($tParams, $GDIP_EPGCOMPRESSION, 1, $GDIP_EPTLONG, DllStructGetPtr($tData, "Compression"))
    If IsDllStruct($tParams) Then $pParams = DllStructGetPtr($tParams)

    ; Save TIFF and cleanup
    _GDIPlus_ImageSaveToFileEx($hImage1, $sOutImage, $CLSID, $pParams)
    _GDIPlus_ImageDispose($hImage1)
    _GDIPlus_ImageDispose($hImage2)
    _GDIPlus_GraphicsDispose($hGraphic)
    _WinAPI_DeleteObject($hBMP)
    _GDIPlus_Shutdown()
    ConsoleWrite("Generated the Scaled TIFF image in (" & TimerDiff($hTimerCapt) & ")ms" & @CRLF)

    ConsoleWrite("Completed Image modification.  Total time = (" & Round(TimerDiff($hTimerFull) / 1000, 1) & ")seconds" & @CRLF & @CRLF)


EndFunc

 

Link to comment
Share on other sites

  • BigDaddyO changed the title to Find most frequent pixel color (solved)

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