Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much

TWAIN Issues and Perl

by newrisedesigns (Curate)
on Sep 12, 2002 at 00:09 UTC ( [id://197122] : perlquestion . print w/replies, xml ) Need Help??

newrisedesigns has asked for the wisdom of the Perl Monks concerning the following question:

I wrote a q&d Perl script to acquire an image from my webcam, modify it, and upload it to my website.

The resizing and uploading features work flawlessly, however in order to acquire the image, the camera (via TWAIN) requires that I "Select", "Capture" then "Transfer" the image, a process that takes four clicks. This kills the possibility of allowing the camera to run continuously; it will halt when I'm not there and drive me completely insane when I am.

As far as I know, I have only three options.

  • Find a different module (I'm using Win32::Scanner::EZTWAIN) that acquires without human intervention
  • Have an intermediary program acquire the image and place it in a file (the same as above, but non-Perl)
  • Automate the button pushing somehow (four mouse clicks, options would not change)

Fellow Monks, which of the above seems like a viable and readily instituted solution?

Code follows...

use Win32::Scanner::EZTWAIN; use Net::FTP; use Image::Magick; my $scanner = new Win32::Scanner::EZTWAIN(); print "Select Image Source...\n"; $scanner->select_image_source(""); print "Acquiring File...\n"; $scanner->acquire_to_file("cam.bmp"); my $image = new Image::Magick; print "Opening Image\n"; $image->Read("cam.bmp"); $image->Resize(width=>320, height=>240, filter=>"Cubic"); $image->Annotate(text=>'', font=>"Verdana", pointsize=>12, fill=>"#000000", antialias=>"true", x=>17, y=>20); $image->Annotate(text=>'', font=>"Verdana", pointsize=>12, fill=>"#ffffff", antialias=>"true", x=>15, y=>18); if($ARGV[0] ne ''){ $ARGV[0] .= "\n"; $image->Annotate(text=>$ARGV[0], font=>"Verdana", pointsize=>12, stroke=>"#000000", strokewidth=>1, antialias=>"true", gravity=>"South"); } $image->Set(quality=>80); print "Reformatting Image\n"; $image->Write(filename=>"cam.jpg", compression=>'jpeg'); my $ftp = Net::FTP->new(""); print "Preparing FTP Connection\n"; $ftp->login('username','password'); print "Changing Directory\n"; $ftp->cwd('httpdocs/cam'); print "Putting Image\n"; $ftp->binary(); $ftp->delete('cam.jpg'); $ftp->put('cam.jpg');

Any solutions other than the three above would also be greatly appreciated.

Many thanks,
John J Reiser

Replies are listed 'Best First'.
Re: TWAIN Issues and Perl
by ryddler (Monk) on Sep 12, 2002 at 15:34 UTC

    In the spirit of TMTOWTDI, you could also look at the Win32::API module, and do API calls to achieve most anything. There is an online API reference (including messages for the SendMessage API I used) at

    Here's a small example I whipped up to experiment myself. Note that you will have to open Calculator in "scientific mode" for this script to work.

    #! C:/perl/bin/perl -w use strict; use Win32::API; use vars qw($rv); use constant BM_CLICK => hex('F5'); my $findwindow = new Win32::API("user32", "FindWindowA", ['P','P'], 'N'); my $findwindowex = new Win32::API("user32", "FindWindowExA", ['N','N','P','P'], 'N'); my $sendmessage = new Win32::API("user32", "SendMessageA", ['N','N','N','P'], 'N'); my $setactivewindow = new Win32::API("user32", "SetActiveWindow", ['N'], 'N'); # Find the handle of the parent window. In this case # 'Calculator' is the text shown in the title bar my $hwnd = $findwindow->Call( 0,'Calculator'); print "Parent window handle = $hwnd\n"; # Find the handle of the buttons we want to press. # Sometimes, but not always, the caption shown on the button my $hex_button = $findwindowex->Call($hwnd, 0, 0, 'Hex'); my $dec_button = $findwindowex->Call($hwnd, 0, 0, 'Dec'); my $oct_button = $findwindowex->Call($hwnd, 0, 0, 'Oct'); my $bin_button = $findwindowex->Call($hwnd, 0, 0, 'Bin'); $rv = $setactivewindow->Call($hwnd); print "setactivewindow returned = $rv\n"; foreach ($hex_button,$dec_button,$oct_button,$bin_button) { $rv = $sendmessage->Call($_ , BM_CLICK, 0, 0); print "sendmessage returned = $rv\n"; sleep 2; }


      ++ for showing the hard way of doing things ;)

      Win32::Guitest makes it easier to do the same API calls... This program does the same thing without all of the return messages. (I didn't see the point for this simple exercise.)

      Start calculator before running this code (mode doesn't matter)

      #! C:/perl/bin/perl use strict; use warnings; # Win32::GuiTest doesn't like -w use Win32::GuiTest qw(FindWindowLike SetForegroundWindow SendKeys Push +Button); my @windows = FindWindowLike(0, "^Calculator"); # find all calculator +windows die "Start Calc before running this example.\n" unless @windows; my $hwnd = $windows[0]; # we'll just the first match SetForegroundWindow($hwnd); # Bring it the foreground SendKeys("%VS"); # switch to scientific mode # press these buttons foreach my $button ("Hex", "Dec", "Oct", "Bin") { sleep(2); PushButton($button); }
      See how much simpler that is? Win32::API is great if it can't be done another way.

      Update: Added the die statement to my code.

      How about passing a ALT-G or CTRL-G to the window??
      THis is soooo close to what I need.
      I am digging....
Re: TWAIN Issues and Perl
by Mr. Muskrat (Canon) on Sep 12, 2002 at 14:45 UTC

    Take a look at Win32::Guitest. It allows you to find a certain window, send keystrokes to it or even take control of the mouse (move the pointer, click mouse buttons, etc).

    There may be others available as well but this is the one that came to mind when reading your post.

Re: TWAIN Issues and Perl
by t'mo (Pilgrim) on Sep 12, 2002 at 15:35 UTC

    Have you looked into any of Jamie Zawinski's stuff that may accomplish something similar (albeit without any Win32::* modules)?

    Otherwise, Mr. Muskrat's suggestion may be the way to go...

      Darn it t'mo, I didn't realize you had two links, not one; I just spent much more time than I should've browsing JWZ's website from the root page. (*grin*)

      This link might be what the original poster would be looking for; except it's for a linux server, not Windows.

      Still, fun stuff to browse.

      ___ -DA $_=' 519-575-3733 /Prescient Code Solutions/ coder.c +om ';s/-/ /g;s/([.@])/ $1/g;@y=(42*1476312054+7*3,14120504e4,-42*330261-3 +3, 42*5436+3,42*2886+10,42*434987+5);s/(.)/ord(uc($1))/ge;for(@x=split/32 +/; @y; map{print chr} split /(..)/, shift(@x) + shift(@y)) {perlmonk.da.r +u}
Re: TWAIN Issues and Perl
by samtregar (Abbot) on Sep 12, 2002 at 06:31 UTC
    Why do you need to find a new module? You didn't mention what's wrong with the code you posted. I can't test it since I don't have a scanner, but it looks ok at a quick glance...


      The code posted is functional, however, when the Win32::Scanner::EZTWAIN functions are called, TWAIN opens the Image Acquire dialog for my camera (much like it would open the dialog for previewing and scanning when using a scanner), which is cumbersome and by no means automatic.

      I'd like the webcam to be automatic, taking pictures every five or ten minutes with out my intervention.

      You're welcome to try it out, if you'd like. You'll see though, that after the first few times of clicking through the TWAIN dialogs, taking pictures becomes an annoyance rather than a pleasure. :)

      John J Reiser

Re: TWAIN Issues and Perl
by BrowserUk (Patriarch) on Sep 13, 2002 at 03:41 UTC

    Personally, I'd probably fork out $35 for Dosadi's (the writers of the EZTWAIN library around which Win32::Scanner::EZTWAIN is wrapped) Aquire command line utility. It has a switch which will try to negotiate with your TWAIN device to prevent the user interface being displayed. This is the source of the popups you see when using EZTWAIN rather than EZTWAIN itself.

    You can even download a copy and try for 7 days to make sure it does what you need before you purchase.

    Well It's better than the Abottoire, but Yorkshire!

      Thanks BrowserUk!

      I downloaded the trial of Acquire, and it works for me.

      <whines>but i wanted to make a free, perl-based alternative to the webcam software out there now. </whines>
      I guess I better keep looking.

      John J Reiser

        John. Glad it helped a little at least.

        Have you looked around Dosadi's site? They also have a package (under Products) called CTwain, which is a library with source for use in building TWAIN apps. Their licencing is very generous in that it "may be freely used for non-commercial purposes". It is designed for exactly your purpose I think.

        They also have a support dept. which, going by my one intereaction with them, seems very knowledgable, efficient and flexible. A rarity these days.

        I'd suggest you contact them, tell them what you are trying to do, and maybe they will be able to give you some pointers. Good luck

        Cor! Like yer ring! ... HALO dammit! ... 'Ave it yer way! Hal-lo, Mister la-de-da. ... Like yer ring!
Re: TWAIN Issues and Perl
by grantm (Parson) on Sep 13, 2002 at 02:22 UTC
    Of course you could 'simply' upgrade to Linux and use SANE which supports a command-line interface :-)