Jump to content

screen capture problems


Recommended Posts

I wrote a simple program that continuously takes pictures of a portion of my screen, and then saves those pictures to a given location on my hard drive. The operation of the program is simple. After you start the program, you let it run for as long as you need. You hit the "escape" button when you want it to stop taking pictures. The program gives a message telling you how many pictures it took. After you click "okay", the program saves the pictures to the hard drive. Because I don't need it to run for very long (less than five minutes), I designed it to temporarily store the pictures in an array with a fixed size (50000), before saving those pictures to the drive. Here's the script for my program.

#Include <ScreenCapture.au3>

#Include <WinAPI.au3>

Dim $A[50000]

Global $control

HotKeySet("{ESC}","capture2")

$control = 0

$n = 0

while $control <> 2

$A[$n] = _ScreenCapture_Capture("",300,121,396,241)

$n = $n + 1

WEnd

$n = $n - 1

MsgBox(0,"number of pictures taken",$n)

$t = 0

while $t <= 49999

if $t <= $n Then

$argument = StringReplace ("f:\location1\pictureW.bmp","W",$t+1)

_ScreenCapture_SaveImage($argument,$A[$t],True)

Else

_WinAPI_DeleteObject($A[$t])

EndIf

$t = $t + 1

WEnd

Func capture2()

$control = 2

EndFunc

Here's the problem. When I run this program, it will only save a portion of the pictures. One time it saved pictures 3 through 9945. This last time, it saved pictures 1 through 9945 and 10971 through 11349. If you run this program for 30 seconds, you'll see that it takes a lot more pictures than 9945, or 11349. Also, what happened to pictures 1 and 2? The second time I ran it, why did it skip pictures 10972 through 11348? Where are the rest of them? Also, it tends to stop at 9945 a lot. Why? I don't understand why this program behaves this way. Any ideas why this happens? What can I do to fix it?

I originally wrote this program so that it would save pictures to the hard drive, one at a time, as it took the pictures. It would take a picture, then save it, take another picture, then save it, and so on. However, this process leaves too long of a gap in time between pictures. It never "lost" any of the pictures, but it couldn't capture the pictures quickly enough. So the approach of saving the pictures as it takes them, isn't an option.

I must also say that this program takes a really long time saving the pictures. I ran the program for 30 seconds before hitting "escape". It took over 9 minutes to save the pictures that it did save. This is probably due to the fact that it deletes the unused portion of the array one element at a time. Is there a faster way to delete the unused elements in the array?

Any help that you may be able to provide would be greatly appreciated. I have attached a copy of the .au3 file for this program. Thanks for your time.

simple.au3

Link to comment
Share on other sites

I tested this script and it worked for me every time, I got as many files as the script said it took. I can't say for sure why it's not working for you. I did rewrite it though to make it more efficient and easier to handle any issues you might have with it.

#include <ScreenCapture.au3>
#include <WinAPI.au3>
Dim $A[50000]
Global $control

HotKeySet("{ESC}", "capture2")

$control = 1
$n = 0
While $control
    $A[$n] = _ScreenCapture_Capture("", 300, 121, 396, 241)
    $n = $n + 1
WEnd
$n = $n - 1

MsgBox(0, "number of pictures taken", $n)
ReDim $A[$n + 1]

For $I = 0 To $n
    $argument = "C:\Temp\Folder\picture" & $I & ".bmp"
    _ScreenCapture_SaveImage($argument, $A[$I], True)
Next

Func capture2()
    $control = 0
EndFunc

If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Link to comment
Share on other sites

I tested this script and it worked for me every time, I got as many files as the script said it took. I can't say for sure why it's not working for you. I did rewrite it though to make it more efficient and easier to handle any issues you might have with it.

#include <ScreenCapture.au3>
#include <WinAPI.au3>
Dim $A[50000]
Global $control

HotKeySet("{ESC}", "capture2")

$control = 1
$n = 0
While $control
    $A[$n] = _ScreenCapture_Capture("", 300, 121, 396, 241)
    $n = $n + 1
WEnd
$n = $n - 1

