VIP

How to determine the PNG image is black or white.

9 posts in this topic

How to determine the PNG image is black or white.
If the test image 1, the results received Black
If the test image 2, the results received White
If the test image 2, the results received White

I do not know how to use PixelSearch :(

image.jpg


Regards,
 

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Can you show your code? The pictures above are both black and white. What are you trying to do exactly? PixelSearch will only search the user defined area for 1 pixel being a user defined color. Maybe this will help.

You can use this script to identify the location of the pixel position your mouse is currently on. It has been invaluable to me when using autoit:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=C:\Users\user\Desktop\PGCAH2.0.Exe
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <GuiConstants.au3>

Opt("GUIOnEventMode", 1)
Opt("WinTitleMatchMode", 4)
Global $xoffset = 10;X axis distance from mouse pointer to blue label
Global $yoffset = 23;Y axis distance from mouse pointer to blue label
Global $wposx, $wposy, $dt, $cwin, $xcalcl, $xcalcr, $ycalc, $cpos, $pos, $tpos, $hexv, $pcolor
Global $title = "Your Title Here"
HotKeySet("{ESC}", "Terminate")
$pgui = GUICreate($title, 250, 13, -1, -1, $ws_popup);Rear place holder for back of the blue label box (Title, Length of the blue lable box, Height of the blue label box,,)
$startlab = GUICtrlCreateLabel(" X: 0000, Y: 0000", 0, -1080, 250, 13)
GUICtrlSetBkColor($startlab, 13434879);blue label box color
WinSetOnTop($pgui, "", 1)
GUISetState(@SW_SHOW)
While 1
    _nmgp()
WEnd

Func _nmgp()
    Local $_cpos = MouseGetPos();get current position of the mouse on desktop
    Sleep(10)
    $pcolor = PixelGetColor($_cpos[0], $_cpos[1]);help
    $pos = MouseGetPos()
    GUICtrlSetData($startlab, " X: " & $pos[0] & ", Y: " & $pos[1] & " HEX: " & Hex($pcolor, 6) & " DEC: " & $pcolor)

;************************************ Moves the blue label with the mouse *****************************
    If $dt = 1 Then
        $xcalcr = 0.95 * @DesktopWidth
        $xcalcl = 0.05 * @DesktopWidth
        $ycalc = 0.9 * @DesktopHeight
        If $pos[1] > $ycalc Then
            $wposy = $pos[1] - $yoffset * 2
        Else
            $wposy = $pos[1] + $yoffset
        EndIf
        If $pos[0] > $xcalcr Then
            $wposx = $pos[0] - $xoffset * 3
        ElseIf $pos[0] < $xcalcl Then
            $wposx = $pos[0] + 10
        Else
            $wposx = $pos[0] - $xoffset
        EndIf
    Else
        _clientmouse()
    EndIf
    WinMove($title, "", $wposx, $wposy)
;************************************ End Moves the blue label with the mouse ***************************

EndFunc

Func _clientmouse()
    Opt("MouseCoordMode", 1)
    $tpos = MouseGetPos()
    $cpos = WinGetPos($cwin)
    $xcalcr = 0.95 * $cpos[2]
    $xcalcl = 0.95 * $cpos[2]
    $ycalc = 5.0 * $cpos[3];Y axis for offsetting the text box when you reach the top of the screen (so you can stil see the coordinates)
    If $tpos[1] > $ycalc Then
        $wposy = $tpos[1] - $yoffset * 2; Y Axis to determine the distance from the mouse pointer and the blue text box
    Else
        $wposy = $tpos[1] + $yoffset
    EndIf
    If $tpos[0] > $xcalcr Then
        $wposx = $tpos[0] - $xoffset - $xcalcr ; X Axis to determine the distance from the mouse pointer and the blue text box
    ElseIf $tpos[0] < $xcalcl Then
        $wposx = $tpos[0] + 10
    Else
        $wposx = $tpos[0] - $xoffset
    EndIf
EndFunc

Func terminate()
    Exit 0
EndFunc

Compile the above code and run it. You can hit esc to exit out of it. pixlesearch - https://www.autoitscript.com/autoit3/docs/functions/PixelSearch.htm If you want to look for a black color then I would try something like this:

#include <MsgBoxConstants.au3>

$color = PixelSearch(0,0,500,500,0);This checks the upper left corner of your main monitor for the color black (dec code '0')

If Not @Error Then
    MsgBox(0,0,"Black was found!")
EndIF

 

Edited by computergroove
1 person likes this

Get Scite to add a popup when you use a 3rd party UDF -> http://www.autoitscript.com/autoit3/scite/docs/SciTE4AutoIt3/user-calltip-manager.html

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Hi,

this little script returns the percentage of pixels with a given color. I also have a Milliseconds-version somewhere in my ASM-folders...hard to find it, but i would try to find it if you want :o)

