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

In the first reply to my slide view of a folder of JPEG's, zentara suggested to use blank() and read() to save memory.

That solution worked great! But now I want not only to view the pictures, but also to process them. In order to do that, the first thing I want to know is the width and height of the picture. I can easily obtain them by calling width() and height(). However with blank() and read(), I don't get the real width and height any more. What happened was that, Tk::Photo extends when a bigger photo is read(), but does not shrink when a smaller one is read, so it reports the biggest width and the biggest height (They are not neccessary to be the width and height of the same picture, as you may have a picture that is super wide, but short, and another one super high, but narrow.)

So I thought there must be a different way to solve the memory issue. I tried couple of things, but all failed. For example (see inline comment):

use Tk; use Tk::JPEG; use File::Glob ':glob'; my @jpgs = bsd_glob('*.jpg'); my $index = 0; my $mw = MainWindow->new(title => "JPEG"); my $b = $mw->Button()->pack(); $mw->after(1000, \&next_image); MainLoop; sub next_image { $b->configure(-image => undef); #effort to free memory eval { my $image = $mw->Photo(-format => 'jpeg', -file => $jpgs[$index]); $b->configure(-image => $image); $mw->configure(-title => $jpgs[$index]); $image = undef; #effort to free memory #undef($image); effort to free memory }; $mw->after(1000, \&next_image) if (++$index <= $#jpgs); }

Any suggestion?

2004-10-29 Edited by Arunbear: Changed title from 'how to free momery allocated for Tk::Photo?', as per Monastery guidelines

Replies are listed 'Best First'.
Re: how to free memory allocated for Tk::Photo?
by BrowserUk (Patriarch) on Oct 29, 2004 at 05:47 UTC

    All you need to do is add the -shrink option on the read and the width and height will be set correctly. You don't even need the blank. In a quick test (under win32) it appears that memory is returned to the system when a small image is read after a large one.

    use Tk; use Tk::JPEG; use File::Glob ':glob'; my @jpgs = bsd_glob('*.jpg'); my $index = 0; my $mw = MainWindow->new(title => "JPEG"); my $image = $mw->Photo(-format => 'jpeg', -file => $jpgs[$index]); my $b = $mw->Button( -image => $image )->pack(); $mw->after(1000, \&next_image); MainLoop; sub next_image { $image->read( $jpgs[$index], -shrink ); $b->configure(-image => $image); $mw->configure( -title => sprintf "$jpgs[$index] [%dx%d]", $image->width, $image->height ); $mw->after(1000, \&next_image) if (++$index <= $#jpgs); }

    Examine what is said, not who speaks.
    "Efficiency is intelligent laziness." -David Dunham
    "Think for yourself!" - Abigail
    "Memory, processor, disk in that order on the hardware side. Algorithm, algorithm, algorithm on the code side." - tachyon

      Very interesting, tested, and -shrink does give memory back. I would rather think that is a bug with read(), not a feature.

      If the memory usage only goes up to fit the largest picture, it makes sense to me, as shrink is not specified, so the memory was retained. I would even think it as a feature, as that might increase efficiency, sort of like maintaining a water mark.

      However it is buggy if the memory goes up every time you read() a new photo without -shrink, regardless whether it is bigger than the biggest.

      At least they should document it as a caveat that, "without -shrink, read() will cause significant memory leak" ;-)

      "You don't even need the blank. In a quick test (under win32) it appears that memory is returned to the system when a small image is read after a large one."

      Thanks for the help!

      blank() was not used for returning memory, and it does not return memory any way. The problem was that, without shrink, if you don't do a blank(), smaller pictures were just displayed on top of bigger ones, so smaller ones cover part of the bigger ones, but not the entire picture, and what you see is a mixture of pictures, a mess ;-) With a call to blank(), your samller picture is simply displayed on top of white space.

      Obviously blank() is no longer needed with shrink specified. This makes sense to me, and I will test the memory usage. Thanks again.