[Templates] Image plugin (was: Modifying TT functions at run time)

darren chamberlain dlc@users.sourceforge.net
Tue, 5 Nov 2002 09:27:19 -0500


--4bRzO86E/ozDv8r1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

* Mark Fowler <mark@twoshortplanks.com> [2002-11-05 08:42]:
> On Tue, 5 Nov 2002, darren chamberlain wrote:
> (I hadn't seen Image::Info before...oooh, shiny)

I love trolling around CPAN.  Of course, having a local mirror helps
(it only hurts the first time!) -- "less /cpan/RECENT" is a good way to
see what's new. :)

> >   * file extension (gif)
> 
> Image::Size does this as well, doesn't it?  Anyway, it's not
> important.  As long as we get it from *somewhere* ;-)

> > Patches against lib/Template/Plugin/Image.pm and t/image.t attached; comments?
> 
> a) If the two modules do the same thing, wouldn't it be nice to use
> either or depending on which ones were installed?

Yep.  Attached is another patch, identical to the first, except this one
tries to load either Image::Info or Image::Size (in that order).
(Don't apply this patch to a version you've patched with my last patch;
this one is against CVS, not against an already patched Image.pm).

> b) What's the speed difference/memory useage of these things?  Does 
> Image::Info use more resources when it's doing the checks?

Um, ok.

> c) Image::Info doesn't seem to mention anything about caching results,
> which Image::Size does (to avoid reloading data each and every time a
> bullet point is used for example.)  Should we add that bit in the
> plugin?

Well, Image::Info gives you much more info for some types; here's some
of the output from my suggested exercise:

  $ perl -MData::Dumper -MImage::Info=image_info -e 'print Dumper(scalar image_info("test.jpg"))' 

$VAR1 = {
          'FileSource' => '(DSC) Digital Still Camera',
          'MeteringMode' => 'Pattern',
          'width' => 640,
          'Olympus-Tag-0x0203' => 0,
          'ExposureProgram' => 'Program',
          'Olympus-Tag-0x0205' => bless( [
                                           780,
                                           100
                                         ], 'Image::TIFF::Rational' ),
          'Olympus-Tag-0x0206' => [
                                    '-215',
                                    65148,
                                    65118,
                                    65351,
                                    65226,
                                    65222
                                  ],
          'ImageDescription' => 'OLYMPUS DIGITAL CAMERA',
          'UserComment' => '                                                                                                                     ',
          'Olympus-JpegQual' => 'SQ',
          'resolution' => '72 dpi',
          'ExifImageLength' => 480,
          'Olympus-DigiZoom' => bless( [
                                         0,
                                         100
                                       ], 'Image::TIFF::Rational' ),
          'Flash' => 1,
          'Model' => 'C2000Z',
          'ExifImageWidth' => 640,
          'Olympus-SoftwareRelease' => 'SR951',
  # snippage...

And so on -- Image::Info returns a lot more stuff for images that have
the stuff.

(darren)

-- 
This is the crucial difference between fiction and real life: fiction
must be plausible; real life has no such constraint.
    -- Kevin Kelly

--4bRzO86E/ozDv8r1
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="Image.patch"

Index: Image.pm
===================================================================
RCS file: /template-toolkit/Template2/lib/Template/Plugin/Image.pm,v
retrieving revision 1.2
diff -u -d -w -u -p -r1.2 Image.pm
--- Image.pm	2002/11/04 19:47:13	1.2
+++ Image.pm	2002/11/05 14:27:19
@@ -22,16 +22,31 @@ package Template::Plugin::Image;
 require 5.004;
 
 use strict;
-use Image::Size;
 use Template::Plugin;
 use File::Spec;
 use base qw( Template::Plugin );
 
-use vars qw( $VERSION );
+use vars qw( $VERSION $AUTOLOAD );
 
 $VERSION = sprintf("%d.%02d", q$Revision: 1.2 $ =~ /(\d+)\.(\d+)/);
 
+BEGIN {
+    if (eval { require Image::Info; }) {
+        *img_info = \&Image::Info::image_info;
+    }
+    elsif (eval { require Image::Size }) {
+        *img_info = sub {
+            my $file = shift;
+            my @stuff = Image::Size::imgsize($file);
+            return { "width" => $stuff[0], "height" => $stuff[1] };
+        }
+    }
+    else {
+        die(Template::Exception->new("image",
+            "Couldn't load Image::Info or Image::Size: $@"));
+    }
 
+}
 
 #------------------------------------------------------------------------
 # new($context, $name, \%config)
@@ -71,66 +86,53 @@ sub new {
     }, $class;
 }
 
-
 #------------------------------------------------------------------------
-# size()
+# init()
 #
-# Return the width and height of the image as a 2 element list.
+# Calls image_info on $self->{ file }
 #------------------------------------------------------------------------
 
-sub size {
+sub init {
     my $self = shift;
-
-    # return cached size
-    return $self->{ size } if $self->{ size };
+    return $self if $self->{ size };
 
-    my ($width, $height, $error ) = imgsize($self->{ file });
-    return $self->throw($error) unless defined $width;
-    $self->{ width  } = $width;
-    $self->{ height } = $height;
-    return ($self->{ size } = [ $width, $height ]);
-}
+    my $image = img_info($self->{ file });
+    return $self->throw($image->{ error }) if defined $image->{ error };
 
+    @$self{ keys %$image } = values %$image;
+    $self->{ size } = [ $image->{ width }, $image->{ height } ];
 
-#------------------------------------------------------------------------
-# width()
-#
-# Return the width of the image.
-#------------------------------------------------------------------------
+    $self->{ lastmod } = (stat $self->{ file })[10];
 
-sub width {
-    my $self = shift;
-    $self->size() unless $self->{ size };
-    return $self->{ width };
+    return $self;
 }
 
-
 #------------------------------------------------------------------------
-# height()
+# attr()
 #
-# Return the height of the image.
+# Return the width and height as HTML/XML attributes.
 #------------------------------------------------------------------------
 
-sub height {
+sub attr {
     my $self = shift;
-    $self->size() unless $self->{ size };
-    return $self->{ height };
+    my $size = $self->size();
+    return "width=\"$size->[0]\" height=\"$size->[1]\"";
 }
 
-
 #------------------------------------------------------------------------
-# attr()
+# lastmod()
 #
-# Return the width and height as HTML/XML attributes.
+# Return last modification time as a time_t:
+#
+#   [% date.format(image.lastmod, "%Y/%m/%d") %]
 #------------------------------------------------------------------------
 
-sub attr {
+sub lastmod {
     my $self = shift;
-    my $size = $self->size();
-    return "width=\"$size->[0]\" height=\"$size->[1]\"";
+    $self->init;
+    return $self->{ lastmod };
 }
 
-
 #------------------------------------------------------------------------
 # tag(\%options)
 #
@@ -160,6 +162,14 @@ sub throw {
     die (Template::Exception->new('Image', $error));
 }
 
+sub AUTOLOAD {
+    my $self = shift;
+   (my $a = $AUTOLOAD) =~ s/.*:://;
+
+    $self->init;
+    return $self->{ $a };
+}
+
 1;
 
 __END__

--4bRzO86E/ozDv8r1--