Jump to content
Sign in to follow this  
corgano

GDIplus crashes without error on running function twice

Recommended Posts

corgano

This is a script that finds the black borders of an image. It accomplishes this by rotating the page so the side it wants to work on is on the top, measures down, and then rotates it back - until it stopped working.

When I run it the first time, it works and returns the correct value. However, when I run it for another side, autoit crashes without giving an error :/ The side I run first / second doesn't matter, even the same side running twice crashes it.  Any ideas?

#include <GDIPlus.au3>
#include <Array.au3>
; not sure if this one is needed
#include <WindowsConstants.au3>


_GDIPlus_Startup()

$hImage = _GDIPlus_ImageLoadFromFile($Jpg)

$Bottom = Image_getBlackBorder($hImage, "Bottom", $Threshold)
$Right = Image_getBlackBorder($hImage, "Right", $Threshold)
$Left = Image_getBlackBorder($hImage, "Left", $Threshold)
$Top = Image_getBlackBorder($hImage, "Top", $Threshold)


_GDIPlus_Shutdown()


Func Image_getBlackBorder($hImage, $sSide = "Top", $Threshold = 97.5 )
    Local $iRotateFlipType = SideGetIRF($sSide)
    _GDIPlus_ImageRotateFlip($hImage, $iRotateFlipType)

    Local $step, $iX, $iY, $count, $similarity, $Black[4] = ["000000","00","00","00"]
    Local $iHeight = _GDIPlus_ImageGetHeight($hImage), $iWidth = _GDIPlus_ImageGetWidth($hImage)
    Local $hGraphics = _GDIPlus_ImageGetGraphicsContext($hImage)

    $iX = $iWidth/2
    $iY = 10

    ConsoleWrite($sSide&"   ")

    For $iSteps = 20 to 400 Step 20
        $CurrentStep = $iHeight*2/3/$iSteps

        $hPen = _GDIPlus_PenCreate("0xFF00FFFF", 3)
        _GDIPlus_GraphicsDrawLine($hGraphics, $iX-20, $iY, $iX - $iSteps, $iY, $hPen)
        _GDIPlus_PenDispose($hPen)

;~      ConsoleWrite($iY&" to "&$iHeight*2/3&" step "&$CurrentStep&"    "&$iHeight&@CRLF)
    For $iY = $iY to $iHeight*2/3 Step $CurrentStep

        $similarity = ColorCheckSim($Black, _GDIPlus_BitmapGetPixel($hImage, $iX, $iY))
        $temp = $similarity[0]-(100-(100-$Threshold)*2)
        If $temp > 10 then $temp = 10
        if $temp < 0 Then $temp = 0
        $hPen = _GDIPlus_PenCreate("0xFF" & valuetoredgreen(100-($temp*10) ), 3)
        _GDIPlus_GraphicsDrawLine($hGraphics, $iX+20, $iY, $iX + $iSteps, $iY, $hPen)
        _GDIPlus_PenDispose($hPen)
;~      If $sSide = "Bottom" Then ConsoleWrite("    "&$iY&" "&$similarity[0]&"  "&$temp&@CRLF)
        If $similarity[0] < $Threshold Then
            $iY -= $CurrentStep
            ExitLoop
        EndIf
    Next

    If $iY < 0 Then $iY = 0
;~  ConsoleWrite(@CRLF)
    Next


    _GDIPlus_ImageRotateFlip($hImage, mod(4-$iRotateFlipType,4))

    _GDIPlus_GraphicsDispose($hGraphics)

    ConsoleWrite($iY&@CRLF)
    Return $iY
EndFunc


Func valuetoredgreen($num)
    $red = Round(510 - (2.55 * $num * 2))
    $green = Round(2.55 * $num * 2)
    If $red > 255 Then $red = 255
    If $green > 255 Then $green = 255
;~  ConsoleWrite($num&" "&$red&"    "&$green&@CRLF)
    Return Hex($red, 2) & Hex($green, 2) & "00"
EndFunc   ;==>valuetoredgreen

;100 = same, 0 = completely different
Func ColorCheckSim($c1, $c2)
;~  ConsoleWrite($c1&"  "&$c2&@CRLF)
    Local $aDif[4], $a, $b
    For $i = 1 To 3
        $a = Dec(StringMid($c1, ($i * 2) - 1, 2))
        $b = Dec(StringMid($c2, ($i * 2) - 1, 2))
        $aDif[$i] = 100 - (Abs($a - $b) / 2.55)
;~      ConsoleWrite($i&"   "&$aDif[$i]&@CRLF)
    Next
;~  ConsoleWrite($aDif[1]&" "&$aDif[2]&"    "&$aDif[3]&@CRLF)
    $aDif[0] = Round(($aDif[1] + $aDif[2] + $aDif[3]) / 3, 2)
    Return $aDif
EndFunc   ;==>ColorCheckSim

