Beefy Boxes and Bandwidth Generously Provided by pair Networks
Pathologically Eclectic Rubbish Lister
 
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 drinking their drinks and smoking their pipes about the Monastery: (3)
As of 2015-07-05 23:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (68 votes), past polls