Merge branch 'ready/imgforpdf-and-more'

master
Simon McVittie 2014-09-12 21:59:00 +01:00
commit 9be3f95116
5 changed files with 150 additions and 67 deletions

View File

@ -65,82 +65,85 @@ sub preprocess (@) {
my $dir = $params{page}; my $dir = $params{page};
my $base = IkiWiki::basename($file); my $base = IkiWiki::basename($file);
my $issvg = $base=~s/\.svg$/.png/i; 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}; eval q{use Image::Magick};
error gettext("Image::Magick is not installed") if $@; error gettext("Image::Magick is not installed") if $@;
my $im = Image::Magick->new($issvg ? (magick => "png") : ()); my $im = Image::Magick->new();
my $imglink; 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; error sprintf(gettext("failed to read %s: %s"), $file, $r) if $r;
my ($dwidth, $dheight); 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*)$/); my ($w, $h) = ($params{size} =~ /^(\d*)x(\d*)$/);
error sprintf(gettext('wrong size format "%s" (should be WxH)'), $params{size}) error sprintf(gettext('wrong size format "%s" (should be WxH)'), $params{size})
unless (defined $w && defined $h && unless (defined $w && defined $h &&
(length $w || length $h)); (length $w || length $h));
if ((length $w && $w > $im->Get("width")) || if ($im->Get("width") == 0 || $im->Get("height") == 0) {
(length $h && $h > $im->Get("height"))) { ($dwidth, $dheight)=(0, 0);
# resizing larger } elsif (! length $w || (length $h && $im->Get("height")*$w > $h * $im->Get("width"))) {
$imglink = $file; # 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")
# don't generate larger image, just set display size $dheight=$h;
if (length $w && length $h) { $dwidth=$h / $im->Get("height") * $im->Get("width");
($dwidth, $dheight)=($w, $h); } else { # (! length $h) or $w is what determines the resized size
} $dwidth=$w;
# avoid division by zero on 0x0 image $dheight=$w / $im->Get("width") * $im->Get("height");
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");
}
}
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;
}
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;
}
}
# always get the true size of the resized image
$dwidth = $im->Get("width");
$dheight = $im->Get("height");
} }
} }
else {
$imglink = $file; if ($dwidth < $im->Get("width") || $ispdf) {
$dwidth = $im->Get("width"); # 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 {
$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 {
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 (it could be
# that imagemagick did its calculations differently)
$dwidth = $im->Get("width");
$dheight = $im->Get("height"); $dheight = $im->Get("height");
} else {
$imglink = $file;
} }
if (! defined($dwidth) || ! defined($dheight)) { if (! defined($dwidth) || ! defined($dheight)) {
@ -148,14 +151,9 @@ sub preprocess (@) {
} }
my ($fileurl, $imgurl); my ($fileurl, $imgurl);
if (! $params{preview}) { my $urltobase = $params{preview} ? undef : $params{destpage};
$fileurl=urlto($file, $params{destpage}); $fileurl=urlto($file, $urltobase);
$imgurl=urlto($imglink, $params{destpage}); $imgurl=$imgdatalink ? $imgdatalink : urlto($imglink, $urltobase);
}
else {
$fileurl=urlto($file);
$imgurl=urlto($imglink);
}
if (! exists $params{class}) { if (! exists $params{class}) {
$params{class}="img"; $params{class}="img";

View File

@ -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 to another page instead, or "link=no" to disable the link, or
"link=http://url" to link to a given url. "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 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. the page, unless overridden. Useful when including many images on a page.

82
t/img.t 100755
View File

@ -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;

BIN
t/img/redsquare.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 B

BIN
t/img/twopages.pdf 100644

Binary file not shown.