PHP - Create thumbnail from picture and keeping proportion - php

I want to create a thumbnail image without black/white bars and have it keep aspect ratio
The thumbnail size should be 320x200 (px).
I actually wrote a function to create a thumbnail for a given resolution but I don't know how to keep the aspect ratio of the image
function imageResize($imageResourceId, $width, $height)
{
$targetWidth = 320;
$targetHeight = 200;
$targetLayer = imagecreatetruecolor($targetWidth, $targetHeight);
imagecopyresampled($targetLayer, $imageResourceId, 0, 0, 0, 0, $targetWidth, $targetHeight, $width, $height);
return $targetLayer;
}
But I can't figure out a way to crop them and have them accommodated as I want. Thanks in advance!

To do this you can use imagecopyresampled function like this:
function imageResize($imageResourceId, $width, $height)
{
$targetWidth = 320;
$targetHeight = 200;
$aspectRatio = $width / $height;
$targetRatio = $targetWidth / $targetHeight;
if ($aspectRatio > $targetRatio) {
$newHeight = $targetHeight;
$newWidth = $targetHeight * $aspectRatio;
} else {
$newWidth = $targetWidth;
$newHeight = $targetWidth / $aspectRatio;
}
$targetLayer = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($targetLayer, $imageResourceId, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
return $targetLayer;
}
Using this, the new Width and Height are calculated based on the aspect ratio of the original image.
More samples on: https://www.php.net/manual/en/function.imagecopyresampled.php

Related

imagecopyresampled / copy issue

I have the following class
public static function resize_imagejpg($file, $new_width, $new_height) {
list($orig_width, $orig_height) = getimagesize($file);
$width = $orig_width;
$height = $orig_height;
# taller
if ($height > $new_width) {
$width = ($new_height / $height) * $width;
$height = $new_height;
}
# wider
if ($width > $new_width) {
$height = ($new_width / $width) * $height;
$width = $new_width;
}
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($file);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $orig_width, $orig_height);
return $image_p;
}
i'm calling it by
$tmp = Url::resize_imagejpg('uploads/temp.jpg', 300, 300);
then
copy($tmp, 'uploads/thumb.jpg');
but i get the following error
Error on May 10, 2021 21:30PM - copy() expects parameter 1 to be a valid path, resource given in /home....
I know the file is their, i know its an image because i have opened it in an editor but i keep getting that error message
PLEASE HELP!!!
You need to use imagejpeg instead of copy.

why image background color is showing me blurry when I crop the image using PHP?

I am using following php function to crop a image. When a image is cropped then the image background is look like a blurry. Like bellow image. It's should be solid white background color :
Blurry Image :
Php code is bellow :
function crop_image ($target, $newcopy, $w, $h, $ext) {
$ext = strtolower($ext);
if ($ext == "gif"){
$image = imagecreatefromgif($target);
} else if($ext =="png"){
$image = imagecreatefrompng($target);
} else {
$image = imagecreatefromjpeg($target);
}
$filename = $newcopy;
$thumb_width = $w;
$thumb_height = $h;
$width = imagesx($image);
$height = imagesy($image);
$original_aspect = $width / $height;
$thumb_aspect = $thumb_width / $thumb_height;
if ( $original_aspect >= $thumb_aspect )
{
$new_height = $thumb_height;
$new_width = $width / ($height / $thumb_height);
}
else
{
$new_width = $thumb_width;
$new_height = $height / ($width / $thumb_width);
}
$thumb = imagecreatetruecolor( $thumb_width, $thumb_height );
$color = imagecolorallocate($thumb, 255, 255, 255);
imagefill($thumb, 0, 0, $color);
imagecopyresampled($thumb,
$image,
0 - ($new_width - $thumb_width) / 2, // Center the image horizontally
0 - ($new_height - $thumb_height) / 2, // Center the image vertically
0, 0,
$new_width, $new_height,
$width, $height);
imagejpeg($thumb, $filename, 80);
}
You're feeding a $quality value of 80 into imagejpeg. JPEG is a lossy format. This results in artifacts like the ones you're seeing:
quality is optional, and ranges from 0 (worst quality, smaller file) to 100 (best quality, biggest file). The default is the default IJG quality value (about 75).
Try using a higher value:
imagejpeg($thumb, $filename, 90);
The maximum value for $quality is 100.

