Jump to content

Recommended Posts

Posted

how do I make everything non-black in an image become white (for example so every pixel that isn't black (which will be text) becomes the same color (white for example)?

Posted (edited)

I want to clean an image that has "dirt" on it's background so it's easier to OCR the text on it. which is all black.

for example

Posted Image

becoming

Posted Image

(roughly)

Edited by Penny
Posted

how do I make everything non-black in an image become white (for example so every pixel that isn't black (which will be text) becomes the same color (white for example)?

Here are two methods.

First one uses _GDIPlus_BitmapLockBits. And at about line #56, there is the regular expression pattern to match all colours that are not 0x000000FF, which in the 32 bit Hexidecimal colour format being used is fully opaque black.

This example was modified from the script from here.

;
#include <ScreenCapture.au3>
#include <GDIPlus.au3>
; http://www.autoitscript.com/forum/index.php?showtopic=102626&view=findpost&p=729016
Global $sRegPath, $sImageIn, $sImageOut

$sImageIn = "C:\Program Files\AutoIt3\Examples\GUI\logo4.gif"
$sImageOut = @ScriptDir & "\B_W_Test.png"
Local $begin = TimerInit()

_ImageNonBlackToWhite(_ScreenCapture_Capture("", 0, 0, 200, 200, False), $sImageOut)
;OR
;_ImageNonBlackToWhite($sImageIn, $sImageOut)

ConsoleWrite("Time taken: " & Round(TimerDiff($begin), 2) & " milliseconds" & @CRLF)
If FileExists($sImageOut) Then ShellExecute($sImageOut)


Func _ImageNonBlackToWhite($sInFile, $sOutFile)
    Local $hImage, $iW, $iH, $tBitmapData, $iStride, $iScan0, $iX, $iY, $hBitmap1, $hBMP1

    _GDIPlus_Startup()
    If Number($sInFile) Then
        $hImage = _GDIPlus_BitmapCreateFromHBITMAP($sInFile)
        _WinAPI_DeleteObject($sInFile)
    Else
        $hImage = _GDIPlus_ImageLoadFromFile($sInFile)
    EndIf
    $iW = _GDIPlus_ImageGetWidth($hImage)
    $iH = _GDIPlus_ImageGetHeight($hImage)
    ;
    Local $aRet, $hBmp, $hBitmap, $hGraphic
    $aRet = _GDIPlus_ImageGetPixelFormat($hImage)
    $hBmp = _WinAPI_CreateBitmap($iW, $iH, 1, 32)
    $hBitmap = _GDIPlus_BitmapCreateFromHBITMAP($hBmp)
    _WinAPI_DeleteObject($hBmp)
    $hGraphic = _GDIPlus_ImageGetGraphicsContext($hBitmap)
    _GDIPlus_GraphicsDrawImage($hGraphic, $hImage, 0, 0)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_GraphicsDispose($hGraphic)
    $hImage = _GDIPlus_BitmapCloneArea($hBitmap, 0, 0, $iW, $iH, $GDIP_PXF32ARGB)
    _GDIPlus_BitmapDispose($hBitmap)

    $tBitmapData = _GDIPlus_BitmapLockBits($hImage, 0, 0, $iW, $iH, $GDIP_ILMWRITE, $GDIP_PXF32ARGB)
    $iStride = DllStructGetData($tBitmapData, "stride")
    $iScan0 = DllStructGetData($tBitmapData, "Scan0")


    Local $v_BufferA = DllStructCreate("byte[" & $iH * $iW * 4 & "]", $iScan0) ; Create DLL structure for all pixels
    Local $AllPixels = DllStructGetData($v_BufferA, 1)
    Local $sREResult1 = StringRegExpReplace(StringTrimLeft($AllPixels, 2), "(.{8})", "\1 ")
    Local $sPix = "0x" & StringStripWS(StringRegExpReplace($sREResult1, _
            "(?i)([^0][0-9a-f]{7} )|([0-9a-f][^0][0-9a-f]{6} )|([0-9a-f]{2}[^0][0-9a-f]{5}FF )|([0-9a-f]{3}[^0][0-9a-f]{4} )|([0-9a-f]{4}[^0][0-9a-f]{3} )|([0-9a-f]{5}[^0][0-9a-f]{2} )|([0-9a-f]{6}[^f]{2} )", " FFFFFFFF "), 8)

    $AllPixels = DllStructSetData($v_BufferA, 1, $sPix)

    _GDIPlus_BitmapUnlockBits($hImage, $tBitmapData)
    _GDIPlus_ImageSaveToFile($hImage, $sOutFile)
    _GDIPlus_ImageDispose($hImage)
    _GDIPlus_Shutdown()
EndFunc ;==>_ImageNonBlackToWhite
;

The second example uses raster operation code in the _WinAPI_BitBlt function. This script is more of a proof of concept than a practical working example.

This script was modified from the script from here.

#include <WinAPI.au3>
#include <ScreenCapture.au3>
#include <GDIPlus.au3>
#include <GUIConstants.au3>
#include <WindowsConstants.au3>
#include <misc.au3>

Global $iX = 0, $iY = 0, $iWidth = 600, $iHeight = 400, $iH, $iW
; Modified from http://www.autoitscript.com/forum/index.php?showtopic=77580&view=findpost&p=561542
Global $iTransparentColor = 0x000000 ;; = 0x3A6EA5 ;0xFFFFFF ;
;if Not IsNumber($iTransparentColor) Then $iTransparentColor = "0x" & Hex(PixelGetColor(3,3),6) ;GetPixel($hGUI2,3,3)
BitmapMasking(@ScriptDir & "\test.png", 0, 0, $iWidth, $iHeight)
;ShellExecute(@DesktopDir & "\test.png")

While GUIGetMsg() <> -3
    Sleep(10)
WEnd

Func BitmapMasking($sFileName = "", $iX=0, $iY=0 , $iWidth=10 , $iHeight=10 )
    Local $hWnd, $hDDC, $hCDC, $hBMP, $aIcon, $hIcon

    $iW = $iWidth
    $iH = $iHeight
    $hWnd = _WinAPI_GetDesktopWindow()
    $hDDC = _WinAPI_GetDC($hWnd)
    $hCDC = _WinAPI_CreateCompatibleDC($hDDC)
    $hBMP = _WinAPI_CreateCompatibleBitmap($hDDC, $iW, $iH)
    _WinAPI_SelectObject($hCDC, $hBMP)

    ; Create GUI for Color Mask
    $GUICompDir = GUICreate("Color Mask", $iWidth, $iHeight, 0, 0)
    WinSetTrans("Color Mask", "", 255)
    GUISetBkColor($iTransparentColor, $GUICompDir) ;<=== TransparentColor ==
    GUISetState()
    $hDDC1 = _WinAPI_GetDC($GUICompDir)
    $hCDC1 = _WinAPI_CreateCompatibleDC($hDDC1)
    $hBMP1 = _WinAPI_CreateCompatibleBitmap($hDDC1, $iW, $iH)
    _WinAPI_SelectObject($hCDC1, $hBMP1)

    ; Create GUI for B/W Mask
    $hGUI = GUICreate("B/W Mask", $iWidth, $iHeight, -1, @DesktopHeight / 2)
    ;WinSetTrans("B/W Mask", "", 254)
    GUISetState()
    $hDDC2 = _WinAPI_GetDC($hGUI)
    $hCDC2 = _WinAPI_CreateCompatibleDC($hDDC2)
    $hBMP2 = _WinAPI_CreateCompatibleBitmap($hDDC2, $iW, $iH)
    _WinAPI_SelectObject($hCDC2, $hBMP2)

    ; Create GUI
    $hGUIRes = GUICreate("Result", $iWidth, $iHeight, @DesktopWidth / 2, 10)
    GUISetState()
    $hDDC3 = _WinAPI_GetDC($hGUIRes)
    $hCDC3 = _WinAPI_CreateCompatibleDC($hDDC3)
    $hBMP3 = _WinAPI_CreateCompatibleBitmap($hDDC3, $iW, $iH)
    _WinAPI_SelectObject($hCDC3, $hBMP3)

    ; A one bit per pixel bitmap
    $hBitmapMask = _WinAPI_CreateBitmap($iW, $iH, 1, 1, 0)
    $hdcMem = _WinAPI_CreateCompatibleDC(0);
    _WinAPI_SelectObject($hdcMem, $hBitmapMask);
    ;MsgBox(0,"","")

    ; The GUI associated with $hDDC1 has the background color set black,
    ; and, $hDDC is the handle of the display device context for the captured desktop area.
    _WinAPI_BitBlt($hDDC1, 0, 0, $iW, $iH, $hDDC, $iX, $iY, $SRCCOPY)   ; Direct copy
    ;MsgBox(0,"","")

    _WinAPI_BitBlt($hdcMem, 0, 0, $iW, $iH, $hDDC1, $iX, $iY, $SRCCOPY) ; Direct copy

    ; Color mask - Has black where black will be
    _WinAPI_BitBlt($hDDC1, 0, 0, $iW, $iH, $hdcMem, $iX, $iY, $SRCINVERT) ;XOR operator

    ; Black/White Mask - Has white where the black will be, all other colors appear black.
    _WinAPI_BitBlt($hDDC2, 0, 0, $iW, $iH, $hdcMem, $iX, $iY, $SRCINVERT) ; XOR operator
    ;MsgBox(0,"","")

    _WinAPI_BitBlt($hDDC2, 0, 0, $iW, $iH, $hDDC1, $iX, $iY, $PATINVERT) ; XOR operator
    ;MsgBox(0,"","")

    ; Invert mask window and copy to Result window
    _WinAPI_BitBlt($hDDC3, 0, 0, $iW, $iH, $hDDC2, $iX, $iY, $SRCINVERT) ; XOR operator


    ; Copy Dislpay DC ($hDDC3) to memory DC ($hCDC3) also known as $hBMP3
    _WinAPI_BitBlt($hCDC3, 0, 0, $iW, $iH, $hDDC3, $iX, $iY, $SRCCOPY)  ; Direct copy

    _WinAPI_ReleaseDC($hWnd, $hDDC)
    _WinAPI_DeleteDC($hCDC)
    _WinAPI_ReleaseDC($GUICompDir, $hDDC1)
    _WinAPI_DeleteDC($hCDC1)
    _WinAPI_ReleaseDC($hGUI, $hDDC2)
    _WinAPI_DeleteDC($hCDC2)
    _WinAPI_ReleaseDC($hGUIRes, $hDDC3)
    _WinAPI_DeleteDC($hCDC3)
    _WinAPI_DeleteObject($hBMP)
    _WinAPI_DeleteObject($hBMP1)
    _WinAPI_DeleteObject($hBMP2)
    _WinAPI_DeleteObject($hBitmapMask)

    If $sFileName = "" Then Return $hBMP3
    _ScreenCapture_SaveImage($sFileName, $hBMP3)
    _WinAPI_DeleteObject($hBMP3)

    ;If FileExists($sFileName) Then ShellExecute($sFileName)

EndFunc ;==>BitmapMasking

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