#include <GUIConstantsEx.au3>
#include <WinAPI.au3>
#include <GDIPlus.au3>
#include <GDIPlusConstants.au3>
#include <StructureConstants.au3>
#include <Array.au3>


$bmpfile = "ergebnis.png"                                      ;the image....
$color = "000000"                                              ;color 24bit RGB , 000000 =black FFFFFF=white


_GDIPlus_Startup()

$t = TimerInit()


$pBitmap = _GDIPlus_BitmapCreateFromFile($bmpfile)
If @error Then MsgBox(0, "", "Fehler BitmapCreateFromFile")
$BitmapData = _GDIPlus_BitmapLockBits($pBitmap, 0, 0, _GDIPlus_ImageGetWidth($pBitmap), _GDIPlus_ImageGetHeight($pBitmap), $GDIP_ILMREAD, $GDIP_PXF24RGB)
If @error Then MsgBox(0, "", "Error locking region " & @error)
$stride = DllStructGetData($BitmapData, "Stride")              ;Stride - Offset, in bytes, between consecutive scan lines of the bitmap. If the stride is positive, the bitmap is top-down. If the stride is negative, the bitmap is bottom-up.
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $stride = ' & $stride & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$Width = DllStructGetData($BitmapData, "Width")                ;Image width - Number of pixels in one scan line of the bitmap.
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Width = ' & $Width & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$Height = DllStructGetData($BitmapData, "Height")              ;Image height - Number of scan lines in the bitmap.
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Height = ' & $Height & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$pixelFormat = DllStructGetData($BitmapData, "PixelFormat")    ;Pixel format - Integer that specifies the pixel format of the bitmap
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $pixelFormat = ' & $pixelFormat & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$Scan0 = DllStructGetData($BitmapData, "Scan0")                ;Scan0 - Pointer to the first (index 0) scan line of the bitmap.
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Scan0 = ' & $Scan0 & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
$pixeldata = DllStructCreate("byte[" & (Abs($stride) * ($Height)) & "]", $Scan0)

$BMP = StringTrimLeft(DllStructGetData($pixeldata, 1), 2)

StringReplace($BMP, $color, $color)                            ;count number of pixel
$count = @extended                                             ;number of pixel with color
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $count = ' & $count & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console

$percent_color = Int($count / $Width / $Height * 10000) / 100
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $Width*$Height = ' & $Width * $Height & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $percent_color = ' & $percent_color & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console


$m = TimerDiff($t)
ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $m = ' & $m & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console


$BMPDataStart = ""
$pixeldata = 0
_GDIPlus_BitmapUnlockBits($pBitmap, $BitmapData)
_GDIPlus_ImageDispose($pBitmap)
_WinAPI_DeleteObject($pBitmap)
_GDIPlus_Shutdown()

ShellExecute($bmpfile)
sleep(1000)
MsgBox(0, "color = " & $color, $percent_color & " % of the picture has pixels with color 0x" & $color)

 

Edited by AndyG
1 person likes this

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

Here a function to count the used colors in a bitmap:

#include <GDIPlus.au3>


Global $sFile = FileOpenDialog("Select an image", "", "Image (*.jpg;*.png;*.bmp;*.gif)")
If @error Then Exit
_GDIPlus_Startup()
Global Const $hImage = _GDIPlus_ImageLoadFromFile($sFile)
Global $fTimer = TimerInit()
Global $iColorCount = _GDIPlus_ImageGetColorCount($hImage)
Global $fEndTime = Round(TimerDiff($fTimer), 2)
MsgBox(0, "Color Counter", "Found " & $iColorCount & " unique colors in " & $fEndTime & " ms.")
_GDIPlus_ImageDispose($hImage)
_GDIPlus_Shutdown()