GD Image resize doesn't work PHP

I've got the following piece of code:
$biggest = ($width > $height) ? $width : $height;
$newWidth = 0;
$newHeight = 0;
if($biggest > $divSize){
echo "BIGGEST<br />";
$scale = $divSize/$biggest;
$newWidth = floor($width * $scale);
$newHeight = floor($height * $scale);
} else if($biggest < $divSize){
echo "DIVSIZE<br />";
$scale = $biggest/$divSize;
$newWidth = floor($width * $scale);
$newHeight = floor($height * $scale);
}
echo "SCALE: ".$scale."<br />";
echo "BIGGEST: ".$biggest."<br />";
echo "WIDTH: ".$width."<br />";
echo "HEIGHT: ".$height."<br />";
echo "NEWWIDTH: ".$newWidth."<br />";
echo "NEWHEIGHT: ".$newHeight."<br />";
$sourceImage = imagecreatefromstring(file_get_contents($fileName));
$thumb = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($thumb, $sourceImage, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagedestroy($sourceImage);
This piece of code works fine for some images but not for all of them.
I've got a div with the dimension of 64 by 64.
For some images they scale perfectly fine but for some images the height of the outputted image is also 64px what should by for example 32px.
I don't have a clue what's causing this problem.
If you need more information, please ask.
Your function is good but sometimes your image should have a static size (this avoid to break design on some web pages).
In such a case, you can use this function. It resizes an image fit inside a defined width / height, and if the image has not the same proportions as the required thumbnail's, unused free space is set transparent.
function resizePreservingAspectRatio($img, $targetWidth, $targetHeight)
{
$srcWidth = imagesx($img);
$srcHeight = imagesy($img);
// Determine new width / height preserving aspect ratio
$srcRatio = $srcWidth / $srcHeight;
$targetRatio = $targetWidth / $targetHeight;
if (($srcWidth <= $targetWidth) && ($srcHeight <= $targetHeight))
{
$imgTargetWidth = $srcWidth;
$imgTargetHeight = $srcHeight;
}
else if ($targetRatio > $srcRatio)
{
$imgTargetWidth = (int) ($targetHeight * $srcRatio);
$imgTargetHeight = $targetHeight;
}
else
{
$imgTargetWidth = $targetWidth;
$imgTargetHeight = (int) ($targetWidth / $srcRatio);
}
// Creating new image with desired size
$targetImg = imagecreatetruecolor($targetWidth, $targetHeight);
// Add transparency if your reduced image does not fit with the new size
$targetTransparent = imagecolorallocate($targetImg, 255, 0, 255);
imagefill($targetImg, 0, 0, $targetTransparent);
imagecolortransparent($targetImg, $targetTransparent);
// Copies image, centered to the new one (if it does not fit to it)
imagecopyresampled(
$targetImg, $img, ($targetWidth - $imgTargetWidth) / 2, // centered
($targetHeight - $imgTargetHeight) / 2, // centered
0, 0, $imgTargetWidth, $imgTargetHeight, $srcWidth, $srcHeight
);
return $targetImg;
}
Usage example :
$gd = imagecreatefromjpeg("images/image5.jpg");
$resized = resizePreservingAspectRatio($gd, 100, 100);
header("Content-type: image/png");
imagepng($resized);
This image :
Becomes :
Never mind.
I figured it out myself.
I simplefied the code for scaling the thumbnail quite a bit:
$biggest = ($width > $height) ? $width : $height;
$newWidth = 0;
$newHeight = 0;
$scale = ($biggest >= $thumbSize) ? $thumbSize/$biggest : $biggest/$thumbSize;
$newWidth = floor($width * $scale);
$newHeight = floor($height * $scale);
$sourceImage = imagecreatefromstring(file_get_contents($fileName));
$thumb = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($thumb, $sourceImage, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagedestroy($sourceImage);
Maybe someone can use this.

Upload, resize, and crop center of image with PHP

I'm wanting to create a very very basic upload, resize, and crop PHP script.
The functionality to this will be identical (last i checked anyway) to the method Twitter uses to upload avatar pictures.
I want the script to take any size image, resize the shortest side to 116px, then crop off the top and bottom (or left and right side if it's landscape) as to get a square 116px by 116px.
I don't want a bloated PHP script with client side resizing or anything, just a simple PHP resize and crop. How is this done?
The GD Library is a good place to start.
http://www.php.net/manual/en/book.image.php
There a simple to use, open source library called PHP Image Magician. It uses GD but simplifies it's usage to 3 lines.
Example of basis usage:
$magicianObj = new imageLib('racecar.jpg');
$magicianObj -> resizeImage(100, 200, 'crop');
$magicianObj -> saveImage('racecar_small.png');
If you want an example to work from my upload, resize and crop class does all of this plus some other cool stuff - you can use it all if needed or just take the bits out that you like:
http://www.mjdigital.co.uk/blog/php-upload-and-resize-image-class/
I don't think it is too bloated! - you can just do something this (not tested):
if((isset($_FILES['file']['error']))&&($_FILES['file']['error']==0)){ // if a file has been posted then upload it
include('INCLUDE_CLASS_FILE_HERE.php');
$myImage = new _image;
// upload image
$myImage->uploadTo = 'uploads/'; // SET UPLOAD FOLDER HERE
$myImage->returnType = 'array'; // RETURN ARRAY OF IMAGE DETAILS
$img = $myImage->upload($_FILES['file']);
if($img) {
$myImage->newWidth = 116;
$myImage->newHeight = 116;
$i = $myImage->resize(); // resizes to 116px keeping aspect ratio
// get new image height
$imgWidth = $i['width'];
// get new image width
$imgHeight = $i['height'];
if($i) {
// work out where to crop it
$cropX = ($imgWidth>116) ? (($imgWidth-116)/2) : 0;
$cropY = ($imgHeight>116) ? (($imgHeight-116)/2) : 0;
$cropped = $myImage->crop(116,116,$cropX,$cropY);
if($cropped) { echo 'It Worked (I think!)'; print_r($cropped);
} else { echo 'Crop failed'; }
} else { echo 'Resize failed'; }
} else { echo 'Upload failed'; }
I made this simple function which is very easy to use, it allows you to resize, crop and center an image to a specific width and height, it can suppert JPGs, PNGs and GIFs. Feel free to copy and paste it to your code:
function resize_imagejpg($file, $w, $h, $finaldst) {
list($width, $height) = getimagesize($file);
$src = imagecreatefromjpeg($file);
$ir = $width/$height;
$fir = $w/$h;
if($ir >= $fir){
$newheight = $h;
$newwidth = $w * ($width / $height);
}
else {
$newheight = $w / ($width/$height);
$newwidth = $w;
}
$xcor = 0 - ($newwidth - $w) / 2;
$ycor = 0 - ($newheight - $h) / 2;
$dst = imagecreatetruecolor($w, $h);
imagecopyresampled($dst, $src, $xcor, $ycor, 0, 0, $newwidth, $newheight,
$width, $height);
imagejpeg($dst, $finaldst);
imagedestroy($dst);
return $file;
}
function resize_imagegif($file, $w, $h, $finaldst) {
list($width, $height) = getimagesize($file);
$src = imagecreatefromgif($file);
$ir = $width/$height;
$fir = $w/$h;
if($ir >= $fir){
$newheight = $h;
$newwidth = $w * ($width / $height);
}
else {
$newheight = $w / ($width/$height);
$newwidth = $w;
}
$xcor = 0 - ($newwidth - $w) / 2;
$ycor = 0 - ($newheight - $h) / 2;
$dst = imagecreatetruecolor($w, $h);
$background = imagecolorallocatealpha($dst, 0, 0, 0, 127);
imagecolortransparent($dst, $background);
imagealphablending($dst, false);
imagesavealpha($dst, true);
imagecopyresampled($dst, $src, $xcor, $ycor, 0, 0, $newwidth, $newheight,
$width, $height);
imagegif($dst, $finaldst);
imagedestroy($dst);
return $file;
}
function resize_imagepng($file, $w, $h, $finaldst) {
list($width, $height) = getimagesize($file);
$src = imagecreatefrompng($file);
$ir = $width/$height;
$fir = $w/$h;
if($ir >= $fir){
$newheight = $h;
$newwidth = $w * ($width / $height);
}
else {
$newheight = $w / ($width/$height);
$newwidth = $w;
}
$xcor = 0 - ($newwidth - $w) / 2;
$ycor = 0 - ($newheight - $h) / 2;
$dst = imagecreatetruecolor($w, $h);
$background = imagecolorallocate($dst, 0, 0, 0);
imagecolortransparent($dst, $background);
imagealphablending($dst, false);
imagesavealpha($dst, true);
imagecopyresampled($dst, $src, $xcor, $ycor, 0, 0, $newwidth,
$newheight,$width, $height);
imagepng($dst, $finaldst);
imagedestroy($dst);
return $file;
}
function ImageResize($file, $w, $h, $finaldst) {
$getsize = getimagesize($file);
$image_type = $getsize[2];
if( $image_type == IMAGETYPE_JPEG) {
resize_imagejpg($file, $w, $h, $finaldst);
} elseif( $image_type == IMAGETYPE_GIF ) {
resize_imagegif($file, $w, $h, $finaldst);
} elseif( $image_type == IMAGETYPE_PNG ) {
resize_imagepng($file, $w, $h, $finaldst);
}
}
All you have to do to use it is call it like so:
ImageResize(image, width, height, destination);
E.g.
ImageResize("uploads/face.png", 100, 150, "images/user332profilepic.png");

Resize an image and fill gaps of proportions with a color

I am uploading logos to my system, and they need to fix in a 60x60 pixel box. I have all the code to resize it proportionately, and that's not a problem.
My 454x292px image becomes 60x38. The thing is, I need the picture to be 60x60, meaning I want to pad the top and bottom with white each (I can fill the rectangle with the color).
The theory is I create a white rectangle, 60x60, then I copy the image and resize it to 60x38 and put it in my white rectangle, starting 11px from the top (which adds up to the 22px of total padding that I need.
I would post my code but it's decently long, though I can if requested.
Does anyone know how to do this or can you point me to code/tutorial that does this?
With GD:
$newWidth = 60;
$newHeight = 60;
$img = getimagesize($filename);
$width = $img[0];
$height = $img[1];
$old = imagecreatefromjpeg($filename); // change according to your source type
$new = imagecreatetruecolor($newWidth, $newHeight)
$white = imagecolorallocate($new, 255, 255, 255);
imagefill($new, 0, 0, $white);
if (($width / $height) >= ($newWidth / $newHeight)) {
// by width
$nw = $newWidth;
$nh = $height * ($newWidth / $width);
$nx = 0;
$ny = round(fabs($newHeight - $nh) / 2);
} else {
// by height
$nw = $width * ($newHeight / $height);
$nh = $newHeight;
$nx = round(fabs($newWidth - $nw) / 2);
$ny = 0;
}
imagecopyresized($new, $old, $nx, $ny, 0, 0, $nw, $nh, $width, $height);
// do something with new: like imagepng($new, ...);
imagedestroy($new);
imagedestroy($old);
http://php.net/manual/en/function.imagecopyresampled.php
That's basically the function you want to copy and resize it smoothly.
http://www.php.net/manual/en/function.imagecreatetruecolor.php
With that one you create a new black image.
http://www.php.net/manual/en/function.imagefill.php
That part explains how to fill it white.
The rest follows.

Categories