Func ColorStringtoArray($Color)
    Local $aRet[4]
    $aRet[0] = $Color
    $aRet[1] = StringLeft($Color, 2)
    $aRet[2] = StringMid($Color, 3, 2)
    $aRet[3] = StringRight($Color, 2)
    Return $aRet
EndFunc

Func _GDIPlus_ImageRotateFlip($hImage, $iRotateFlipType)
    Local $aResult = DllCall($ghGDIPDll, "uint", "GdipImageRotateFlip", "hwnd", $hImage, "int", $iRotateFlipType)

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


Func _GDIPlus_BitmapGetPixel($hImage, $iX, $iY)
    Local $tArgb, $pArgb, $aRet
    $tArgb = DllStructCreate("dword Argb")
    $pArgb = DllStructGetPtr($tArgb)
    $aRet = DllCall($ghGDIPDll, "int", "GdipBitmapGetPixel", "hwnd", $hImage, "int", $iX, "int", $iY, "ptr", $pArgb)
    Return Hex(DllStructGetData($tArgb, "Argb"), 6)
EndFunc   ;==>_GDIPlus_BitmapGetPixel
Edited by corgano

0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e

Share this post


Link to post
Share on other sites
Danp2

Seems like you are missing the appropriate calls to _GDIPlus_Startup and _GDIPlus_Shutdown.

Also, it's unclear where the script is crashing. Is it when you run the script a 2nd time or on your 2nd call to the Image_getBlackBorder function?

Share this post


Link to post
Share on other sites
corgano

I always keep looking into problems after I post them

I re-ran the script with a different set of images, it works flawlessly. Re-ran with the set I was working on, and it crashes at this function

Func _GDIPlus_BitmapGetPixel($hImage, $iX, $iY)
    Local $tArgb, $pArgb, $aRet
    $tArgb = DllStructCreate("dword Argb")
    $pArgb = DllStructGetPtr($tArgb)
    $aRet = DllCall($ghGDIPDll, "int", "GdipBitmapGetPixel", "hwnd", $hImage, "int", $iX, "int", $iY, "ptr", $pArgb)
    Return Hex(DllStructGetData($tArgb, "Argb"), 6)
EndFunc   ;==>_GDIPlus_BitmapGetPixel

note, this only happens the SECOND time the Image_getBlackBorder() function is called, and this passes ~fifty times from the first run, but the second time the Image_getBlackBorder() function is called it gets to the first _GDIPlus_BitmapGetPixel() and it fails. WHY? It just worked with the exact same image half a second ago, fifty times, without any issues! Why does autoit crash now?

And even stranger, I open the source image in MSPaint, re-save it, and the program runs without issue. This baffles me because:

1: If it was an issue with the image, why does the first call to Image_getBlackBorder() work and the second one doesn't???

2: If it is a coding issue then the first call shouldn't work either, but it does

I am severely confused. Is this a bug in autoit? In the GDI udf?


0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e

Share this post


Link to post
Share on other sites
corgano

Seems like you are missing the appropriate calls to _GDIPlus_Startup and _GDIPlus_Shutdown.

Also, it's unclear where the script is crashing. Is it when you run the script a 2nd time or on your 2nd call to the Image_getBlackBorder function?

Lol I realized that, I had them in the main script, and copied the functions over. I must have forgot to add them, thanks :P

The script crashes on the second call to Image_getBlackBorder, inside the first call to _GDIPlus_BitmapGetPixel() as such

call Image_getBlackBorder() for top

It loops, using _GDIPlus_BitmapGetPixel() several times without crashing

Returns

call Image_getBlackBorder() for right this time

It gets to the loop, but hard crashes at the first _GDIPlus_BitmapGetPixel()

Edited by corgano

