I have an upload form where you select photos. Upon upload I resize the image if necessary.
It seems any photo that I upload where the HEIGHT > WIDTH stretches the image. If I upload an image where WIDTH > HEIGHT it works fine. I've been racking my brain trying to figure this out. I'm pretty sure I know which line is the issue and I've pointed it out in a comment.
Can anyone see what is wrong with my math? Thanks!
<?php
$maxWidth = 900;
$maxHeight = 675;
$count = 0;
foreach ($_FILES['photos']['name'] as $filename)
{
$uniqueId = uniqid();
$target = "../resources/images/projects/" . strtolower($uniqueId . "_" . $filename);
$file = $_FILES['photos']['tmp_name'][$count];
list($originalWidth, $originalHeight) = getimagesize($file);
// if the image is larger than maxWidth or maxHeight
if ($originalWidth > $maxWidth || $originalHeight > $maxHeight)
{
$ratio = $originalWidth / $originalHeight;
// I think this is the problem line
(($maxWidth / $maxHeight) > $ratio) ? $maxWidth = $maxWidth * $ratio : $maxHeight = $maxWidth / $ratio;
// resample and save
$image_p = imagecreatetruecolor($maxWidth, $maxHeight);
$image = imagecreatefromjpeg($file);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $maxWidth, $maxHeight, $originalWidth, $originalHeight);
$image = imagejpeg($image_p, $target, 75);
}
else
{
// just save the image
move_uploaded_file($file,$target);
}
$count += 1;
}
?>
When scaling, you need to modify both the width and the height of the target.
Try:
if ($originalWidth > $maxWidth || $originalHeight > $maxHeight)
{
if ($originalWidth / $maxWidth > $originalHeight / $maxHeight) {
// width is the limiting factor
$width = $maxWidth;
$height = floor($width * $originalHeight / $originalWidth);
} else { // height is the limiting factor
$height = $maxHeight;
$width = floor($height * $originalWidth / $originalHeight);
}
$image_p = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($file);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $originalWidth, $originalHeight);
$image = imagejpeg($image_p, $target, 75);
}
Related
I want to create a thumbnail for an image so that it's a square with no black bars/white bars and it fills the whole square while maintaining proportion. Kind of like CSS background-size: cover.
Like this:
Even if the image is smaller than the tuhmbnail size (which is arbitrary) it should still create the thumbnail.
The thumbnail size should be 400x400 (px).
I actually wrote a function to create a thumbnail with the white bars, here it is:
function createThumbnail($orig, $sizes){
$width = $sizes[0];
$height = $sizes[1];
$targetSize = 340;
$targetWidth = ($width > $height) ? $targetSize : round(($width * $targetSize) / $height);
$targetHeight = ($width > $height) ? round(($height * $targetSize) / $width) : $targetSize;
$targetLayer = imagecreatetruecolor($targetSize, $targetSize);
$color = imagecolorallocate($targetLayer, 255, 255, 255);
imagefill($targetLayer, 0, 0, $color);
$targetX = ($width > $height) ? 0 : ($targetSize - $targetWidth) / 2;
$targetY = ($width > $height) ? ($targetSize - $targetHeight) / 2 : 0;
imagecopyresampled($targetLayer, $orig, $targetX, $targetY, 0, 0, $targetWidth, $targetHeight, $width, $height);
return $targetLayer;
}
But I can't figure out a way to crop them and have them accomodated as I want. Thanks in advance!
Well after some back and forth I actually came up with a solution, probably not the best or most efficient, I have yet to test it for all cases but it seems to work for now:
function createThumbnail($orig, $sizes){
$width = $sizes[0];
$height = $sizes[1];
$targetSize = 400;
$srcX = 0;
$srcY = 0;
$src = $width;
if ($width > $height){
$ratio = $targetSize / $height;
$srcX = (($ratio * $width) - $targetSize) / (2 * $ratio);
$src = $height;
}else if ($height > $width){
$ratio = $targetSize / $width;
$srcY = (($ratio * $height) - $targetSize) / (2 * $ratio);
}
$targetLayer = imagecreatetruecolor($targetSize, $targetSize);
$color = imagecolorallocate($targetLayer, 255, 255, 255);
imagecopyresampled($targetLayer, $orig, 0, 0, $srcX, $srcY, $targetSize, $targetSize, $src, $src);
return $targetLayer;
}
If someone has a better solution or knows how to improve this one please let me know!
$newimg = imagecreatefromjpeg($tempname);
Now I need to scale this image proportionally but don't know both dimensions in advance.
$newimg = imagescale($newimg, 160, auto, IMG_BICUBIC); //doesn't work
or
$newimg = imagescale($newimg, auto, 160, IMG_BICUBIC); // doesn't work
Is there a way to say auto or something to calculate width or height automatically.
If no, how can I calculate this?
The accepted solution here doesn't work. I doesn't keep aspect ratio.
I made a function that will do what you need. I have tested this function with scaling down images and it works as intended.
This function will size an image preserving the aspect ratio to completely fit inside the dimensions that you specify. The image will also be centered.
The function also has the ability to crop. If you use the crop parameter, it will oversize the image to make sure the smallest side of the image fills the desired dimensions. It will then crop the image to fit inside the dimensions, thus completely filling the given dimensions. The image will be centered.
Here is the function:
function scaleMyImage($filePath, $newPath, $newSize, $crop = NULL){
$img = imagecreatefromstring(file_get_contents($filePath));
$dst_x = 0;
$dst_y = 0;
$width = imagesx($img);
$height = imagesy($img);
$newWidth = $newSize;
$newHeight = $newSize;
if($width < $height){ //Portrait.
if($crop){
$newWidth = floor($width * ($newSize / $width));
$newHeight = floor($height * ($newSize / $width));
$dst_y = (floor(($newHeight - $newSize)/2)) * -1;
}else{
$newWidth = floor($width * ($newSize / $height));
$newHeight = $newSize;
$dst_x = floor(($newSize - $newWidth)/2);
}
} elseif($width > $height) { //Landscape
if($crop){
$newWidth = floor($width * ($newSize / $height));
$newHeight = floor($height * ($newSize / $height));
$dst_x = (floor(($newWidth - $newSize)/2)) * -1;
}else{
$newWidth = $newSize;
$newHeight = floor($height * ($newSize / $width));
$dst_y = floor(($newSize - $newHeight)/2);
}
}
$finalImage = imagecreatetruecolor($newSize, $newSize);
imagecopyresampled($finalImage, $img, $dst_x, $dst_y, 0, 0, $newWidth, $newHeight, $width, $height);
imagejpeg($finalImage, $newPath, 60); //Set your compression.
imagedestroy($img);
imagedestroy($finalImage);
}
How to use:
$newSize = 160;
$filePath = 'path/myImg.jpg';
$newPath = 'path/newImg.jpg';
$crop = 1; //Set to NULL if you don't want to crop.
scaleMyImage($filePath, $newPath, $newSize, 1);
This should do exactly what you want with the crop parameter set to 1.
First of all you will have to mention al-least one dimension (either height or width) then using aspect ration of original image you can identify another. Here is a sample code which i used in my case:
$width = 160; // User-defined
$height = ''; // User-defined
$path = $uploadDir . '/' . $tempname;
$mime = getimagesize($path);
// Load original image
if($mime['mime']=='image/png') {
$orig_img = imagecreatefrompng($path);
}
if($mime['mime']=='image/jpg' || $mime['mime']=='image/jpeg' || $mime['mime']=='image/pjpeg') {
$orig_img = imagecreatefromjpeg($path);
}
// Get original image height and width
$width_orig = imagesx($orig_img);
$height_orig = imagesy($orig_img);
// Aspect ratio of original image
$aspectRatio = $width_orig / $height_orig;
// If any one dimension available then calculate other with the help of aspect-ratio of original image
if ($width == '' && $height != '') {
$newheight = $height;
$newwidth = round($height * $aspectRatio);
}
if ($width != '' && $height == '') {
$newheight = round($width / $aspectRatio);
$newwidth = $width;
}
$newimg = imagescale($orig_img, $newwidth, $newheight, IMG_BICUBIC);
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.
I have this resize and crop function :
$file = imagecreatefromjpeg($imagefile["tmp_name"]);
if($imagefile["type"] == "image/jpg" || $imagefile["type"] == "image/jpeg") {
$uploaded_file = "/var/www/adimages/".$fid."-".$imagefile["name"];
} elseif($imagefile["type"] == "image/png") {
$uploaded_file = "/var/www/adimages/".$fid."-".$imagefile["name"];
}
imagejpeg($file, $uploaded_file, 100);
chmod($uploaded_file, 0644);
list($width, $height, $type, $attr) = getimagesize($uploaded_file);
$this->imageSizeW = $width;
$this->imageSizeH = $height;
$this->newSizeW = 250;
$this->newSizeH = 400;
$aspect = $width / $height;
$new_aspect = $this->newSizeW / $this->newSizeH;
if($aspect >= $new_aspect) {
$new_height = $this->newSizeH;
$new_width = $width / ($height / $this->newSizeH);
} else {
$new_width = $this->newSizeW;
$new_height = $height / ($width / $this->newSizeW);
}
$img_source = imagecreatefromjpeg($uploaded_file);
$newimage = imagecreatetruecolor($this->newSizeW, $this->newSizeH);
imagecopyresampled($newimage, $img_source, 0 - ($new_width - $this->newSizeW) / 2, 0 - ($new_height - $this->newSizeH), 0, 0, $new_width, $new_height, $width, $height);
imagejpeg($newimage, $uploaded_file, 100);
}
That works as intended, almost - when it crops it removes part of the image.
Can I somehow extend / configure this function so that it will resize / center the image and add whitespace so the image will be as original but still 250 x 400 px
Using Class upload 0.32 from voret.net instead - this does what I want!
I have this piece of code here
imagecopyresampled($new_image,$image,0,0,$x,$y,$thumb_width,$thumb_width,$width,$height);
Baiscally what I am trying to do is upload an image and resize the width and have the height adjusted based on the width.
I tried this also
imagecopyresampled($new_image,$image,0,0,$x,$y,$thumb_width,$thumb_width,$width);
without the height and got this error
Warning: Wrong parameter count for imagecopyresampled() in /home/content/44/8713044/html/admin/Categories.php on line 63
this is the current code where the $width and $height variables come from.
if($width> $height) {
$x = ceil(($width - $height) / 2 );
$width = $height;
} elseif($height> $width) {
$y = ceil(($height - $width) / 2);
$height = $width;
}
Any Help would be appreciated, Thanks in advanced,
J
Here is the full function..
function create_thumbnail($source,$destination, $thumb_width) {
$percent = 0.5;
$size = getimagesize($source);
$width = $size[0];
$height = $size[1];
$x = 0;
$y = 0;
if($width> $height) {
$x = ceil(($width - $height) / 2 );
$width = $height;
} elseif($height> $width) {
$y = ceil(($height - $width) / 2);
$height = $width;
}
$new_image = imagecreatetruecolor($thumb_width,$thumb_width)or die('Cannot Initialize new GD image stream');
$extension = get_image_extension($source);
if($extension=='jpg' || $extension=='jpeg')
$image = imagecreatefromjpeg($source);
if($extension=='gif')
$image = imagecreatefromgif($source);
if($extension=='png')
$image = imagecreatefrompng($source);
imagecopyresampled($new_image,$image,0,0,$x,$y,$thumb_width,$thumb_width,$width,$height);
if($extension=='jpg' || $extension=='jpeg')
imagejpeg($new_image,$destination);
if($extension=='gif')
imagegif($new_image,$destination);
if($extension=='png')
imagepng($new_image,$destination);
}
the $thumb_width is 600 and this returns my image 600*600
This worked perfectly when i tested it .... Except you want to work with fixed size
$filename = "a.jpg" ;
$percent = 0.5;
header('Content-Type: image/jpeg');
list($width, $height) = getimagesize($filename);
$new_width = $width * $percent;
$new_height = $height * $percent;
// Resample
$image_p = imagecreatetruecolor($new_width, $new_height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagejpeg($image_p, null, 100);
Demo