Jump to content

Image capture script works perfectly the first time...


Recommended Posts

Can anyone venture a suggestion as to why this script behaves the way it does? I think it's something to do with control styles, which I find impenatrable even after two hours of trying to work them out.

Instructions:

Click the "capture" button

Find a region of the desktop that's pretty

Move the mouse to the top-left corner of the region and press F1

Move the mouse to the bottom right corner of the region and press F1

Image appears in the script's window

Works perfectly the first time; on subsequent times, the image isn't in the right position or the right size :)

help.au3

Link to comment
Share on other sites

Welcome to the forums.

The position is fine, it's the size that needs to be changed.

Just add the dimensions to your positioning line in RefreshImage()...

GUICtrlSetPos($Mwin_imagebox, $Mwin_imagebox_xposition, $Mwin_imagebox_yposition, $Image_width, $Image_height)

(You don't need to zero it out first, so the preceding GUICtrlSetPos line is unnecessary)

Nice script, btw.

[font="Tahoma"]"Tougher than the toughies and smarter than the smarties"[/font]

Link to comment
Share on other sites

Thanks! Does this really work on your computer? When I add your line, the captured image is always blurry - as though AutoIT has attempted to resize it. Without your line, it's perfect at least the first time.

Edited by annelinn
Link to comment
Share on other sites

Thanks! Does this really work on your computer? When I add your line, the captured image is always blurry - as though AutoIT has attempted to resize it. Without your line, it's perfect at least the first time.

Now that you mention it, I did notice the blurriness.

I checked the saved BMP's, and they were fine, so that narrows it down to a display issue.

It turns out that the Width and Height you calculated are off by one. Here's why:

$Image_width = ($bottom_x - $top_x + 1)

$Image_height = ($bottom_y - $top_y + 1)

After removing the +1s, the pic is sized properly and the blur is gone.

[font="Tahoma"]"Tougher than the toughies and smarter than the smarties"[/font]

Link to comment
Share on other sites

It turns out that the Width and Height you calculated are off by one. Here's why:

After removing the +1s, the pic is sized properly and the blur is gone.

Still no dice! Despite making both your suggested changes, I still see a blurry and mis-positioned picture, either the first time or all times.

Does your copy of help.au3 look exactly like mine (attached) ? If so, it might perhaps be a non-AutoIT problem.

Additionally: I don't understand why removing the -1 is right. If I choose an image from coordinates (1,1) to (10,10), the width is 10 pixels - but $Image_width = ($bottom_x - $top_x) would give a width of 9 pixels.

Removing the -1 does seem to set the width to the actual width of the bitmap, but it's a mystery why.

help.au3

Edited by annelinn
Link to comment
Share on other sites

Trashing and redefining the $Mwin_imagebox control at the beginning of the RefreshImage() paragraph seems to change the behavior. Also, according to the helpfile, _ScreenCapture_Capture either writes the image to disk, or returns a handle to the image in memory. I'm thinking the $Image_handle variable is superfluous? Try adding this:

Func RefreshImage()
    GUICtrlDelete($Mwin_imagebox)
    $Mwin_imagebox =    GUICtrlCreatePic("", 10, 10, 0, 0, $SS_SUNKEN)  
    $Mwin_imagebox_xposition = 10 + Floor(($Mwin_imagebox_maxwidth - $Image_width) / 2)

Better yet, just change these two lines:

GUICtrlSetPos($Mwin_imagebox, 0, 0, $Image_width, $Image_height)
    GUICtrlSetPos($Mwin_imagebox, $Mwin_imagebox_xposition, $Mwin_imagebox_yposition)

to

GUICtrlSetPos($Mwin_imagebox, $Mwin_imagebox_xposition, $Mwin_imagebox_yposition, $Image_width, $Image_height)

Edit: Worse yet! The second option does ensure the proper image size and coordinates, but also adds the "blur". Only the first option, destroying and recreating the control, maintains a crisp image.

Edited by Spiff59
Link to comment
Share on other sites

Still no dice! Despite making both your suggested changes, I still see a blurry and mis-positioned picture, either the first time or all times.

Does your copy of help.au3 look exactly like mine (attached) ? If so, it might perhaps be a non-AutoIT problem.

Mine doesn't match... You need to change $Image_width/$Image_height, not $width/$height.

Additionally: I don't understand why removing the -1 is right. If I choose an image from coordinates (1,1) to (10,10), the width is 10 pixels - but $Image_width = ($bottom_x - $top_x) would give a width of 9 pixels.

Removing the -1 does seem to set the width to the actual width of the bitmap, but it's a mystery why.

I'm not sure why one pixel needs to be removed. I was just comparing the result against what MSPaint thought the dimensions were. After making that adjustment, the image displayed properly.

Here's what I have:

CODE
#include <GUIConstants.au3>

#include <Date.au3>

#include <GuiEdit.au3>

#Include <ScreenCapture.au3>

#include <StaticConstants.au3>

; Script variables

Global $Script_name = "photographer"

Global $Script_version = "1"

; Window variables

Global $Mwin_width = 800

Global $Mwin_height = 550

Global $Mwin_handle

Global $Mwin_imagebox

Global $Mwin_imagebox_maxwidth = 780

Global $Mwin_imagebox_maxheight = 300

Global $Mwin_imagebox_xposition

Global $Mwin_imagebox_yposition

Global $Mwin_imagebox_info[5 + 1]

Global $Mwin_imagebox_label[5 + 1]

; Image variables

Global $Image_handle

Global $Image_currentfile

Global $Image_checksum

Global $Image_width

Global $Image_height

Global $Image_count = 0

; Buttons

Global $Mwin_maxbuttons = 4

Global $Mwin_button[$Mwin_maxbuttons + 1]

; Misc variables

Global $Misc_exitscriptflag = 0

; Set the hotkey for taking photos and exiti

HotKeySet("{F1}", "Hotkey_TakePhoto")

HotKeySet('{esc}', "Hotkey_Escape")

Global $Keypress

Opt("MouseCoordMode", 0)

; Main script

; -----------

CreateMainWindow()

Do

CheckButtons()

CheckCursor()

Until $Misc_exitscriptflag = 1

Exit

Func CreateMainWindow()

; Create the main window

$Mwin_handle = GuiCreate($Script_name & " v" & $Script_version, $Mwin_width, $Mwin_height)

GUISetState(@SW_SHOW)

; Create an area for displaying captured images

$Mwin_imagebox = GUICtrlCreatePic("", 10, 10, 0, 0, $SS_SUNKEN)

; Create info boxes to describe it

$Mwin_imagebox_info[1] = GUICtrlCreateInput("", 10, ($Mwin_imagebox_maxheight + 20), 90, 20, $ES_READONLY)

$Mwin_imagebox_label[1] = GUICtrlCreateLabel("Checksum", 10, ($Mwin_imagebox_maxheight + 40), 90, 20, $ES_READONLY)

$Mwin_imagebox_info[2] = GUICtrlCreateInput("", 110, ($Mwin_imagebox_maxheight + 20), 40, 20, $ES_READONLY)

$Mwin_imagebox_label[2] = GUICtrlCreateLabel("Width", 110, ($Mwin_imagebox_maxheight + 40), 40, 20, $ES_READONLY)

$Mwin_imagebox_info[3] = GUICtrlCreateInput("", 160, ($Mwin_imagebox_maxheight + 20), 40, 20, $ES_READONLY)

$Mwin_imagebox_label[3] = GUICtrlCreateLabel("Height", 160, ($Mwin_imagebox_maxheight + 40), 40, 20, $ES_READONLY)

$Mwin_imagebox_info[4] = GUICtrlCreateInput("", 210, ($Mwin_imagebox_maxheight + 20), 90, 20, $ES_READONLY)

$Mwin_imagebox_label[4] = GUICtrlCreateLabel("Image file", 210, ($Mwin_imagebox_maxheight + 40), 90, 20, $ES_READONLY)

$Mwin_imagebox_info[5] = GUICtrlCreateInput("", 310, ($Mwin_imagebox_maxheight + 20), 80, 20, $ES_READONLY)

$Mwin_imagebox_label[5] = GUICtrlCreateLabel("Cursor", 310, ($Mwin_imagebox_maxheight + 40), 80, 20, $ES_READONLY)

; Create buttons

$Mwin_button[1] = GUICtrlCreateButton("Capture", 10, ($Mwin_imagebox_maxheight + 70), 80, 20)

Return "success"

EndFunc

Func CheckButtons()

; Check the buttons

$msg = GUIGetMsg()

; React to mouse clicks

Select

Case $msg = $GUI_EVENT_CLOSE

$Misc_exitscriptflag = 1

Return "exit"

Case $msg = $Mwin_button[1]

CaptureImage()

EndSelect

Return "success"

EndFunc

Func CheckCursor()

; If cursor is above the image, display the cursor position

$position = MouseGetPos()

; Correct for the window border

$position[0] = $position[0] - 4

$position[1] = $position[1] - 23

If $position[0] >= $Mwin_imagebox_xposition AND $position[0] <= ($Mwin_imagebox_xposition + $Image_width - 1) AND $position[1] >= $Mwin_imagebox_yposition AND $position[1] <= ($Mwin_imagebox_yposition + $Image_height - 1) Then

; The mouse is over the image

$xpos = $position[0] - $Mwin_imagebox_xposition + 1

$ypos = $position[1] - $Mwin_imagebox_yposition + 1

GUICtrlSetData($Mwin_imagebox_info[5], $xpos & "x" & $ypos & "(" & $Mwin_imagebox_xposition & "x" & $Mwin_imagebox_yposition & ")")

Else

GUICtrlSetData($Mwin_imagebox_info[5], "")

EndIf

Return "success"

EndFunc

Func CaptureImage()

Opt("MouseCoordMode", 1)

$Keypress = ""

Do

$xy = MouseGetPos()

$currentpixel = PixelGetColor($xy[0],$xy[1])

ToolTip("Click the top-left corner" & @LF & "Pixel color = " & $currentpixel & @LF & "Coords " & $xy[0] & "x" & $xy[1])

Sleep(100)

Until $Keypress <> ""

If $Keypress = "escape" Then

Opt("MouseCoordMode", 0)

Return "fail"

Else

$top_x = $xy[0]

$top_y = $xy[1]

EndIf

$Keypress = ""

Do

$xy = MouseGetPos()

$currentpixel = PixelGetColor($xy[0],$xy[1])

ToolTip("Click the bottom-right corner" & @LF & "Pixel color = " & $currentpixel & @LF & "Coords " & $xy[0] & "x" & $xy[1])

Sleep(100)

Until $Keypress <> ""

If $Keypress = "escape" Then

Return "fail"

Else

$bottom_x = $xy[0]

$bottom_y = $xy[1]

$width = $bottom_x - $top_x + 1; <- Left this alone

$height = $bottom_y - $top_y + 1; <- Left this alone

EndIf

If $width > $Mwin_imagebox_maxwidth OR $height > $Mwin_imagebox_maxheight Then

ToolTip("Image is too big!" & @LF & "Image: " & $width & "x" & $height & ", max: " & $Mwin_imagebox_maxwidth & "x" & $Mwin_imagebox_maxheight)

Sleep(2000)

ToolTip("")

Else

$Image_count = $Image_count + 1

$Image_currentfile = "image-" & $Image_count & ".bmp"

$Image_handle = _ScreenCapture_Capture($Image_currentfile, $top_x, $top_y, $bottom_x, $bottom_y)

$Image_checksum = PixelChecksum($top_x, $top_y, $bottom_x, $bottom_y)

$Image_width = ($bottom_x - $top_x) ; <- Removed the +1

$Image_height = ($bottom_y - $top_y) ; <- Removed the +1

; Show the image in the main window

RefreshImage()

ToolTip("Captured " & $Image_width & "x" & $Image_height & " image" & @LF & "Checksum " & $Image_checksum)

Sleep(2000)

ToolTip("")

EndIf

Opt("MouseCoordMode", 0)

Return "success"

EndFunc

Func RefreshImage()

Local $xposition, $yposition

$Mwin_imagebox_xposition = 10 + Floor(($Mwin_imagebox_maxwidth - $Image_width) / 2)

$Mwin_imagebox_yposition = 10 + Floor(($Mwin_imagebox_maxheight - $Image_height) / 2)

GUICtrlSetPos($Mwin_imagebox, 0, 0)

; GUICtrlSetPos($Mwin_imagebox, $Mwin_imagebox_xposition, $Mwin_imagebox_yposition)

GUICtrlSetPos($Mwin_imagebox, $Mwin_imagebox_xposition, $Mwin_imagebox_yposition, $Image_width, $Image_height)

GUICtrlSetImage($Mwin_imagebox, $Image_currentfile)

GUICtrlSetData($Mwin_imagebox_info[1], $Image_checksum)

GUICtrlSetData($Mwin_imagebox_info[2], $Image_width)

GUICtrlSetData($Mwin_imagebox_info[3], $Image_height)

GUICtrlSetData($Mwin_imagebox_info[4], $Image_currentfile)

EndFunc

Func Hotkey_TakePhoto()

; Whenever the hotkey is pressed, sets the global variable $Keypress

$Keypress = "takephoto"

EndFunc

Func Hotkey_Escape()

; Whenever the hotkey is pressed, sets the global variable $Keypress

$Keypress = "escape"

EndFunc

@Spiff59: Trashing/recreating does work, because of the behavior of the 0 sizes in GUICtrlCreatePic. In my testing, it was one of the solutions that worked for me before I discovered the pixel difference. It's too bad that auto-sizing functionality isn't available via GUICtrlSetPos or some other function. (afaik)

Good luck!

[font="Tahoma"]"Tougher than the toughies and smarter than the smarties"[/font]

Link to comment
Share on other sites

Thank you all! Both your proposed solutions work perfectly. I will think clearly about my misunderstanding of single pixels when I have a clear head.

In case you'd like to see the latest version of the script, it's included as an attachment to this post.

@Spiff59, about $Image_handle: I spent two days scratching my head, wondering why PixelSearch(.... $some_bitmap_handle) didn't work, before realising that PixelSearch and Pixelchecksum only work with window handles.

I haven't given up hope of finding a way to search the original bitmap handle or the original bitmap file directly, rather than using PixelSearch / Pixelchecksum to read whatever happens to be on the screen right now. That would allow the script to work even when the whole image isn't visible on the desktop.

JScrape.au3

Link to comment
Share on other sites

I haven't given up hope of finding a way to search the original bitmap handle or the original bitmap file directly, rather than using PixelSearch / Pixelchecksum to read whatever happens to be on the screen right now. That would allow the script to work even when the whole image isn't visible on the desktop.

You should be able to do this with _GDIPlus_BitmapLockBits... I'll see what I can come up with.

Also, to make the characters more legible, I set the font on the EditBox to a fixed-width font (Courier New), and changed the "1"s to spaces.

[font="Tahoma"]"Tougher than the toughies and smarter than the smarties"[/font]

Link to comment
Share on other sites

Also, to make the characters more legible, I set the font on the EditBox to a fixed-width font (Courier New), and changed the "1"s to spaces.

How did you do that? I had given up hope of ever finding a way to change that font.

EDIT: Oh. GuiCtrlSetFont

Edited by annelinn
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...