Simple Linux Screenshot Application in Perl

Shutter, a powerful application for taking screenshots is possibly soon to be removed from Debian, taking with it the last desktop Perl application in that ubiquitous distro. That is a shame, but there is hope, I guess, some brave soul with take up the effort required to make it fit with GTK3s new APIs. That person is not going to be me. I don't have the skills or the time to do this. But hey, I am the author of the world's simplest GUI generator( probably). Surely it can't be that difficult to cobble together a few applications to make the world's simplest Screenshot tool? Does not need to be fancy, but needs to have a ton more features than the basic Screenshot application in Ubuntu, and be generally useful for day to day use even as a proof of concept.

Requirements

  1. Must be able to do everything that the built-in screenshot application does: -capture screenshots, save the images, and copy to clipboard.
  2. Add-on an external editor to annotate the captured images
  3. Delayed image capture
  4. Extract multiple application window captures, not just the active window
  5. (Animated screen captures e.g. to generate tutorials)
  6. (Add web camera support)

The first 4 I have been able to do relatively easily, using Imager::Screenshot, File::Copy, and a few external X11 tools: - xprop (included by default in Ubuntu) and xclip (needed sudo apt-get install xclip to install, adds clipboard functionality).

Collecting Window IDs and Names of the frame

A couple of ways to get window Ids on X11, of which xprop comes already installed in Ubuntu.

my $windowList= `xprop -root|grep ^_NET_CLIENT_LIST`;
my @winIds=$windowList=~m/(0x[0-9a-f]{7})/g;

xprop also gives us a way of getting the names of the windows

my $name=`xprop -id $id|grep '^WM_NAME(STRING)'`;
       $name=~s/WM_NAME\(STRING\) =//;
       $name=~s/\"//g;
       chomp $name;

Capturing the screenshot

Imager::Screenshot takes, would you believe, screenshots. Passed with a window ID it will capture the contents of the frame. If we know the window Ids of all the windows we could create a hash containing all the screens. While it is possible to include window decorations with the Winodws variant of Imager, this appears not to be possible for Linux. Nevermind...the code is simple.: -

my %images=map($_ => screenshot(hex $_) @winIds ;

In practice this takes a while if there are are many windows. Better to to these as and when needed.

Saving to clipboard

Now I know there is a module called Clipboard. I presume this uses xclip, itself, and as I know there is only one line that needs it, it is easier to install just xclip and : -

  system("xclip -selection clipboard -t image/png -i $workingDir.$workingFile ");

Wrapping it up with a GUI

It is trivial to set up this with GUIDeFATE, to provide all the functionality and much more in little more than 100 lines of code. Using GUIDeFATE means that we can use this with Qt, Gtk, Wx, or Tk. (Win32 not covered with this version, but probably not challenging to add the functionality). Connecting to GIMP is also trivial one line connected to an Edit button. A delayed capture is again trivial. As we know the names of the window, this can be displayed with the thumbnail. Now I don't imagine that this could ever replace a professional application, but as a proof of concept, this shows what can be achieved with relatively little effort. But with only a little more effort more can be achieved...e.g. the ability to generate animated tutorials. I am just thinking of how this might look in action...

Screenshot

This is the result of a full screen grab containing another running screen grabber (using Tk back end) grabbing the contents of the frame of another application... screenshot of screenshot in action.png

2 Comments

Hi Saif,
That is seriously clever!

Leave a comment

About Saif

user-pic An Orthopaedic Surgeon, A Tissue Engineering Scientist, Lecturer, (and Hobbyist Programmer, Electronics Engineer and Roboticist)