0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e

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
Sign in to follow this  

  • Similar Content

    • mdepot
      By mdepot
      I have a situation where I am repeatedly capturing a region of the screen and feeding it into Tesseract OCR.  Since the OCR is a relatively slow operation, I would like to create an in memory cache of the ocr results.  An ideal hash key for this cache would be a checksum of the captured image.  With this I could capture the region, checksum it, and then only if I don't get a cache hit I would write the image out to disk for external OCR.
      Now I know I can do this by saving the captured image out to disk, and then summing the disk file with _Crypt_HashFile().  But that's still slower than I would like, and it shouldn't be necessary.  Ideally, it should be possible to checksum the image data directly in memory so I don't have to go to disk at all.  In order to do that, I need a way to dump a representation of the image into a string  (or some equivalent).  Then I could use the _Crypt_HashData() function against that string to create my cache hash key.
      Googling around I found an article here that shows a way to convert an image object to a byte array using System.Drawing.  This was the closest thing I found to what I'm trying to do.  I don't know if that method could be used from within AutoIT, or if perhaps there may be a better way I don't know about.  If someone could give me a shove in the right direction it would be a big help.  Thanks!
    • UEZ
      By UEZ
      Here some graphical examples written completely in FreeBasic just for fun.  
      3D Starfield Rotating Flight 3D Starfield Scrolling v1 Booster 3D Starfield Scrolling v3 Booster CreateWindowEx (hGUI) Example FB File2Bas Code Generator (AutoIt script) FB GFX Examples Fire Particles FMOD Examples GDI - GDI+ 3D Sinus Wave GDI - GDI+ Animated Pythagoras Tree GDI - GDI+ Particles - Repulsive Force Sim v2.0 GDI - GDI+ Plasma v5 Booster GDI - GDI+ Random Pattern GDI - GDI+ Space Flight GDI - GDI+ Tunnel Flight - WipeOut Style GDI Classic Raytraced Tunnel GDI Elastic Twister Effect GDI Exploding Pixels GDI Infinite Image Zoom Flight GDI Liquid Pixels GDI Particle Repulsion Grid GDI Particles Mouse Attraction GDI Starfield GDI The Nautilus Raymarcher GDI Worm Tunnel Flight GDI+ Impossible Possible GDI+ Kaleidoscope GDI+ Performance Test - Au3 vs FB GDI+ Polar Clock GDI+ Rotating Earth GDI+ Star Wars Scroller GDI+ Streamer GDI+ Swiss Railway Clock Ini Read - Write Mandelbrot Plasma Puristic Clock Rutt_Etra_Izer_Booster Tunnel Flight uFMOD _WinAPI_SetWindowTitleIcon  
      Download: FreeBasic Examples build 2018-07-10.rar
       
      I will add new examples from time to time.
       
      FreeBasic source codes are also included.
       
    • Atoxis
      By Atoxis
      Howdy, I've gone through a lot of au3 forums, and I once had a working Imagesearch script that I got from here.  However, and i'm just totally not sure how but my imagesearch scripts aren't working anymore.
      I'm not new to au3 but i'm not the most experienced with it's syntax/commands.

      Anyways, I've looked over the big threads involving imagesearch.

      Does anyone have a working Imagesearch x64 for win10 that is currently working as of the date with the post.

      Dll's and what not is fine, just when I tell the script to run, I want to be able to find the image on the screen!
      Can't find a working copy so if anyone has one please send it my way lol.

      I've taken all the imagesearch downloads and what not and have played with them but I can't get any of them working on my end, despite others saying they're working.
      Thanks.
    • Xandy
      By Xandy
      MapIt is a tile world editor.  MapIt was built around the concept of reversing Dragon Warrior map images.  MapIt can take image input and produce a tile and world array.
      MapIt features Unity style dragable labels that adjust property values.

      MapParser is a C++ project that scans images for unique tiles.  MapParser is very fast.  Due to hard drive failure, many bugs were restored b/c I had to rewind many years.  Frustrated with the design, I wrote a new version from the ground up.  This New Version:  AutoIt Front-end, command line controls, and shared with the world; so that I can't lose it again.
      You can toggle the C++ MapParser off to see the difference in speeds between the MapParser CPP verse AutoIt function.  Function is named Scan_Tiles() in AutoIt.  You can also chose to download without MapParser.exe.
      At the moment Scanning a image resets the arrays, but you can add tiles after scanning.
      Images can be added as tiles without scan image at all.  Then configure settings to give your world parameters and manually fill the world data with tile indexes.
      Using the settings you can change tile size after a scan.  Example: you wanted to replace a map with different sized tiles.
      Changing and replacing tile / world data is easy.  B/c tile world editor.

      Hotkeys, I use CTRL+R in image above to signal replace tile action and I use "G" to Get the tile under mouse.
      Hotkeys are not saved to disk and thus are set to default between sessions.
      I might draw the world to pre-rendered surfaces and use them as multi-layer someday.  I do that in my AutoIt, DragonWarrior Remake but I could spend forever unsure what features are important for this.  The DW_Remake has a method of replacing a tile with a tile on two layers.  So you could replace a tree on the first layer with a grass, and a tree in the second layer.  This is all getting very confusing.
      I attempted to write the good code.  If something could be better, please advise.
      Fifth release.  Enjoy.
      For download, videos, and example of created world file data; please visit the MapIt webpage: http://songersoft.com/programming/mapit/mapit_about.phtml
      Special thanks: @AdmiralAlkex, @Melba23, @MrCreatoR
      Main AutoIt source file: Will not run without other Includes and SDL DLLs.
      Last Update: 5/26/2018 3:45 PM EST
      REMOVED CODE BLOCK:  I was informed the this page loaded very slowly, one solution so far has been to remove the 2k lines in the code block.
      When I recieve more feedback from the User I may reduce image size or remove images.
      Next Version Added: $eSETTING_TILE_LAST_PATH I have the weekend, I want to write world layers with aBoard surfaces.  
    • lenclstr746
      By lenclstr746
      HELLO GUYS
      I'm a work on a background see and click bot project 
      I can complete it if your help me
      (using imagesearch , gdi+ and  fastfind)
×