Func _GDIPlus_ImageGetColorCount($hImage) ;faster but uses a lot of memory for huge images!
    Local Const $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage)
    If $iW * $iH > 2 ^ 24 Then Return SetError(1, 0, -1) ;will cause memory issues
    Local Const $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMREAD, $GDIP_PXF32ARGB)
    Local Const $iScan0 = $tBitmapData.Scan0
    Local $tPixel = DllStructCreate("byte Binary[" & $iW * $iH * 4 & "];", $iScan0)
    Local $bData = $tPixel.Binary
    _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
    Local $aResult = StringRegExp($bData, "[[:xdigit:]]{8}", 3), $y, $s, $iColorCount = 0
    If $iW * $iH <> UBound($aResult) Then Return SetError(1, 0, -2) ;internal error
    For $y = 0 To UBound($aResult) - 1
        $s = "_" & $aResult[$y] & "_"
        If Not IsDeclared($s) Then
            Assign($s, 0, 1)
            $iColorCount += 1
        EndIf
    Next
    $bData = Null
    $tPixel = Null
    $aResult = Null
    Return $iColorCount
EndFunc   ;==>_GDIPlus_ImageGetColorCount

 

Edit: ok, I see that your problem is not to count the colors. I should read carefully before posting...

 

You can use _GDIPlus_BitmapGetPixel ( $hBitmap, 0, 0 ) to get the color to check whether it is b/w or w/b.

Edited by UEZ
Added much faster _GDIPlus_ImageGetColorCount function
1 person likes this

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

Share this post


Link to post
Share on other sites

Thank you for helping me.

@computergroove: Code like color picker, but not working on my computer.

@UEZ: Too many time to count.
With one small picture that takes 20 seconds.

@AndyG: Worked very well and fast, I will try to use it.


Regards,
 

Share this post


Link to post
Share on other sites

With @AndyG script I can get black and white photographs successful.
But this century color photos are very popular.
Is there any way determine the dominant color of the picture is bright or dark?

I can not express my intent to computer implementation.
The program I intended to write just convert png to jpg images.
I need to determine the dominant color of the image that is bright or dark to me to replace transparent background color with black or white.


This process I think is impossible.
Sometimes I wonder if this photo background color with white or black?
I will give up.

 

image.png

image.png

image.png

image.png


Regards,
 

Share this post


Link to post
Share on other sites

Hi,

you could easily transfer a 32-Bit-Color-picture into black/white! If this is done, count black/white pixels...

You have to think about the threshold, if a colored pixel is black or white, example:  if (R+G+B)/3>127 then white

If Alpha is XXX then black(white)

1 person likes this

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Try this:

;example needs GDI+ v1.1 which is available with Win7+
#include <GDIPlus.au3>

Global $sFile = FileOpenDialog("Select an image", "", "Image (*.jpg;*.png;*.bmp;*.gif)")
If @error Then Exit
_GDIPlus_Startup()
Global Const $hImage = _GDIPlus_ImageLoadFromFile($sFile), $iW = _GDIPlus_ImageGetWidth($hImage), $iH = _GDIPlus_ImageGetHeight($hImage)
Global $tHistogram = _GDIPlus_BitmapGetHistogramEx($hImage)
_GDIPlus_ImageDispose($hImage)
Global $fAverage, $i, $sState
For $i = 1 To 256
    $fAverage += $tHistogram.Grey(($i)) * $i
Next
_GDIPlus_Shutdown()
$fAverage /= $iW * $iH
$sState = $fAverage < 0x80 ? " dark" : " light"
MsgBox(0, "Test", "Image is more " & $sState & ". Greyscale average is: " & $fAverage)

 

Edited by UEZ
1 person likes this

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

Share this post


Link to post
Share on other sites

Thank AndyG and UEZ,
Script of UEZ find the dominant color of the image is successful.

But the purpose of which is to find appropriate background image.
I do not know how but ImageMagick has done it very well with the option -flatten.
I tried it for a lot of photo work very well, it was magic.

If you know c ++ you can transcode it on AutoIt?
http://www.imagemagick.org/api/Magick++/STL_8h_source.html
 

// Merge a sequence of image frames which represent image layers.
 2335   // This is useful for combining Photoshop layers into a single image.
 2336   template <class InputIterator>
 2337   void flattenImages( Image *flattendImage_,
 2338           InputIterator first_,
 2339           InputIterator last_ ) {
 2340     GetPPException;
 2341     linkImages( first_, last_ );
 2342     MagickCore::Image* image = MagickCore::MergeImageLayers( first_->image(),
 2343       FlattenLayer,exceptionInfo );
 2344     unlinkImages( first_, last_ );
 2345     flattendImage_->replaceImage( image );
 2346     ThrowPPException(flattendImage_->quiet());
 2347   }

 


Regards,
 

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