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

Hi, I'm trying to use Tk::TableMatrix to organize images in an image gallery in various ways.

Problem is that I have to deal with allot of images at the same time and it takes long time to load all these images into tablematrix widget. Could any logic be applied so that we could somehow store away image data once loaded into tablematrix and just fetch all images right away from disk (without doing any convertion etc) into the tablematrix next time when images are needed?

  • Comment on Using Tk::TableMatrix for gallery image manipulation?

Replies are listed 'Best First'.
Re: Using Tk::TableMatrix for gallery image manipulation?
by zentara (Cardinal) on Jun 15, 2006 at 17:13 UTC
    Hi again. Just to demonstrate the speed up from using Storable, I chopped down the script I mentioned above, so you can see the basics. Just run it in a directory with some jpgs in a subdir called "pics". The first run will be slow as the thumbnails are built, but exit the program and restart. The second run will be very fast by comparison.
    #!/usr/bin/perl use warnings; use strict; use Tk; use Tk::Pane; use Tk::JPEG; use MIME::Base64; use Imager; use File::Basename; use File::Path; use File::Copy; use Storable; use POSIX qw(strftime); use YAML; my $photo;#my $photo; my $image; my %info; my @exts = qw(.jpg .png .gif); # list allowed extensions if(-e 'notebook.db'){ %info = %{retrieve('notebook.db')}; # direct to hash }else{ make_thumbs() } #to see a dump of the db, just put an 1 as an arg to the script if(shift){print Dump(\%info);exit;} my $mw = MainWindow->new(-bg=>'black'); $mw->geometry('800x700+100+15'); #setup auto save of storable db $mw->protocol('WM_DELETE_WINDOW' => sub { &save_it() }); $SIG{__DIE__} = sub { &save_it()}; $SIG{INT} = sub { &save_it()}; $mw->bind('<Control-c>', [sub{&save_it(); Tk::exit;}] ); my $mainframe = $mw->Frame(-background=>'black') ->pack(-side => "right", -anchor => "n", -fill=>'both', -expand=>1); #fill mainframe with default screen setup_pane(); MainLoop; ############################################################# sub setup_pane{ my $pane = $mainframe->Scrolled('Pane', Name => 'Main Display', -width => 1000, -height =>1000, -background => 'black', -scrollbars => 'osoe', -sticky => 'n', )->pack(-side => "left", -anchor => "n", -fill=>'both',-expand=>1); foreach my $key ( keys %info ){ my $image = $mw->Photo( -data => $info{$key}{'thumbnail'} ); $pane->Label(-image => $image, -background =>'black' )->pack(-side => 'top', -anchor => 'n', -fill => 'both', -expand => 1, ); } } ################################################################ sub make_thumbs{ umask 0022; my @pics = <pics/*.jpg pics/*.gif pic/*.png>; my $image = Imager->new(); foreach my $pic (@pics){ my ($basename,$path,$suffix) = fileparse($pic,@exts); $info{$basename}{'name'} = $basename; $info{$basename}{'pic'} = "pics/$basename.jpg"; #convert to jp +g $image->open(file=>$pic) or die $image->errstr(); # Create smaller version my $temp; my $thumb = $image->scale(xpixels=>100); print "Storing thumbnail: $basename.jpg\n"; $thumb->write(data => \$temp, type =>'jpeg', jpegquality=>30) or die $thumb->errstr; $info{$basename}{'thumbnail'} = encode_base64($temp); } print "\n#################endofthumbcreation########################## +#####\n"; } ################################################################### sub save_it{ store(\%info,'notebook.db'); print "saved\n"; exit; } #####################################################################

    I'm not really a human, but I play one on earth. flash japh
      Didn't know that base64 encoding images speeded up image loading. It's certainly a step in the right direction. Thanks, man (zentara).

      Zenatara wrote: "People have been trying to experiment with somehow "freezing" and "thawing" the actual Tk::Photo objects"

      Yes, that would be the ideal solution. I assume that quite allot happens with that base64 encoded data before photo is generated, but since it's a c widget (Tk::Photo, child of Tk::Image) I didn't understand much of what is going on inside..

      from image.pm
      my $obj = $widget->Tk::image('create',$leaf,@_);

      How/where can we decrypt (or even find) the "create" method?

        Didn't know that base64 encoding images speeded up image loading

        Well you are misinterpreting what is happening. The base64encoding only is helping in an indirect way, and really is a Tk-only thing. Tk has a particular ideosyncrancy, that it wants it's images to be base64encoded (the reason is probably buried deep down in the c code). When you load a Photo object from -file, it does the base64encoding automatically. When loading a Photo object from -data, you must provide the encoding yourself.

        So, in this particular instance, we can save the thumbnails as encoded images in one big file. That gives us 2 speed bonuses. The first is that we are saving the time it takes for Tk to base64encode the files, and the second, is that the system only has to open 1 file, the 'notebook.db', instead of 100 smaller thumbnail files. Disk I/O is the biggest slowdown in most programs.

        As far as freezing the Photo object itself, you are in virgin territory. Many attempts have been made by people smarter than me, and they have given up because of all the complexities.


        I'm not really a human, but I play one on earth. flash japh
Re: Using Tk::TableMatrix for gallery image manipulation?
by zentara (Cardinal) on Jun 15, 2006 at 15:17 UTC
    Well, no matter what widget you use, if you try to load alot (like > 20) images, it is going to take time. How many are you trying to load at startup?

    The only thing I can think of, is to base64encode the images(and their thumbnails) and save them in a Storable hash db. Then at startup, all you need to do is import the base64 coded images into a Tk::Photo object using the -data option. That would save you remaking the thumbnails, and would speed up the read operations. People have been trying to experiment with somehow "freezing" and "thawing" the actual Tk::Photo objects, and importing them from the db. That would be the ideal. It would seem possible to do.

    For an example of Storable and Tk (not exactly your situation, but shows the principles) see ztkdb


    I'm not really a human, but I play one on earth. flash japh