aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--IkiWiki/Plugin/img.pm128
-rw-r--r--doc/ikiwiki/directive/img.mdwn3
-rwxr-xr-xt/img.t82
-rw-r--r--t/img/redsquare.pngbin0 -> 84 bytes
-rw-r--r--t/img/twopages.pdfbin0 -> 2295 bytes
5 files changed, 148 insertions, 65 deletions
diff --git a/IkiWiki/Plugin/img.pm b/IkiWiki/Plugin/img.pm
index b92e24cc0..54c13d069 100644
--- a/IkiWiki/Plugin/img.pm
+++ b/IkiWiki/Plugin/img.pm
@@ -65,82 +65,85 @@ sub preprocess (@) {
my $dir = $params{page};
my $base = IkiWiki::basename($file);
my $issvg = $base=~s/\.svg$/.png/i;
+ my $ispdf = $base=~s/\.pdf$/.png/i;
+ my $pagenumber = exists($params{pagenumber}) ? int($params{pagenumber}) : 0;
+ if ($pagenumber != 0) {
+ $base = "p$pagenumber-$base";
+ }
eval q{use Image::Magick};
error gettext("Image::Magick is not installed") if $@;
- my $im = Image::Magick->new($issvg ? (magick => "png") : ());
+ my $im = Image::Magick->new();
my $imglink;
- my $r = $im->Read($srcfile);
+ my $imgdatalink;
+ my $r = $im->Read("$srcfile\[$pagenumber]");
error sprintf(gettext("failed to read %s: %s"), $file, $r) if $r;
my ($dwidth, $dheight);
- if ($params{size} ne 'full') {
+ if ($params{size} eq 'full') {
+ $dwidth = $im->Get("width");
+ $dheight = $im->Get("height");
+ } else {
my ($w, $h) = ($params{size} =~ /^(\d*)x(\d*)$/);
error sprintf(gettext('wrong size format "%s" (should be WxH)'), $params{size})
unless (defined $w && defined $h &&
(length $w || length $h));
-
- if ((length $w && $w > $im->Get("width")) ||
- (length $h && $h > $im->Get("height"))) {
- # resizing larger
- $imglink = $file;
-
- # don't generate larger image, just set display size
- if (length $w && length $h) {
- ($dwidth, $dheight)=($w, $h);
- }
- # avoid division by zero on 0x0 image
- elsif ($im->Get("width") == 0 || $im->Get("height") == 0) {
- ($dwidth, $dheight)=(0, 0);
- }
- # calculate unspecified size from the other one, preserving
- # aspect ratio
- elsif (length $w) {
- $dwidth=$w;
- $dheight=$w / $im->Get("width") * $im->Get("height");
- }
- elsif (length $h) {
- $dheight=$h;
- $dwidth=$h / $im->Get("height") * $im->Get("width");
- }
+
+ if ($im->Get("width") == 0 || $im->Get("height") == 0) {
+ ($dwidth, $dheight)=(0, 0);
+ } elsif (! length $w || (length $h && $im->Get("height")*$w > $h * $im->Get("width"))) {
+ # using height because only height is given or ...
+ # because original image is more portrait than $w/$h
+ # ... slimness of $im > $h/w
+ # ... $im->Get("height")/$im->Get("width") > $h/$w
+ # ... $im->Get("height")*$w > $h * $im->Get("width")
+
+ $dheight=$h;
+ $dwidth=$h / $im->Get("height") * $im->Get("width");
+ } else { # (! length $h) or $w is what determines the resized size
+ $dwidth=$w;
+ $dheight=$w / $im->Get("width") * $im->Get("height");
+ }
+ }
+
+ if ($dwidth < $im->Get("width") || $ispdf) {
+ # resize down, or resize to pixels at all
+
+ my $outfile = "$config{destdir}/$dir/$params{size}-$base";
+ $imglink = "$dir/$params{size}-$base";
+
+ will_render($params{page}, $imglink);
+
+ if (-e $outfile && (-M $srcfile >= -M $outfile)) {
+ $im = Image::Magick->new;
+ $r = $im->Read($outfile);
+ error sprintf(gettext("failed to read %s: %s"), $outfile, $r) if $r;
}
else {
- # resizing smaller
- my $outfile = "$config{destdir}/$dir/${w}x${h}-$base";
- $imglink = "$dir/${w}x${h}-$base";
-
- will_render($params{page}, $imglink);
-
- if (-e $outfile && (-M $srcfile >= -M $outfile)) {
- $im = Image::Magick->new;
- $r = $im->Read($outfile);
- error sprintf(gettext("failed to read %s: %s"), $outfile, $r) if $r;
+ $r = $im->Resize(geometry => "${dwidth}x${dheight}");
+ error sprintf(gettext("failed to resize: %s"), $r) if $r;
+
+ $im->set(($issvg || $ispdf) ? (magick => 'png') : ());
+ my @blob = $im->ImageToBlob();
+ # don't actually write resized file in preview mode;
+ # rely on width and height settings
+ if (! $params{preview}) {
+ writefile($imglink, $config{destdir}, $blob[0], 1);
}
else {
- $r = $im->Resize(geometry => "${w}x${h}");
- error sprintf(gettext("failed to resize: %s"), $r) if $r;
-
- # don't actually write resized file in preview mode;
- # rely on width and height settings
- if (! $params{preview}) {
- my @blob = $im->ImageToBlob();
- writefile($imglink, $config{destdir}, $blob[0], 1);
- }
- else {
- $imglink = $file;
- }
+ eval q{use MIME::Base64};
+ error($@) if $@;
+ $imgdatalink = "data:image/".$im->Get("magick").";base64,".encode_base64($blob[0]);
}
-
- # always get the true size of the resized image
- $dwidth = $im->Get("width");
- $dheight = $im->Get("height");
}
- }
- else {
- $imglink = $file;
- $dwidth = $im->Get("width");
+
+ # always get the true size of the resized image (it could be
+ # that imagemagick did its calculations differently)
+ $dwidth = $im->Get("width");
$dheight = $im->Get("height");
+ } else {
+ $imglink = $file;
}
if (! defined($dwidth) || ! defined($dheight)) {
@@ -148,14 +151,9 @@ sub preprocess (@) {
}
my ($fileurl, $imgurl);
- if (! $params{preview}) {
- $fileurl=urlto($file, $params{destpage});
- $imgurl=urlto($imglink, $params{destpage});
- }
- else {
- $fileurl=urlto($file);
- $imgurl=urlto($imglink);
- }
+ my $urltobase = $params{preview} ? undef : $params{destpage};
+ $fileurl=urlto($file, $urltobase);
+ $imgurl=$imgdatalink ? $imgdatalink : urlto($imglink, $urltobase);
if (! exists $params{class}) {
$params{class}="img";
diff --git a/doc/ikiwiki/directive/img.mdwn b/doc/ikiwiki/directive/img.mdwn
index cda62b58f..08d158987 100644
--- a/doc/ikiwiki/directive/img.mdwn
+++ b/doc/ikiwiki/directive/img.mdwn
@@ -28,6 +28,9 @@ to the full size version. By default it does; set "link=somepage" to link
to another page instead, or "link=no" to disable the link, or
"link=http://url" to link to a given url.
+The `pagenumber` parameter selects which of multiple images should be rendered;
+this is relevant mainly for GIF and PDF source images.
+
You can also set default values that will be applied to all later images on
the page, unless overridden. Useful when including many images on a page.
diff --git a/t/img.t b/t/img.t
new file mode 100755
index 000000000..9a48cb1c5
--- /dev/null
+++ b/t/img.t
@@ -0,0 +1,82 @@
+#!/usr/bin/perl
+#
+# unit test that creates test images (png, svg, multi-page pdf), runs ikiwiki
+# on them, checks the resulting images for plausibility based on their image
+# sizes, and checks if they vanish when not required in the build process any
+# more
+#
+# if you have trouble here, be aware that there are three debian packages that
+# can provide Image::Magick: perlmagick, libimage-magick-perl and
+# graphicsmagick-libmagick-dev-compat
+#
+package IkiWiki;
+
+use warnings;
+use strict;
+use Test::More;
+
+BEGIN { use_ok("IkiWiki"); }
+BEGIN { use_ok("Image::Magick"); }
+
+ok(! system("rm -rf t/tmp; mkdir -p t/tmp/in"));
+
+ok(! system("cp t/img/redsquare.png t/tmp/in/redsquare.png"));
+writefile("emptysquare.svg", "t/tmp/in", '<svg width="30" height="30"/>');
+# using different image sizes for different pages, so the pagenumber selection can be tested easily
+ok(! system("cp t/img/twopages.pdf t/tmp/in/twopages.pdf"));
+
+writefile("imgconversions.mdwn", "t/tmp/in", <<EOF
+[[!img redsquare.png]]
+[[!img redsquare.png size=10x]]
+[[!img redsquare.png size=30x50]] expecting 30x30
+[[!img emptysquare.svg size=10x]]
+[[!img twopages.pdf size=12x]]
+[[!img twopages.pdf size=16x pagenumber=1]]
+EOF
+);
+
+ok(! system("make -s ikiwiki.out"));
+
+my $command = "perl -I. ./ikiwiki.out -set usedirs=0 -plugin img t/tmp/in t/tmp/out -verbose";
+
+ok(! system($command));
+
+sub size($) {
+ my $filename = shift;
+ my $im = Image::Magick->new();
+ my $r = $im->Read($filename);
+ return "no image" if $r;
+ my $w = $im->Get("width");
+ my $h = $im->Get("height");
+ return "${w}x${h}";
+}
+
+my $outpath = "t/tmp/out/imgconversions";
+my $outhtml = readfile("$outpath.html");
+
+is(size("$outpath/10x-redsquare.png"), "10x10");
+ok(! -e "$outpath/30x-redsquare.png");
+ok($outhtml =~ /width="30" height="30".*expecting 30x30/);
+# if this fails, you need libmagickcore-6.q16-2-extra installed
+is(size("$outpath/10x-emptysquare.png"), "10x10");
+is(size("$outpath/12x-twopages.png"), "12x12");
+is(size("$outpath/16x-p1-twopages.png"), "16x2");
+
+# now let's remove them again
+
+if (1) { # for easier testing
+ writefile("imgconversions.mdwn", "t/tmp/in", "nothing to see here");
+
+ ok(! system("$command --refresh"));
+
+ ok(! -e "$outpath/10x-simple.png");
+ ok(! -e "$outpath/10x-simple-svg.png");
+ ok(! -e "$outpath/10x-simple-pdf.png");
+ ok(! -e "$outpath/10x-p1-simple-pdf.png");
+
+ # cleanup
+ ok(! system("rm -rf t/tmp"));
+}
+done_testing;
+
+1;
diff --git a/t/img/redsquare.png b/t/img/redsquare.png
new file mode 100644
index 000000000..0033932aa
--- /dev/null
+++ b/t/img/redsquare.png
Binary files differ
diff --git a/t/img/twopages.pdf b/t/img/twopages.pdf
new file mode 100644
index 000000000..8be9b6539
--- /dev/null
+++ b/t/img/twopages.pdf
Binary files differ