In the previous section, we came across Gtk2::Gdk::Pixbuf
and Gtk2::Gdk::Pixmap
. This in itself does not display an image on the screen, you have to use the Gtk2::Image
widget. Gtk2::Gdk::Pixbuf
is used to manipulate images. You can scale them, grab pieces of them, change their color, saturation, add alpha channels, the list goes on. These methods are all documented on Gtk2::Gdk::Pixbuf
's man page or online in the POD.
In this lesson, we will turn our eyes to one of modern music's real heroes, Mr Robert Zimmerman aka Bob Dylan.
We will take an image of him, and scale it. We will add him to our Gtk2::Stock
, as a final exercise, we will cut out his head and take a closer look at it.
If you DO NOT need any image manipulation, and just want to display an image "as is", you can use the |
Table 11-1. Gtk2
object classes used
Gtk2 Class Name |
---|
Gtk2::Window |
Gtk2::VBox |
Gtk2::HBox |
Gtk2::Button |
Gtk2::Frame |
Gtk2::Image |
Gtk2::Label |
Gtk2::Stock |
Gtk2::IconSet |
Gtk2::IconFactory |
Table 11-2. Gtk2::Gdk
object classes used
Gtk2::Gdk Class Name |
---|
Gtk2::Gdk::Pixbuf |
Gtk2::Gdk::PixbufLoader |
The program can be found here: 'Image Manipulation'
1 #! /usr/bin/perl -w 2 3 use strict; 4 use Glib qw/TRUE FALSE/; 5 use Gtk2 '-init'; 6 use Gtk2::Gdk::Keysyms; 7 8 #create the stock item 9 &create_stock_item; 10 11 #standard window creation, placement, and signal connecting 12 my $window = Gtk2::Window->new('toplevel'); 13 $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); 14 $window->set_border_width(5); 15 $window->set_position('center_always'); 16 17 #this vbox will return the bulk of the gui 18 my $vbox = &ret_vbox(); 19 20 #add and show the vbox 21 $window->add($vbox); 22 $window->show(); 23 24 25 #our main event-loop 26 Gtk2->main(); 27 28 sub create_stock_item { 29 #this sub will add a stockitem: 30 31 # the stock id our stock item will be accessed with 32 my $stock_id = 'dylan'; 33 34 # add a new entry to the stock system with our id 35 Gtk2::Stock->add ({ 36 stock_id => $stock_id, 37 label => '_Dylan - Stock image sizes', 38 modifier => [], 39 keyval => $Gtk2::Gdk::Keysyms{D}, 40 translation_domain => 'gtk2_image', 41 }); 42 43 # create an icon set, with only one member in this particular case 44 my $icon_set = Gtk2::IconSet->new_from_pixbuf ( 45 Gtk2::Gdk::Pixbuf->new_from_file ("./pix/dylan.jpg")); 46 47 # create a new icon factory to handle rendering the image at various sizes... 48 my $icon_factory = Gtk2::IconFactory->new; 49 # add our new stock icon to it... 50 $icon_factory->add ($stock_id, $icon_set); 51 # and then add this custom icon factory to the list of default places in 52 # which to search for stock ids, so any gtk+ code can find our stock icon. 53 $icon_factory->add_default; 54 55 } 56 57 58 sub ret_vbox { 59 60 my $vbox = Gtk2::VBox->new(FALSE,5); 61 62 #the stock images 63 my $frame = Gtk2::Frame->new(); 64 #to prove that a Gtk2::Frame can contain something else 65 66 $frame->set_shadow_type ('out'); 67 #method of Gtk2::Container 68 $frame->set_border_width(5); 69 70 my $btn_dylan = Gtk2::Button->new_from_stock('dylan'); 71 72 $frame->set_label_widget ($btn_dylan); 73 74 #create a hbox that will contain the various stock image sizes 75 my $hbox_stock = Gtk2::HBox->new(FALSE,5); 76 my @sizes =qw/menu small-toolbar large-toolbar button dnd dialog /; 77 foreach my $size(@sizes){ 78 $hbox_stock->pack_start(Gtk2::Label->new($size.":"),FALSE,FALSE,0); 79 my $img_stock = Gtk2::Image->new_from_stock('dylan',$size); 80 $hbox_stock->pack_start($img_stock,FALSE,FALSE,0); 81 } 82 $frame->add($hbox_stock); 83 84 $vbox->pack_start($frame,FALSE,FALSE,0); 85 86 #scaling the image 87 $frame = Gtk2::Frame->new('Fetching the image from a file, and scaling the original:'); 88 $frame->set_shadow_type ('out'); 89 #method of Gtk2::Container 90 $frame->set_border_width(5); 91 92 #create a hbox that will contain the original and scaled images 93 my $hbox_scale = Gtk2::HBox->new(FALSE,5); 94 95 my $lbl_type = Gtk2::Label->new("original\n(100x100):"); 96 $hbox_scale->pack_start($lbl_type,FALSE,FALSE,0); 97 98 #________ 99 #the Gtk2::Gdk::PixbufLoader is used in 100 # the acquisition of images in "raw" format. 101 #This will typically be data from a database 102 my $pixbufloader = Gtk2::Gdk::PixbufLoader->new; 103 my $raw_data = `cat ./pix/dylan.jpg`; 104 $pixbufloader->write($raw_data); 105 $pixbufloader->close; 106 my $pixbuf = $pixbufloader->get_pixbuf; 107 108 my $img_orig = Gtk2::Image->new_from_pixbuf($pixbuf); 109 $hbox_scale->pack_start($img_orig,FALSE,FALSE,0); 110 111 $lbl_type = Gtk2::Label->new("Scale\n(150x150):"); 112 $hbox_scale->pack_start($lbl_type,FALSE,FALSE,0); 113 114 my $pixbuf_larger = $pixbuf->scale_simple(150,150,'bilinear'); 115 my $img_larger = Gtk2::Image->new_from_pixbuf($pixbuf_larger); 116 $hbox_scale->pack_start($img_larger,FALSE,FALSE,0); 117 118 $lbl_type = Gtk2::Label->new("Scale\n(50x50):"); 119 $hbox_scale->pack_start($lbl_type,FALSE,FALSE,0); 120 121 my $pixbuf_smaller = $pixbuf->scale_simple(50,50,'bilinear'); 122 my $img_smaller = Gtk2::Image->new_from_pixbuf($pixbuf_smaller); 123 $hbox_scale->pack_start($img_smaller,FALSE,FALSE,0); 124 125 $frame->add($hbox_scale); 126 127 $vbox->pack_start($frame,FALSE,FALSE,0); 128 129 #cut and zoom 130 $frame = Gtk2::Frame->new('Fetching a piece of a pixbuff, and scaling it:'); 131 $frame->set_shadow_type ('out'); 132 #method of Gtk2::Container 133 $frame->set_border_width(5); 134 135 my $pixbuf_head = $pixbuf->new_subpixbuf (13, 11, 50, 50); 136 my $pixbuf_head_large = $pixbuf_head->scale_simple(150,150,'bilinear'); 137 138 #create a hbox that will contain the original and scaled head images 139 my $hbox_head_scale = Gtk2::HBox->new(0,5); 140 141 $lbl_type = Gtk2::Label->new("Original head:"); 142 $hbox_head_scale->pack_start($lbl_type,FALSE,FALSE,0); 143 my $img_head = Gtk2::Image->new_from_pixbuf($pixbuf_head); 144 $hbox_head_scale->pack_start($img_head,FALSE,FALSE,0); 145 146 $lbl_type = Gtk2::Label->new("Scaled head:"); 147 $hbox_head_scale->pack_start($lbl_type,FALSE,FALSE,0); 148 my $img_head_large = Gtk2::Image->new_from_pixbuf($pixbuf_head_large); 149 $hbox_head_scale->pack_start($img_head_large,FALSE,FALSE,0); 150 151 $frame->add($hbox_head_scale); 152 153 $vbox->pack_start($frame,FALSE,FALSE,0); 154 155 $vbox->show_all(); 156 return $vbox; 157 }
Gtk2::Stock
We will start our discussion by looking at Gtk2::Stock
. Up to now, we only used available stock items. Stock items can be used in various places, is a nice way to standardize, and eases internationalization.
If you expect to see the standard stock icons stored somewhere in your file system, you are in for a surprise. These icons are data structures, compiled into Gtk+. |
Gtk2::Stock
has the ability to add new stock items to it. These new items will only be available while the program run, and is destroyed as soon as it terminates. We follow a few standard steps to create a stock item.
To add the new stock item, we use the add
method, and supply data to a hash of key/value pairs
# add a new entry to the stock system with our id Gtk2::Stock->add ({ stock_id => $stock_id, label => '_Dylan - Stock image sizes', modifier => [], keyval => $Gtk2::Gdk::Keysyms{D}, translation_domain => 'gtk2_image', });
Two important hash keys are "stock_id" and "label". The rest are used for more advanced functions, that will not be needed in our program. At this stage the new stock item is ready to be used. If you want to incorporate an icon with it (like we want to) you need a few extra steps.
Create a Gtk2::IconSet
, with only one member in this particular case.
my $icon_set = Gtk2::IconSet->new_from_pixbuf ( Gtk2::Gdk::Pixbuf->new_from_file ("./pix/dylan.jpg"));The data for the pixbuf can be from various sources, in our example we opt for an image file.
Create a new Gtk2::IconFactory
factory to handle rendering the image at various sizes.
my $icon_factory = Gtk2::IconFactory->new;We will show in our program the various sizes available for stock icons.
Add our new stock icon to it.
$icon_factory->add ($stock_id, $icon_set);This will tie the icon to the stock item.
Then add this custom Gtk2::IconFactory
to the list of default places in which to search for stock ids, so any Gtk+ code can find our stock icon.
$icon_factory->add_default;This finish the steps to add the icon to the
Gtk2::Stock
item.
Sometimes the images you want to show in your application can not be fetched using the typical 'from_file'
methods. Images from a database is a classic example. Rather than writing them to a temp file, and reading the temp file, we can directly use them. In our sample program we simulate this situation.
#the Gtk2::Gdk::PixbufLoader is used in # the acquisition of images in "raw" format. #This will typically be data from a database my $pixbufloader = Gtk2::Gdk::PixbufLoader->new; my $raw_data = `cat ./pix/dylan.jpg`; $pixbufloader->write($raw_data); $pixbufloader->close; my $pixbuf = $pixbufloader->get_pixbuf; my $img_orig = Gtk2::Image->new_from_pixbuf($pixbuf);
In our program, we use available methods of Gtk2::Gdk::Pixbuf
to manipulate an image.
To scale a image we use:
pixbuf = $src->scale_simple ($dest_width, $dest_height, $interp_type)This allow various values for "$interp_type", but most end results are the same. We used 'bilinear'.
To grab only a piece of an exitsing Gtk2::Gdk::Pixbuf
:
pixbuf = $src_pixbuf->new_subpixbuf ($src_x, $src_y, $width, $height)All the arguments should be easy to understand.
Remember that manipulating a Gtk2::Gdk::Pixbuf
does not show it on screen. To do that, we have to show it in a Gtk2::Image
widget.
When displaying stock images, you need to supply the size of the image. Our program list, and show all available sizes for stock images.