From a308b212ad697fb204fa8543d00c39a24f58de5f Mon Sep 17 00:00:00 2001 From: chrysn Date: Tue, 15 Jul 2014 00:23:56 +0200 Subject: [PATCH] img plugin: split resizing calculations and actual resizing there is now a size calculating part (which chooses a final size) and a scaling part (which triggers if the sizes calculated by the former indicate a downscaling). this solves the issue of unproportional upscalings (bugs/image_rescaling_distorts_with_small_pictures). also, "small" pdf files (or pdf files without explicit size settings), which would not be converted under the old mechanism, now get rendered to pngs. this commit affects a unit test: while svgs were previously unconditionally rendered to pngs, this now only happens on downscaling. this is intentional -- while a small version of an svg graphic is likely to be more compact when rendered (eg as a preview), a large version would not have that benefit, and why convert something that browsers basically can show and be inconsistend with how other images are handled. the new unit test simply makes the original svg larger to check for the same behaviros as before. --- IkiWiki/Plugin/img.pm | 106 ++++++++++++++++++++---------------------- t/img.t | 2 +- 2 files changed, 51 insertions(+), 57 deletions(-) diff --git a/IkiWiki/Plugin/img.pm b/IkiWiki/Plugin/img.pm index fe0ba2ef1..1ab753352 100644 --- a/IkiWiki/Plugin/img.pm +++ b/IkiWiki/Plugin/img.pm @@ -80,73 +80,67 @@ sub preprocess (@) { 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; + + # don't actually write resized file in preview mode; + # rely on width and height settings + if (! $params{preview}) { + $im->set(($issvg || $ispdf) ? (magick => 'png') : ()); + my @blob = $im->ImageToBlob(); + 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}) { - $im->set(($issvg || $ispdf) ? (magick => 'png') : ()); - my @blob = $im->ImageToBlob(); - writefile($imglink, $config{destdir}, $blob[0], 1); - } - else { - $imglink = $file; - } + $imglink = $file; } - - # 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)) { diff --git a/t/img.t b/t/img.t index c336c6744..0183f8779 100755 --- a/t/img.t +++ b/t/img.t @@ -21,7 +21,7 @@ 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", ''); +writefile("emptysquare.svg", "t/tmp/in", ''); # 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")); -- 2.39.5