note 125882 added to function.imageaffine
| From: | der at herrstrietzel dot de | Date: | Sat, 06 Mar 2021 01:43:12 +0000 |
| Subject: | note 125882 added to function.imageaffine | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-219316@lists.php.net to get a copy of this message | ||
Might be an alternative or workaround for imagecopyresampled as imageaffine supports more
sophisticated interpolation such as IMG_MITCHELL.
// create image resource
$img_path = 'test.jpg';
$img = imagecreatefromstring(file_get_contents($img_path));
// scale image to 50% with Mitchell interpolation
$scale = 0.5;
imagesetinterpolation($img, IMG_MITCHELL);
$img_scaled = imageaffine($img, [0.5, 0, 0, 0.5, 0, 0]);
// save image
$output = 'test_scaledAffine.png';
imagepng($img_scaled, $output, 9);
echo '<img src="'.$output.'" width="300">';
Helper function example:
function scaleImgAffine($img, $newWidth, $resized_file='', $interpolation=IMG_MITCHELL)
{
// create img resource if $img is file path
if(!is_resource($img)){
$img = imagecreatefromstring(file_get_contents($img));
}
// get original img dimensions
$w = imagesx($img);
$h = imagesy($img);
/**
* recommended interpolation method is 'IMG_MITCHELL'
* providing the overall best precision and
* compression for most image types
* in particular for pngs with transparency suffering
* from artifacted downsampling result
*/
imagesetinterpolation($img, $interpolation);
/*
* imageaffine will scale dimensions in an anamorphic way â
* even with square based images:
* 1200x1200 will get something like 1199x1200
* â improvements are very welcome
* Workaround: Adjusting both the original width and the clip parameter
* by adding 1px solved the issue for me
*/
$scale = ($newWidth+1) / $w;
$newHeight = floor($h*$scale);
// scale by affine matrix
$resized_affine =
imageaffine(
$img,
[$scale, 0, 0, $scale, 0, 0],
['x' => 0, 'y' => 0, 'width' => $w, 'height'
=> $h-1]
);
/*
* 'clip' parameter might be misleading as it expects
* the original and not the final/transformed width
*/
// save to file or return resource
if($resized_file){
$file_type = pathinfo($resized_file, PATHINFO_EXTENSION );
switch($file_type){
case 'jpg':
case 'jpeg':
// flatten transparency for jpgs
$tmp_img = imagecreatetruecolor($newWidth, $newHeight );
$bg = imagecolorallocate($tmp_img, 255,255,255);
imagefill($tmp_img, 0, 0, $bg);
imagesavealpha($tmp_img, false);
imagealphablending($tmp_img, true);
imagecopy($tmp_img, $resized_affine, 0, 0, 0, 0, $newWidth, $newHeight );
imagejpeg($tmp_img, $resized_file, 85);
break;
case 'png':
imagepng($resized_affine, $resized_file, 9);
break;
}
}else{
return $resized_affine;
}
}
$img_scaled_affine = scaleImgAffine($img_path, 400, 'test_scaledAffine.jpg', true);
IMG_MITCHELL is in particular advanced when it comes to scaling png24 with transparency in GDlib
environments (... actually png31 due to gds alpha 7bit channel?). Most commonly you'll
experience bad compression using png due to imperceptible artifacts after resizing.
Hopefully we'll see an implementation of more advanced interpolation methods in basic GD
resizing functions like imagecopyresized or imagescale.
----
Server IP: 45.112.84.4
Probable Submitter: 45.112.85.247 (proxied: 77.3.140.181)
----
Manual Page -- http://php.net/manual/en/function.imageaffine.php
Edit -- https://master.php.net/note/edit/125882
Del: integrated -- https://master.php.net/note/delete/125882/integrated
Del: useless -- https://master.php.net/note/delete/125882/useless
Del: bad code -- https://master.php.net/note/delete/125882/bad+code
Del: spam -- https://master.php.net/note/delete/125882/spam
Del: non-english -- https://master.php.net/note/delete/125882/non-english
Del: in docs -- https://master.php.net/note/delete/125882/in+docs
Del: other reasons-- https://master.php.net/note/delete/125882
Reject -- https://master.php.net/note/reject/125882
Search -- https://master.php.net/manage/user-notes.php