9

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)

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Basj
  • 41,386
  • 99
  • 383
  • 673
  • As noted [here](http://php.net/manual/fr/function.imagecopyresampled.php#54448) by someone: "It should be noted that the imagecopyresampled() function is much more blurry than Photoshop CS's default bicubic funtion. And looks similar to a blury version of Photoshop's bilinear function. The documentation fails to note which algorithm is used in resampling." – Basj Jan 18 '17 at 14:41
  • 1
    It looks like it doesn't apply to imagecopyresampled - I shall delete it as incorrect while I try to work it out. Sorry. – Mark Setchell Jan 18 '17 at 21:21
  • As stated [in this question](http://stackoverflow.com/q/41729409/1422096), setting `imagesetinterpolation($dst, IMG_BILINEAR_FIXED);` or such things doesn't seem to work. – Basj Jan 26 '17 at 18:17
  • _"How can I modify the resizing algorithm used by PHP?"_ wouldn't it be easier to just write your own custom PHP function rather than modify the programming language itself (if that's even allowed)? – VC.One Jan 27 '17 at 06:52
  • 1
    I've edited a keyword in your Question, since I understand it better now. Don't say _"I want to **modify** algorithm X"_ when really you mean _"I want to **select** option of algorithm X"_... The former suggests you want to modify PHP source code's functions. You just want to enable some resize option... correct? – VC.One Jan 28 '17 at 21:45

4 Answers4

12

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.

timclutton
  • 12,682
  • 3
  • 33
  • 43
  • Seems great! I'll test asap. – Basj Jan 30 '17 at 14:57
  • 1
    @Basj this is the Answer I was going to give myself. I think it's correct for your needs...? – VC.One Jan 30 '17 at 15:49
  • For me using `imagescale()` with `IMG_BICUBIC` makes the image even blurrier, and introduces weird artifact in flat colours. – Chris Seufert Nov 13 '19 at 06:47
  • 2
    I can't say which filter produces the best results but avoid using `IMG_BICUBIC_FIXED`, `IMG_BILINEAR_FIXED` and `IMG_NEAREST_NEIGHBOUR` as those methods produce really bad images (I tested downscaling). – mgutt Apr 19 '20 at 21:35
  • 3
    An important note is the "or anything else" in the manual. I noticed that I can use many more filter types, listed here https://www.php.net/manual/de/function.imagesetinterpolation.php . Probably all except IMG_WEIGHTED4 (see php manual for imagescale). I had good results with e.g. IMG_CATMULLROM for downscaling (tested in PHP 7). – Jens Jul 24 '20 at 09:13
5

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;
mrbm
  • 2,164
  • 12
  • 11
0

Why do you not use a library? I think that if you use a php library it will be more easy. Try this one. Hope it will help you.

Faegy
  • 942
  • 1
  • 12
  • 29
cakpep
  • 87
  • 6
  • @Cakpep check the new edit & re-read for true meaning of Question. You can [**`edit`**](http://stackoverflow.com/posts/41889086/edit) your Answer with new info, if you wish... – VC.One Jan 28 '17 at 21:55
  • This library won't allow to change algorithm. See [this comment](https://github.com/eventviva/php-image-resize/issues/68): `http://php.net/manual/en/function.imagecopyresampled.php this is the function used internally by library. I could not find information on which algorithm is used by the function.` – Basj Jan 30 '17 at 14:56
0

Well you could download the PHP Source , add your filter function and compile php.

here you can find the filters https://github.com/php/php-src/blob/master/ext/gd/libgd/gd_interpolation.c#L481

here is the switch case where you have to apply the method https://github.com/php/php-src/blob/master/ext/gd/libgd/gd_interpolation.c#L2530

here you can define constants https://github.com/php/php-src/blob/master/ext/gd/libgd/gd.h#L137

happy hacking :D

Vitalij Mik
  • 542
  • 3
  • 6
  • There is nothing wrong with this Answer. It's correct for the previous wording of Question which suggested the Asker wanted to modify the source code of a re-sampling algorithm. I've edited the Question. @VitalijMik, check the new edit if you wish to [**`change`**](http://stackoverflow.com/posts/41889429/edit) your Answer also... – VC.One Jan 28 '17 at 21:58