Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select PHP's Image resizing algorithm

The function imagecopyresampled is useful to generate a thumbnail or resize images, while keeping aspect ratio:

$fn = $_FILES['data']['tmp_name'];
$size = getimagesize($fn);
$width = $size[0];
$height = $size[1];
$ratio = $width / $height;
if ($ratio > 1 && $size[0] > 500) { $width = 500; $height = 500 / $ratio; }
else { if ($ratio <= 1 && $size[1] > 500) { $width = 500 * $ratio; $height = 500; }}
$src = imagecreatefromstring(file_get_contents($fn));
$dst = imagecreatetruecolor($width, $height);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $width, $height, $size[0], $size[1]);
imagedestroy($src);
imagejpeg($dst, 'test.jpg');
imagedestroy($dst);

How can I select the resizing algorithm used by PHP?
Note: as stated in this question, setting imagesetinterpolation($dst, IMG_BILINEAR_FIXED); or such things doesn't seem to work.


According to tests I did (in another language), "bilinear resizing" sometimes gives better result than bicubic, and sometimes it's the contrary (depends if it's downsizing or upsizing).


(source: dpchallenge.com)

like image 499
Basj Avatar asked Jan 18 '17 14:01

Basj


2 Answers

An alternative is the imagescale() function, that allows specifying the interpolation algorithm as a parameter:

imagescale($image, $new_width, $new_height, $algorithm);

According to the documentation $algorithm can be:

One of IMG_NEAREST_NEIGHBOUR, IMG_BILINEAR_FIXED, IMG_BICUBIC, IMG_BICUBIC_FIXED or anything else (will use two pass).

A test in PHP 7.0.15 (comparing file hash) shows that BICUBIC and BICUBIC_FIXED result in a different image, while BILINEAR_FIXED and NEAREST_NEIGHBOUR result in the same image.

like image 83
timclutton Avatar answered Oct 30 '22 19:10

timclutton


imagecopyresampled is based/part of LibGD , by looking at the source code of LibGD, you can see clearly its implementation , also the documentation is not ambiguous about the used algorithm as it's stated that :

If the source and destination area differ in size, the area will be resized using bilinear interpolation for truecolor images, and nearest-neighbor interpolation for palette images.

So how can you select the resizing algorithm used by PHP?

If you insist/must use LibGD functions, you can't (unless you recompile PHP with a LibGD fork you code just for this matter).

However if you're free to use another image manipulation library, you can simply use one that use a different algorithm for resizing, for example Imagick seems to offer a wide range of interpolations but since the documentation is quite mute about it here is the constants needed to use the Imagick::setImageInterpolateMethod(int $) method :

const INTERPOLATE_UNDEFINED = 0;
const INTERPOLATE_AVERAGE = 1;
const INTERPOLATE_BICUBIC = 2;
const INTERPOLATE_BILINEAR = 3;
const INTERPOLATE_FILTER = 4;
const INTERPOLATE_INTEGER = 5;
const INTERPOLATE_MESH = 6;
const INTERPOLATE_NEARESTNEIGHBOR = 7;
const INTERPOLATE_SPLINE = 8;
like image 38
mrbm Avatar answered Oct 30 '22 19:10

mrbm