MsgBox(0, "number of pictures taken", $n)
ReDim $A[$n + 1]

For $I = 0 To $n
    $argument = "C:\Temp\Folder\picture" & $I & ".bmp"
    _ScreenCapture_SaveImage($argument, $A[$I], True)
Next

Func capture2()
    $control = 0
EndFunc

Thanks so much for your response. I think I know why it may have worked for you. If you run the program for a short period of time (10 seconds or fewer), it's able to work. The problem seems to manifest when you run it for a longer period of time, like 30 seconds or longer. I tried to run it again on a different computer and have found that it still doesn't work correctly if it runs for 30 seconds before hitting "escape". Did you run the program for at least 30 seconds before hitting "escape"?

I also want to thank you for the improvements that you made. I didn't want to use the StringReplace function in order to build the "argument" variable. But I didn't know of any other way to include the changing count variable, "I". I haven't written very many programs in AutoIt, so I'm still getting used to syntax for doing certain things. So, thank you. The same thing is true for the "for-loop" that you used instead of a "while-loop".

In any case, if you were able to get this to work, with either the old program that I provided or the revised one that you have made, for a run time of at least 30 seconds, then I truly am stumped. As I've said, I have now tried it on two different computers and still can't get it to work for over 30 seconds. So I'm interested to know whether or not you could get it to work correctly when waiting at least 30 seconds before hitting "escape". Thanks again for your help.

Link to comment
Share on other sites

You're capturing 97x121 pixels, that is at the very least 97*121*3 = 35 211 (34.386Kb) bytes for every image, excluding headers of hbitmap.

With a modified version (with timing but no saving), I got this:

#include <ScreenCapture.au3>
Dim $A[50000]
Global $control

HotKeySet("{ESC}", "capture2")

$control = 1
$n = 0
$t = TimerInit()
While $control
    $A[$n] = _ScreenCapture_Capture("", 300, 121, 396, 241)
    $n = $n + 1
WEnd
$n = $n - 1
$t = TimerDiff($t) / 1000
ConsoleWrite($n & ' shots taken in ' & $t & 's (about ' & $n / $t & ' per second' & @LF)
Exit

Func capture2()
    $control = 0
EndFunc

