summaryrefslogtreecommitdiff
path: root/IkiWiki/Plugin/img.pm
blob: 9f9c72c500a3efb428da8918025b77df68eca4c2 (plain)
  1. #!/usr/bin/perl
  2. # Ikiwiki enhanced image handling plugin
  3. # Christian Mock cm@tahina.priv.at 20061002
  4. package IkiWiki::Plugin::img;
  5. use warnings;
  6. use strict;
  7. use IkiWiki 3.00;
  8. my %imgdefaults;
  9. sub import {
  10.     hook(type => "getsetup"id => "img"call => \&getsetup);
  11.     hook(type => "preprocess"id => "img"call => \&preprocessscan => 1);
  12. }
  13. sub getsetup () {
  14.     return
  15.         plugin => {
  16.             safe => 1,
  17.             rebuild => undef,
  18.             section => "widget",
  19.         },
  20. }
  21. sub preprocess (@) {
  22.     my ($image) = $_[0] =~ /$config{wiki_file_regexp}/# untaint
  23.     my %params=@_;
  24.     if (! defined $image) {
  25.         error("bad image filename");
  26.     }
  27.     if (exists $imgdefaults{$params{page}}) {
  28.         foreach my $key (keys %{$imgdefaults{$params{page}}}) {
  29.             if (! exists $params{$key}) {
  30.                 $params{$key}=$imgdefaults{$params{page}}->{$key};
  31.             }
  32.         }
  33.     }
  34.     if (! exists $params{size} || ! length $params{size}) {
  35.         $params{size}='full';
  36.     }
  37.     if ($image eq 'defaults') {
  38.         $imgdefaults{$params{page}} = \%params;
  39.         return '';
  40.     }
  41.     add_link($params{page}, $image);
  42.     add_depends($params{page}, $image);
  43.     # optimisation: detect scan mode, and avoid generating the image
  44.     if (! defined wantarray) {
  45.         return;
  46.     }
  47.     my $file bestlink($params{page}, $image);
  48.     my $srcfile srcfile($file1);
  49.     if (! length $file || ! defined $srcfile) {
  50.         return htmllink($params{page}, $params{destpage}, $image);
  51.     }
  52.     my $dir $params{page};
  53.     my $base IkiWiki::basename($file);
  54.     my $issvg $base=~s/\.svg$/.png/i;
  55.     my $usegm 1;
  56.     my $ispdf $base=~s/\.pdf$/.png/i;
  57.     my $pagenumber exists($params{pagenumber}) int($params{pagenumber}) : 0;
  58.     if ($pagenumber != 0) {
  59.         $base "p$pagenumber-$base";
  60.     }
  61.     eval q{use Graphics::Magick};
  62.     if ($@) {
  63.         $usegm 0;
  64.         eval q{use Image::Magick};
  65.         error gettext("Image::Magick is not installed"if $@;
  66.     }
  67.     my $im $usegm
  68.         ? Graphics::Magick->new($issvg (magick => "png") : ())
  69.         Image::Magick->new($issvg (magick => "png") : ());
  70.     my $imglink;
  71.     my $imgdatalink;
  72.     my $r $im->Read("$srcfile\[$pagenumber]");
  73.     error sprintf(gettext("failed to read %s%s"), $file$rif $r;
  74.     if (! defined $im->Get("width") || ! defined $im->Get("height")) {
  75.         error sprintf(gettext("failed to get dimensions of %s"), $file);
  76.     }
  77.     my ($dwidth$dheight);
  78.     if ($params{sizeeq 'full') {
  79.         $dwidth $im->Get("width");
  80.         $dheight $im->Get("height");
  81.     else {
  82.         my ($w$h) = ($params{size} =~ /^(\d*)x(\d*)$/);
  83.         error sprintf(gettext('wrong size format "%s" (should be WxH)'), $params{size})
  84.             unless (defined $w && defined $h &&
  85.                     (length $w || length $h));
  86.         if ($im->Get("width") == || $im->Get("height") == 0) {
  87.             ($dwidth$dheight)=(00);
  88.         elsif (! length $w || (length $h && $im->Get("height")*$w $h $im->Get("width"))) {
  89.             # using height because only height is given or ...
  90.             # because original image is more portrait than $w/$h
  91.             # ... slimness of $im > $h/w
  92.             # ... $im->Get("height")/$im->Get("width") > $h/$w
  93.             # ... $im->Get("height")*$w > $h * $im->Get("width")
  94.             $dheight=$h;
  95.             $dwidth=$h $im->Get("height") * $im->Get("width");
  96.         else # (! length $h) or $w is what determines the resized size
  97.             $dwidth=$w;
  98.             $dheight=$w $im->Get("width") * $im->Get("height");
  99.         }
  100.     }
  101.     if ($dwidth $im->Get("width") || $ispdf) {
  102.         # resize down, or resize to pixels at all
  103.         my $outfile "$config{destdir}/$dir/$params{size}-$base";
  104.         $imglink "$dir/$params{size}-$base";
  105.         will_render($params{page}, $imglink);
  106.         if (-$outfile && (-$srcfile >= -$outfile)) {
  107.             $im $usegm ? Graphics::Magick->new Image::Magick->new;
  108.             $r $im->Read($outfile);
  109.             error sprintf(gettext("failed to read %s%s"), $outfile$rif $r;
  110.         }
  111.         else {
  112.             $r $im->Resize(geometry => "${dwidth}x${dheight}");
  113.             error sprintf(gettext("failed to resize: %s"), $rif $r;
  114.             $im->set(($issvg || $ispdf(magick => 'png') : ());
  115.             my @blob $im->ImageToBlob();
  116.             # don't actually write resized file in preview mode;
  117.             # rely on width and height settings
  118.             if (! $params{preview}) {
  119.                 writefile($imglink$config{destdir}, $blob[0], 1);
  120.             }
  121.             else {
  122.                 eval q{use MIME::Base64};
  123.                 error($@if $@;
  124.                 $imgdatalink "data:image/".$im->Get("magick").";base64,".encode_base64($blob[0]);
  125.             }
  126.         }
  127.         # always get the true size of the resized image (it could be
  128.         # that imagemagick did its calculations differently)
  129.         $dwidth  $im->Get("width");
  130.         $dheight $im->Get("height");
  131.     else {
  132.         $imglink $file;
  133.     }
  134.     
  135.     if (! defined($dwidth) || ! defined($dheight)) {
  136.         error sprintf(gettext("failed to determine size of image %s"), $file)
  137.     }
  138.     my ($fileurl$imgurl);
  139.     my $urltobase $params{previewundef $params{destpage};
  140.     $fileurl=urlto($file$urltobase);
  141.     $imgurl=$imgdatalink $imgdatalink urlto($imglink$urltobase);
  142.     if (! exists $params{class}) {
  143.         $params{class}="img";
  144.     }
  145.     my $attrs='';
  146.     foreach my $attr (qw{alt title class id hspace vspace}) {
  147.         if (exists $params{$attr}) {
  148.             $attrs.=$attr=\"$params{$attr}\"";
  149.         }
  150.     }
  151.     
  152.     my $imgtag='<img src="'.$imgurl.
  153.         '" width="'.$dwidth.
  154.         '" height="'.$dheight.'"'.
  155.         $attrs.
  156.         (exists $params{align} && ! exists $params{caption' align="'.$params{align}.'"' '').
  157.         ' />';
  158.     my $link;
  159.     if (! defined $params{link}) {
  160.         $link=$fileurl;
  161.     }
  162.     elsif ($params{link} =~ /^\w+:\/\//) {
  163.         $link=$params{link};
  164.     }
  165.     if (defined $link) {
  166.         $imgtag='<a href="'.$link.'">'.$imgtag.'</a>';
  167.     }
  168.     else {
  169.         my $b bestlink($params{page}, $params{link});
  170.     
  171.         if (length $b) {
  172.             add_depends($params{page}, $bdeptype("presence"));
  173.             $imgtag=htmllink($params{page}, $params{destpage},
  174.                 $params{link}, linktext => $imgtag,
  175.                 noimageinline => 1,
  176.             );
  177.         }
  178.     }
  179.     if (exists $params{caption}) {
  180.         return '<table class="img'.
  181.             (exists $params{align" align-$params{align}" "").
  182.             '">'.
  183.             '<caption>'.$params{caption}.'</caption>'.
  184.             '<tr><td>'.$imgtag.'</td></tr>'.
  185.             '</table>';
  186.     }
  187.     else {
  188.         return $imgtag;
  189.     }
  190. }
  191. 1