mason/{.perl-lib/TrivGal,dhandler}: Make an image object.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 24 Dec 2021 17:28:03 +0000 (17:28 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Sat, 25 Dec 2021 16:09:18 +0000 (16:09 +0000)
The objective here is to separate image loading from scaling, so that we
can make several scaled output images without having to load and decode
the original image each time.

The `.thumbnail' module now takes an image object rather than a
pathname.  There's no functional change.

mason/.perl-lib/TrivGal.pm
mason/dhandler

index 9822a0b..838de97 100644 (file)
@@ -29,7 +29,6 @@ use autodie qw{:all};
 
 use Errno;
 use Exporter qw{import};
-use File::Path qw{make_path};
 use File::stat;
 use Image::Imlib2;
 use User::pwent;
@@ -183,35 +182,55 @@ sub clean_temp_files () {
 ###--------------------------------------------------------------------------
 ### Scaled images.
 
-export qw{scaled};
-sub scaled ($$) {
-  my ($scale, $path) = @_;
-
-  my $sz = $SIZE{$scale} or die "unknown scale `$scale'";
-  my $imgpath = "$IMGROOT/$path";
-  my $ist = stat $imgpath or die "no image `$path'";
-  my $thumb = "$CACHE/scaled.$scale/$path";
-  my $thumburl = "$CACHEURL/scaled.$scale/$path";
-  my $tst = stat $thumb;
-  if (defined $tst && $tst->mtime > $ist->mtime) { return $thumburl; }
-  my ($dir, $base, $ext) = split_path $thumb;
-  my $ty = $TYPE{lc $ext} or die "unknown type `$ext'";
-
-  my $img = Image::Imlib2->load($imgpath);
-  my ($wd, $ht) = ($img->width, $img->height);
-  my $max = $wd > $ht ? $wd : $ht;
-  if ($max <= $sz) { return "$IMGURL/$path"; }
-  my $sc = $sz/$max;
-  my $scaled = $img->create_scaled_image($sc*$wd, $sc*$ht);
-
-  $scaled->image_set_format($ty->imlibfmt);
-  $scaled->set_quality(90);
-  my $new = "$TMP/t${$}$ext";
-  make_path $TMP;
-  $scaled->save($new);
-  make_path $dir;
-  rename $new, $thumb;
-  return $thumburl;
+package TrivGal::Image {
+  use File::Path qw{make_path};
+  use File::stat;
+
+  sub new ($$) {
+    my ($cls, $path) = @_;
+    my $imgpath = "$IMGROOT/$path";
+    my $st = stat $imgpath or die "no image `$path'";
+    return bless {
+      path => $path,
+      mtime => $st->mtime,
+      img => undef
+    }, $cls;
+  }
+
+  sub scale ($$) {
+    my ($me, $scale) = @_;
+
+    my $path = $me->{path};
+    my $sz = $SIZE{$scale} or die "unknown scale `$scale'";
+    my $thumb = "$CACHE/scale.$sz/$path";
+    my $thumburl = "$CACHEURL/scale.$sz/$path";
+    my $st = stat $thumb;
+    if (defined $st && $st->mtime > $me->{mtime}) { return $thumburl; }
+
+    my ($dir, $base, $ext) = TrivGal::split_path $thumb;
+    my $ty = $TYPE{lc $ext} or die "unknown type `$ext'";
+
+    my $img = $me->{img};
+    unless (defined $img) {
+      my $imgpath = "$IMGROOT/$path";
+      $img = $me->{img} = Image::Imlib2->load($imgpath);
+    }
+
+    my ($wd, $ht) = ($img->width, $img->height);
+    my $max = $wd > $ht ? $wd : $ht;
+    if ($max <= $sz) { return "$IMGURL/$path"; }
+    my $sc = $sz/$max;
+    my $scaled = $img->create_scaled_image($sc*$wd, $sc*$ht);
+
+    $scaled->image_set_format($ty->imlibfmt);
+    $scaled->set_quality(90);
+    my $new = "$TMP/t${$}$ext";
+    make_path $TMP;
+    $scaled->save($new);
+    make_path $dir;
+    rename $new, $thumb;
+    return $thumburl;
+  }
 }
 
 ###--------------------------------------------------------------------------
index 44a9ceb..7d76fdf 100755 (executable)
@@ -100,9 +100,9 @@ Failed to find &lsquo;<% $path |h %>&rsquo;.
 <div class=gallery>
 %   for my $d (@$dd) {
 %     my ($ddd, $fff, $iii) = listdir $real . "/" . $d->name;
-%     my $tn;
-%     if ($iii) { $tn = join_paths $path, $d->name, $iii->name; }
-%     else { $tn = undef; }
+%     my $tn = $iii ?
+%      TrivGal::Image->new(join_paths $path, $d->name, $iii->name) :
+%       undef;
   <& .thumbnail, target => $d->name . "/", comment => $d->comment,
                 img => $tn, size => "bigthumb",
                 caption => $m->interp->apply_escapes($d->name, "h") &>\
@@ -115,7 +115,8 @@ Failed to find &lsquo;<% $path |h %>&rsquo;.
 <div class=gallery>
 %   for my $f (@$ff) {
   <& .thumbnail, target => $f->name, comment => $f->comment,
-                img => $path . $f->name, size => "bigthumb",
+                img => TrivGal::Image->new($path . $f->name),
+                size => "bigthumb",
                 caption => $m->interp->apply_escapes($f->name, "h") &>\
 %   }
 </div>
@@ -139,7 +140,7 @@ Failed to find &lsquo;<% $path |h %>&rsquo;.
        my $realdir = join_paths $IMGROOT, $dir;
        my $urldir = join_paths $SCRIPTURL, $dir;
        my ($dd, $ff, $ii) = listdir $realdir;
-       my $vw = scaled "view", $path;
+       my $vw = TrivGal::Image->new($path)->scale("view");
 
        my $fi = undef;
        FILE: for (my $i = 0; $i < @$ff; $i++)
@@ -191,7 +192,7 @@ Failed to find &lsquo;<% $path |h %>&rsquo;.
 %
 <div class=thumbstrip>
 % for my $f (@$ff) {
-%   my $img = $dir . "/" . $f->name;
+%   my $img = TrivGal::Image->new($dir . "/" . $f->name);
   <& .thumbnail, target => $f->name, img => $img, size => "bigthumb",
                 caption => $m->interp->apply_escapes($f->name, "h"),
                 focus => $f->name eq "$base$ext" &>\
@@ -236,7 +237,7 @@ Failed to find &lsquo;<% $path |h %>&rsquo;.
 %###-------------------------------------------------------------------------
 <%def .thumbnail>\
 % my $tn;
-% if (defined $img) { $tn = scaled $size, $img; }
+% if (defined $img) { $tn = $img->scale($size); }
 % else { $tn = "$STATICURL/folder.svg"; }
 % if ($focus) {
   <figure class="thumb <% $size %>" id=focusthumb>