45106 shots taken in 27.9215318537624s (about 1615.45577929751 per second

This machine is a 3-year old PC powered by a (now ridiculous) Intel Core2 Duo E8400 @ 3GHz running XP x86.

If I leave it running for more than 30 s or so, it hits the boundary of $A and crashes while trying to write at $A[50000].

Also realize that 50000 shots of 34.386Kb each represent more than 1.7Gb or RAM.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

You're capturing 97x121 pixels, that is at the very least 97*121*3 = 35 211 (34.386Kb) bytes for every image, excluding headers of hbitmap.

With a modified version (with timing but no saving), I got this:

#include <ScreenCapture.au3>
Dim $A[50000]
Global $control

HotKeySet("{ESC}", "capture2")

$control = 1
$n = 0
$t = TimerInit()
While $control
    $A[$n] = _ScreenCapture_Capture("", 300, 121, 396, 241)
    $n = $n + 1
WEnd
$n = $n - 1
$t = TimerDiff($t) / 1000
ConsoleWrite($n & ' shots taken in ' & $t & 's (about ' & $n / $t & ' per second' & @LF)
Exit

Func capture2()
    $control = 0
EndFunc

45106 shots taken in 27.9215318537624s (about 1615.45577929751 per second

This machine is a 3-year old PC powered by a (now ridiculous) Intel Core2 Duo E8400 @ 3GHz running XP x86.

If I leave it running for more than 30 s or so, it hits the boundary of $A and crashes while trying to write at $A[50000].

Also realize that 50000 shots of 34.386Kb each represent more than 1.7Gb or RAM.

After reading your response, I thought you had finally shown me what I needed to see. The hard drive that I was saving these files to, didn't have enough space to hold all of the pictures that I wanted to save. So I figured that the program simply stopped saving them once it ran out of hard drive space. So I put in a different hard drive that has 23 GB of free space. I ran the program for around 30 seconds and it said that it had captured 27146 pictures. So I then clicked "okay" in order to let it save to the drive that now has plenty of room. I still have the same problem. It only saved 9262 files. What is going on?

Thanks for your response. I realize that I'll have to increase the size of "A" to be greater than 50000 if I want to let it run for times longer than 30 seconds, like 5 minutes. I don't have a problem with that. But I still don't know why it won't save all of these files. I really do appreciate the responses that all of you are giving. Any thoughts, ideas, or information is greatly appreciated.

Link to comment
Share on other sites

Ahem, 5 minutes @ about 2Gb of RAM every 30s would mean your OS lets a single application use 20 Gb of working set RAM.

I don'tknow what is the max size of an array (max sizes for strings and binary types is 2Gb), if any, but it isn't clear you wouldn't exceed some limit there.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

It`s not the Hard Disk space, Is the RAM memory where you store all the screen captures.

What is the propourse of the script? Maybe we can help you in another way.

You're right. It is due to the amount of memory. I placed a short delay in between each frame capture. This takes fewer pictures, but not as few as when I had it designed to save after every capture. So this should work well enough. It comes out to about 65 pictures per second rather than 905, which was overkill.

I want to thank everyone who helped out on this. Every single response was insightful and helpful. I appreciate the time that all of you have given.

Link to comment
Share on other sites

Why don't you save the pictures as you're taking them? Seems like you are wasting a lot of RAM without any good purpose so far.

Saving each picture after every capture is too slow. It leaves too big of a gap in time between the pictures taken. This was my first approach, but it just doesn't capture enough pictures per second.

Link to comment
Share on other sites

Use AdLibRegister to capture screenshots at decent, fixed rate. Use a loop in the main code to save them at whatever rate is achievable. Free hbitmaps after save to keep the RAM working set low.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

Use AdLibRegister to capture screenshots at decent, fixed rate. Use a loop in the main code to save them at whatever rate is achievable. Free hbitmaps after save to keep the RAM working set low.

I have tested this while saving the images to a folder as wel as writing them to an avi. Both methods maxed out at about 50-55 FPS for me, both with AdlibRegister and using a loop.

The process doesn't use a lot of memory, or CPU, and the file only increases with about 2MB/sec (While a larger search area reaches ~40MB/sec)

Not sure how to achieve 65 fps, other than using two (identical) processes that alternate storing the $hBMP's in an array and then writing them when the other process takes over.

Here's a way to make the avi if anyone cares:

#include <ScreenCapture.au3>
#include "AVIWriter.au3"

FileDelete(@DesktopDir & "\test.avi")
MsgBox(0,"Achieved framerate:",_Record(@DesktopDir & "\test.avi", 300, 121, 396, 241, 65, 30*1000) & "fps")

Func _Record($sFile, $iLeft, $iTop, $iRight, $iBottom, $iFPS, $iLength)
    Local $hBmp, $i, $iMs = 1000/$iFPS
    _StartAviLibrary()
    Local $aAvi = _CreateAvi($sFile, $iFPS, $iRight - $iLeft, $iBottom - $iTop)
    Local $iTimer = TimerInit()
    Do
        If TimerDiff($iTimer) > $i*$iMs Then
            $i += 1
            $hBmp = _ScreenCapture_Capture("", $iLeft, $iTop, $iRight, $iBottom)
            _AddHBitmapToAvi($aAvi, $hBmp)
            _WinAPI_DeleteObject($hBmp)
        EndIf
    Until TimerDiff($iTimer) > $iLength
    _CloseAvi($aAvi)
    _StopAviLibrary()
    Return $i/($iLength/1000)
EndFunc

Aviwriter UDF can be found

Edit: I expected _AddHBitmapToAvi() to be the thing slowing the script down, but it turns out 95% of the time is spend in _ScreenCapture_Capture(). What kind of FPS did you achieve using the original method? You mentioned 905, but I don't get how you could get anywhere near that.

Edit2: Suddenly had a brainwave and disabled dwm.exe. Now I'm happily recording an avi at 800 fps. I don't have time to test with images again though.

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