Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

saving a Gtk2 canvas which is bigger than the window

by zentara (Archbishop)
on Nov 05, 2006 at 15:48 UTC ( #582317=snippet: print w/ replies, xml ) Need Help??

Description: In Perl/Tk there is the postscript method for saving an entire unseen canvas. In Gtk2's Gnome2::Canvas, you can only grab a snapshot of the visible portion of the canvas. This is a way to slide thru a scrolled window( which contains a canvas), and stitch together a full snapshot.

It may seem clumsy the way I cycle thru the scrolled window, (and someone may be able to refine the loop), but this way makes it obvious what is happeneing.

Any comments, bugs found, improvements are welcome. ( I'm probably overlooking something :-) )

#!/usr/bin/perl
use warnings;
use strict;
use Glib qw/TRUE FALSE/;
use Gtk2 -init;
use Gnome2::Canvas;

my $debug = 0;  # set to 1 to get small pixbuf files

# Create the window
my $window = new Gtk2::Window ( "toplevel" );
$window->signal_connect ("delete_event", sub { Gtk2->main_quit; });
$window->set_border_width (10);
#$window->set_size_request(640,480);
$window->set_position('center');

my $vbox = Gtk2::VBox->new( 0, 0 );
$window->add($vbox);
$vbox->set_border_width(2);

my $hbox = Gtk2::HBox->new( 0, 0 );
$vbox->pack_start($hbox,1,1,0);
$hbox->set_size_request(320,240);
$hbox->set_border_width(0);

my $hbox1 = Gtk2::HBox->new( 0, 0 );
$vbox->pack_start($hbox1,0,0,0);
$hbox1->set_border_width(0);

my $scwin = Gtk2::ScrolledWindow->new();
my $ha1  = $scwin->get_hadjustment;
my $va1  = $scwin->get_vadjustment;
$scwin->set_policy('automatic','automatic');
$hbox->add($scwin);

 my $white = Gtk2::Gdk::Color->new (0xFFFF,0xFFFF,0xFFFF);

 my $canvas = Gnome2::Canvas->new();
 $canvas->set_scroll_region(0,0,1000,1000);
 $canvas->modify_bg('normal',$white);
 $canvas->set_center_scroll_region (0);
 my $root = $canvas->root();

my $item = Gnome2::Canvas::Item->new($root,
   "Gnome2::Canvas::Ellipse",
    x1 => 0,
    y1 => 0,
    x2 => 1000,
    y2 => 400,
   fill_color=>"red",
   outline_color=>"black"
);

$item = Gnome2::Canvas::Item->new($root,
   "Gnome2::Canvas::Ellipse",
    x1 => 0,
    y1 => 400,
    x2 => 1000,
    y2 => 800,
   fill_color=>"blue",
   outline_color=>"black"
);

$item = Gnome2::Canvas::Item->new($root,
   "Gnome2::Canvas::Ellipse",
    x1 => 0,
    y1 => 800,
    x2 => 1000,
    y2 => 1000,
   fill_color=>"green",
   outline_color=>"black"
);

$scwin->add($canvas);

my $button2 = Gtk2::Button->new('Quit');
$hbox1->pack_start( $button2, FALSE, FALSE, 2);
$button2->signal_connect( clicked => sub{ exit; });

my $button3 = Gtk2::Button->new('Save');
$hbox1->pack_start( $button3, FALSE, FALSE, 2);
$button3->signal_connect( clicked => \&save_it,$canvas);

$window->show_all;

Gtk2->main;
#######################################################

sub save_it{
my (undef, $widget) = @_;

my ($width, $height) = $widget->get_size;
my ($x,$y,$width1, $height1,$depth) = $widget->window->get_geometry;
print "$width $height\n" if $debug;
print "$width1 $height1\n" if $debug;

# a hack to slide the viewport and grab each viewable area
my $cols = int($width/$width1);
my $cmod = $width % $width1;
my $rows = int($height/$height1);
my $rmod = $height % $height1;
print "rows - rmod-> $rows - $rmod\n" if $debug;
print "cols - cmod-> $cols - $cmod\n" if $debug;

# create large blank pixbuf to hold the stitched image
my $gdkpixbuf_l = Gtk2::Gdk::Pixbuf->new ('rgb',
                    0, 8, $width, $height);

# get full rows and cols ##################################
for my $c (0 .. $cols - 1 ){    
    #slide viewport along
    $ha1->set_value( $c * $width1  );    
      for my $r (0..$rows - 1 ){
         $va1->set_value( $r * $height1  );    

        # create blank pixbuf to hold the small image
        my $gdkpixbuf = Gtk2::Gdk::Pixbuf->new ('rgb',
                    0, 8,$width1, $height1);

       $gdkpixbuf->get_from_drawable ($canvas->window, 
                  undef, 0, 0, 0, 0, $width1, $height1);

      # $src_pixbuf->copy_area ($src_x, $src_y, $width, $height, 
      #                         $dest_pixbuf,  $dest_x, $dest_y)
      $gdkpixbuf->copy_area (0, 0, $width1, $height1, 
                        $gdkpixbuf_l, $c*$width1, $r*$height1);

      $gdkpixbuf->save ("$0-$c-$r.jpg", 'jpeg', 
              quality => 100) if $debug;

  } #end rows
} #end cols
######################################################################
+##

# get bottom odd row except lower right corner#######################
for my $c (0 .. $cols - 1 ){    
    $ha1->set_value( $c * $width1  );    
    $va1->set_value( $rows * $height1  );    

    my $gdkpixbuf = Gtk2::Gdk::Pixbuf->new ('rgb',
                    0,8,$width1,$rmod);

    $gdkpixbuf->get_from_drawable ($canvas->window, 
                  undef, 0, 0, 0, 0, $width1, $rmod);

    $gdkpixbuf->copy_area (0, 0, $width1, $rmod, 
                $gdkpixbuf_l, $c*$width1, $rows*$height1);

    $gdkpixbuf->save ("$0-$c-rmod.jpg", 'jpeg', 
               quality => 100) if $debug;

 } #end odd row
######################################################################
+##

# get right odd col except lower right corner ########################
+##
for my $r (0 .. $rows - 1 ){    
    $ha1->set_value( $cols * $width1  );    
    $va1->set_value( $r * $height1  );    

    # create blank pixbuf to hold the image
    my $gdkpixbuf = Gtk2::Gdk::Pixbuf->new ('rgb',
                    0,8,$cmod, $height1);

   $gdkpixbuf->get_from_drawable ($canvas->window, 
                  undef, 0, 0, 0, 0, $cmod, $height1);

   $gdkpixbuf->copy_area (0, 0, $cmod, $height1, 
            $gdkpixbuf_l, $cols*$width1, $r*$height1);

   $gdkpixbuf->save ("$0-$r-cmod.jpg", 'jpeg', 
               quality => 100) if $debug;

} #end odd col
######################################################################
+##

# get  lower right corner ##########################
    $ha1->set_value( $cols * $width1  );    
    $va1->set_value( $rows * $height1  );    

    # create blank pixbuf to hold the image
    my $gdkpixbuf = Gtk2::Gdk::Pixbuf->new ('rgb',
                    0,8,$cmod,$rmod);

   $gdkpixbuf->get_from_drawable ($canvas->window, 
                  undef, 0, 0, 0, 0, $cmod, $rmod);

   $gdkpixbuf->copy_area (0, 0, $cmod, $rmod, 
     $gdkpixbuf_l, $width - $cmod, $height - $rmod);

  $gdkpixbuf->save ("$0-rmod-cmod.jpg", 'jpeg', 
              quality => 100) if $debug;

######################################################################
+##

$gdkpixbuf_l->save ("$0-large.jpg", 'jpeg', quality => 100);

$ha1->set_value( 0 );    
$va1->set_value( 0 );    

return FALSE;
}

Comment on saving a Gtk2 canvas which is bigger than the window
Download Code

Back to Snippets Section

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: snippet [id://582317]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others meditating upon the Monastery: (12)
As of 2014-12-19 13:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (83 votes), past polls