Alter my scale and crop class to work properly? [duplicate] - php
I have a defined fixed width and height to resize an image. However, I have problem a with this, because the image can have any kind of size ratio (it can be vertical or the horizontal). In this case, fixed width and height cause a problem. I want to calculate width and height in a smarter way.
For example lets say I have defined width 1024px and height 768px. And I want to resize an image which is vertical (height 1100px and width 200px). So in my case it will resize to fixed size (1024x768), so the width will be increased from 100px to 768px, and it will be very ugly. Similarly if the image has height less than 768px, it will increase the height by force to 768px.
Therefore I would like to calculate the new image size based on the original image size ratio. Lets say if the above example image should be resized to maximum height of 768px, but then what about the width? it's already less than my "maximum width", which is 200px, so should the width remain unchanged? or should it be further decreased?
Similarly, if the image has the height 200px, and the width 1100px. So the width should be decreased to 1024px, but what about the height?
The third problem is that, let's suppose if both height and width are more than the maximum height and maximum width, let's say width: 1100px and height:4000px. Now since width and height both are more than the maximum width and maximum height but the image is vertical, it will make it horizontal. So how can I check if in this case if I should resize the image according to maximum height, or according to maximum width?
I appreciate any help with this.
Here's code from my personal grab bag of image resizing code. First, data you need:
list($originalWidth, $originalHeight) = getimagesize($imageFile);
$ratio = $originalWidth / $originalHeight;
Then, this algorithm fits the image into the target size as best it can, keeping the original aspect ratio, not stretching the image larger than the original:
$targetWidth = $targetHeight = min($size, max($originalWidth, $originalHeight));
if ($ratio < 1) {
$targetWidth = $targetHeight * $ratio;
} else {
$targetHeight = $targetWidth / $ratio;
}
$srcWidth = $originalWidth;
$srcHeight = $originalHeight;
$srcX = $srcY = 0;
This crops the image to fill the target size completely, not stretching it:
$targetWidth = $targetHeight = min($originalWidth, $originalHeight, $size);
if ($ratio < 1) {
$srcX = 0;
$srcY = ($originalHeight / 2) - ($originalWidth / 2);
$srcWidth = $srcHeight = $originalWidth;
} else {
$srcY = 0;
$srcX = ($originalWidth / 2) - ($originalHeight / 2);
$srcWidth = $srcHeight = $originalHeight;
}
And this does the actual resizing:
$targetImage = imagecreatetruecolor($targetWidth, $targetHeight);
imagecopyresampled($targetImage, $originalImage, 0, 0, $srcX, $srcY, $targetWidth, $targetHeight, $srcWidth, $srcHeight);
In this case the $size is just one number for both width and height (square target size). I'm sure you can modify it to use non-square targets. It should also give you an inspiration on what other resizing algorithms you can use.
$ratio = $originalWidth / $originalHeight
if you want to change the Height:
$targetWidth = $targetHeight * $ratio
if you want to change the Width:
$targetHeight = $targetWidth / $ratio
What you want is to maintain the aspect ratio of your original image. This is the ratio between the width and the height of the image. So you calculate the factor by which you have to resize the image in the vertical and horizontal direction and then you keep the higher of the two. In pseudocode:
target_height = 768
target_width = 1024
# v_fact and h_fact are the factor by which the original vertical / horizontal
# image sizes should be multiplied to get the image to your target size.
v_fact = target_height / im_height
h_fact = target_width / im_width
# you want to resize the image by the same factor in both vertical
# and horizontal direction, so you need to pick the correct factor from
# v_fact / h_fact so that the largest (relative to target) of the new height/width
# equals the target height/width and the smallest is lower than the target.
# this is the lowest of the two factors
im_fact = min(v_fact, h_fact)
new_height = im_height * im_fact
new_width = im_width * im_fact
image.resize(new_width, new_height)
this is working.
function calculateDimensions($width,$height,$maxwidth,$maxheight)
{
if($width != $height)
{
if($width > $height)
{
$t_width = $maxwidth;
$t_height = (($t_width * $height)/$width);
//fix height
if($t_height > $maxheight)
{
$t_height = $maxheight;
$t_width = (($width * $t_height)/$height);
}
}
else
{
$t_height = $maxheight;
$t_width = (($width * $t_height)/$height);
//fix width
if($t_width > $maxwidth)
{
$t_width = $maxwidth;
$t_height = (($t_width * $height)/$width);
}
}
}
else
$t_width = $t_height = min($maxheight,$maxwidth);
return array('height'=>(int)$t_height,'width'=>(int)$t_width);
}
How about this:
double ratio = imageWidth/imageHeight;
int newHeight = Math.min(displayHeight, displayWidth / ratio);
int newWidth = Math.min(displayWidth, displayHeight * ratio);
Check the php code below :
$new_width = 1024;
$new_height = 768;
$this_image = "images/my_image";
list($width, $height, $type, $attr) = getimagesize("$this_image");
if ($width > $height) {
$image_height = floor(($height/$width)*$new_width);
$image_width = $new_width;
} else {
$image_width = floor(($width/$height)*$new_height);
$image_height = $new_height;
}
echo "<img src='$this_image' height='$image_height' width='$image_width'>";
What you need is to 'maintain' the width/height ratio.
Originally you have an image of size (wxh) 500x1000, this width/height ratio is 0.5 . Assuming you are changing 1000 to 768 in height, your result width would be 0.5 * 768 = 384.
Another example, 1800 x 1200 and your new height is 200, then your new width is 300 because 300/200 is 1.5 and 1800/1200 is also 1.5.
Good luck.
You should resize it depending on what property is farer away from the maximum value. Then, calculate the ratio.
if(($w - $w_max) > ($h - $h_max)) {
$w_new = $w_max;
$h_new = (int) ($h * ($w_max / $w));
}
else {
$h_new = $h_max;
$w_new = (int) ($w * ($h_max / $h));
}
I reached this question and didn't find a suitable answer, so i set out on my own to answer the question.
i started with some basic logic, and after consulting a friend of mine who is a bit better at math, this is what we came up with.
function calculate_dimensions($width,$height,$max){
if($width != $height){
if($width > $height){
$t_height = $max;
$t_width = min(($width * $t_height)/$height);
}
if($height > $width){
$t_width = $max;
$t_height = min(($t_width * $height)/$width)
}
}else{
if($width > $max){
$t_width = $t_height = $max;
}
}
$res = ['height'=>$t_height,'width'=>$t_width]
return $res;
}
This snippet of code is reusable, so knock yourself out. just pass it the maximum smallest dimension allowed, and it will calculate the largest side's dimension, so you will get back a correctly scaled dimension, in which you can then center crop, resulting in a correctly shrinked and cropped image square image. this is useful for things like profile pictures and thumbnails.
credit to my friend, Justin Gillett for his brilliant suggestion of cross multiplication.
This example will shrink an image to fit a defined pixel perfect aspect ratio ( 16:9 ) creating an image no larger than a specified limit ( 1200 x 675 ).
Set your image ratio and any upper limit:
const RATIO_W = 16;
const RATIO_H = 9;
const RATIO_MULIPLIER_UPPER_LIMIT = 75;
Calculate the new image width and height
list($imageWidth, $imageHeight) = getimagesize($path_to_image);
if( ($imageWidth / $imageHeight) === (self::RATIO_W / self::RATIO_H) ){
return;
// Find closest ratio multiple to image size
if($imageWidth > $imageHeight){
// landscape
$ratioMultiple = round($imageHeight / self::RATIO_H, 0, PHP_ROUND_HALF_DOWN);
}else{
// portrait
$ratioMultiple = round($imageWidth / self::RATIO_W, 0, PHP_ROUND_HALF_DOWN);
}
$newWidth = $ratioMultiple * self::RATIO_W;
$newHeight = $ratioMultiple * self::RATIO_H;
if($newWidth > self::RATIO_W * self::RATIO_MULIPLIER_UPPER_LIMIT|| $newHeight > self::RATIO_H * self::RATIO_MULIPLIER_UPPER_LIMIT){
// File is larger than upper limit
$ratioMultiple = self::RATIO_MULIPLIER_UPPER_LIMIT;
}
$this->tweakMultiplier($ratioMultiple, $imageWidth, $imageHeight);
$newWidth = $ratioMultiple * self::RATIO_W;
$newHeight = $ratioMultiple * self::RATIO_H;
Resize image
$originalImage = imagecreatefromjpeg( $tempImagePath );
$newImage = imagecreatetruecolor($newWidth, $newHeight);
imagefilledrectangle($newImage, 0, 0, $newWidth, $newHeight, imagecolorallocate($newImage, 255, 255, 255));
imagecopyresampled($newImage, $originalImage, 0, 0, 0, 0, $newWidth, $newHeight, $imageWidth, $imageHeight);
imagejpeg($newImage, $tempImagePath, 100);
Loop through factors until both dimensions are less than the original image size
protected function tweakMultiplier( &$ratioMultiple, $fitInsideWidth, $fitInsideHeight ){
$newWidth = $ratioMultiple * self::RATIO_W;
$newHeight = $ratioMultiple * self::RATIO_H;
if($newWidth > $fitInsideWidth || $newHeight > $fitInsideHeight){
echo " Tweak ";
$ratioMultiple--;
$this->tweakMultiplier($ratioMultiple, $fitInsideWidth, $fitInsideHeight);
}else{
return;
}
}
If max height or width given or not, using #(jilles de wit) logic
considerations : these should already be defined!
$mh = given height limit; //optional
$mw = given width limit; //optional
$height = $nh =[your original height];
$width = $nw =[your original width];
The Code
if($mh || $mw){
if(is_numeric($mh)){$h_fact = $mh / $nh;}
if(is_numeric($mw)){$v_fact = $mw / $nw;}
if(is_numeric($v_fact) && is_numeric($h_fact) ){$im_fact = min($v_fact, $h_fact);}else{$im_fact=is_numeric($v_fact)?$v_fact:$h_fact;}
$nw = $nw * $im_fact;
$nh = $nh * $im_fact;
}
resampling
$dst_img = imagecreatetruecolor($nw,$nh);
imagecopyresampled ($dst_img, $image, 0, 0, 0, 0, $nw, $nh, $width , $height);
get the nearest Ratio
$r=getRatio(820,460);//41:23
$r=getRatio(160,40);//4:1
$r=getRatio(1743,367);//1743:367
function getRatio($num1, $num2){
if(abs($num1-$num2)<10 && $num1>100){
$num1=$num2;
}
for($i = $num2; $i > 1; $i--) {
if((($num1 % $i) == 0 && ($num2 % $i) == 0) ) {
$num1 = $num1 / $i;
$num2 = $num2 / $i;
}
}
return round($num1,1).':'.round($num2,1);
}
class Image_Aspect_Ratio_Resize {
var $image_to_resize;
var $new_width;
var $new_height;
var $ratio;
var $new_image_name;
var $save_folder;
function resize() {
if (!file_exists($this->image_to_resize)) {
exit("File " . $this->image_to_resize . " does not exist.");
}
$info = GetImageSize($this->image_to_resize);
if (empty($info)) {
exit("The file " . $this->image_to_resize . " doesn't seem to be an image.");
}
$width = $info[0];
$height = $info[1];
$mime = $info['mime'];
/* Keep Aspect Ratio? */
if ($this->ratio) {
$thumb = ($this->new_width < $width && $this->new_height < $height) ? true : false; // Thumbnail
$bigger_image = ($this->new_width > $width || $this->new_height > $height) ? true : false; // Bigger Image
if ($thumb) {
if ($this->new_width >= $this->new_height) {
$x = ($width / $this->new_width);
$this->new_height = ($height / $x);
} else if ($this->new_height >= $this->new_width) {
$x = ($height / $this->new_height);
$this->new_width = ($width / $x);
}
} else if ($bigger_image) {
if ($this->new_width >= $width) {
$x = ($this->new_width / $width);
$this->new_height = ($height * $x);
} else if ($this->new_height >= $height) {
$x = ($this->new_height / $height);
$this->new_width = ($width * $x);
}
}
}
$type = substr(strrchr($mime, '/'), 1);
switch ($type) {
case 'jpeg':
$image_create_func = 'ImageCreateFromJPEG';
$image_save_func = 'ImageJPEG';
$new_image_ext = 'jpg';
break;
case 'png':
$image_create_func = 'ImageCreateFromPNG';
$image_save_func = 'ImagePNG';
$new_image_ext = 'png';
break;
case 'bmp':
$image_create_func = 'ImageCreateFromBMP';
$image_save_func = 'ImageBMP';
$new_image_ext = 'bmp';
break;
case 'gif':
$image_create_func = 'ImageCreateFromGIF';
$image_save_func = 'ImageGIF';
$new_image_ext = 'gif';
break;
case 'vnd.wap.wbmp':
$image_create_func = 'ImageCreateFromWBMP';
$image_save_func = 'ImageWBMP';
$new_image_ext = 'bmp';
break;
case 'xbm':
$image_create_func = 'ImageCreateFromXBM';
$image_save_func = 'ImageXBM';
$new_image_ext = 'xbm';
break;
default:
$image_create_func = 'ImageCreateFromJPEG';
$image_save_func = 'ImageJPEG';
$new_image_ext = 'jpg';
}
// New Image
$image_c = ImageCreateTrueColor($this->new_width, $this->new_height);
$new_image = $image_create_func($this->image_to_resize);
ImageCopyResampled($image_c, $new_image, 0, 0, 0, 0, $this->new_width, $this->new_height, $width, $height);
if ($this->save_folder) {
if ($this->new_image_name) {
$new_name = $this->new_image_name . '.' . $new_image_ext;
} else {
$new_name = $this->new_thumb_name(basename($this->image_to_resize)) . '_resized.' . $new_image_ext;
}
$save_path = $this->save_folder . $new_name;
} else {
/* Show the image without saving it to a folder */
header("Content-Type: " . $mime);
$image_save_func($image_c);
$save_path = '';
}
$process = $image_save_func($image_c, $save_path);
return array('result' => $process, 'new_file_path' => $save_path);
}}
/* Function Call */
$resize_image = new Image_Aspect_Ratio_Resize;
$new_width = (int) $_POST['new_width'];
$new_height = (int) $_POST['new_height'];
$resize_image->new_width = $new_width;
$resize_image->new_height = $new_height;
$resize_image->image_to_resize = $image; // Full Path to the file
$resize_image->ratio = true; // Keep aspect ratio
// Name of the new image (optional) - If it's not set a new will be added automatically
$resize_image->new_image_name = 'water_lilies_thumbnail';
/* Path where the new image should be saved. If it's not set the script will output the image without saving it */
$resize_image->save_folder = 'thumbs/';
$process = $resize_image->resize(); // Output image
Related
PHP Resize image and crop them to prevent stretching [duplicate]
I have a defined fixed width and height to resize an image. However, I have problem a with this, because the image can have any kind of size ratio (it can be vertical or the horizontal). In this case, fixed width and height cause a problem. I want to calculate width and height in a smarter way. For example lets say I have defined width 1024px and height 768px. And I want to resize an image which is vertical (height 1100px and width 200px). So in my case it will resize to fixed size (1024x768), so the width will be increased from 100px to 768px, and it will be very ugly. Similarly if the image has height less than 768px, it will increase the height by force to 768px. Therefore I would like to calculate the new image size based on the original image size ratio. Lets say if the above example image should be resized to maximum height of 768px, but then what about the width? it's already less than my "maximum width", which is 200px, so should the width remain unchanged? or should it be further decreased? Similarly, if the image has the height 200px, and the width 1100px. So the width should be decreased to 1024px, but what about the height? The third problem is that, let's suppose if both height and width are more than the maximum height and maximum width, let's say width: 1100px and height:4000px. Now since width and height both are more than the maximum width and maximum height but the image is vertical, it will make it horizontal. So how can I check if in this case if I should resize the image according to maximum height, or according to maximum width? I appreciate any help with this.
Here's code from my personal grab bag of image resizing code. First, data you need: list($originalWidth, $originalHeight) = getimagesize($imageFile); $ratio = $originalWidth / $originalHeight; Then, this algorithm fits the image into the target size as best it can, keeping the original aspect ratio, not stretching the image larger than the original: $targetWidth = $targetHeight = min($size, max($originalWidth, $originalHeight)); if ($ratio < 1) { $targetWidth = $targetHeight * $ratio; } else { $targetHeight = $targetWidth / $ratio; } $srcWidth = $originalWidth; $srcHeight = $originalHeight; $srcX = $srcY = 0; This crops the image to fill the target size completely, not stretching it: $targetWidth = $targetHeight = min($originalWidth, $originalHeight, $size); if ($ratio < 1) { $srcX = 0; $srcY = ($originalHeight / 2) - ($originalWidth / 2); $srcWidth = $srcHeight = $originalWidth; } else { $srcY = 0; $srcX = ($originalWidth / 2) - ($originalHeight / 2); $srcWidth = $srcHeight = $originalHeight; } And this does the actual resizing: $targetImage = imagecreatetruecolor($targetWidth, $targetHeight); imagecopyresampled($targetImage, $originalImage, 0, 0, $srcX, $srcY, $targetWidth, $targetHeight, $srcWidth, $srcHeight); In this case the $size is just one number for both width and height (square target size). I'm sure you can modify it to use non-square targets. It should also give you an inspiration on what other resizing algorithms you can use.
$ratio = $originalWidth / $originalHeight if you want to change the Height: $targetWidth = $targetHeight * $ratio if you want to change the Width: $targetHeight = $targetWidth / $ratio
What you want is to maintain the aspect ratio of your original image. This is the ratio between the width and the height of the image. So you calculate the factor by which you have to resize the image in the vertical and horizontal direction and then you keep the higher of the two. In pseudocode: target_height = 768 target_width = 1024 # v_fact and h_fact are the factor by which the original vertical / horizontal # image sizes should be multiplied to get the image to your target size. v_fact = target_height / im_height h_fact = target_width / im_width # you want to resize the image by the same factor in both vertical # and horizontal direction, so you need to pick the correct factor from # v_fact / h_fact so that the largest (relative to target) of the new height/width # equals the target height/width and the smallest is lower than the target. # this is the lowest of the two factors im_fact = min(v_fact, h_fact) new_height = im_height * im_fact new_width = im_width * im_fact image.resize(new_width, new_height)
this is working. function calculateDimensions($width,$height,$maxwidth,$maxheight) { if($width != $height) { if($width > $height) { $t_width = $maxwidth; $t_height = (($t_width * $height)/$width); //fix height if($t_height > $maxheight) { $t_height = $maxheight; $t_width = (($width * $t_height)/$height); } } else { $t_height = $maxheight; $t_width = (($width * $t_height)/$height); //fix width if($t_width > $maxwidth) { $t_width = $maxwidth; $t_height = (($t_width * $height)/$width); } } } else $t_width = $t_height = min($maxheight,$maxwidth); return array('height'=>(int)$t_height,'width'=>(int)$t_width); }
How about this: double ratio = imageWidth/imageHeight; int newHeight = Math.min(displayHeight, displayWidth / ratio); int newWidth = Math.min(displayWidth, displayHeight * ratio);
Check the php code below : $new_width = 1024; $new_height = 768; $this_image = "images/my_image"; list($width, $height, $type, $attr) = getimagesize("$this_image"); if ($width > $height) { $image_height = floor(($height/$width)*$new_width); $image_width = $new_width; } else { $image_width = floor(($width/$height)*$new_height); $image_height = $new_height; } echo "<img src='$this_image' height='$image_height' width='$image_width'>";
What you need is to 'maintain' the width/height ratio. Originally you have an image of size (wxh) 500x1000, this width/height ratio is 0.5 . Assuming you are changing 1000 to 768 in height, your result width would be 0.5 * 768 = 384. Another example, 1800 x 1200 and your new height is 200, then your new width is 300 because 300/200 is 1.5 and 1800/1200 is also 1.5. Good luck.
You should resize it depending on what property is farer away from the maximum value. Then, calculate the ratio. if(($w - $w_max) > ($h - $h_max)) { $w_new = $w_max; $h_new = (int) ($h * ($w_max / $w)); } else { $h_new = $h_max; $w_new = (int) ($w * ($h_max / $h)); }
I reached this question and didn't find a suitable answer, so i set out on my own to answer the question. i started with some basic logic, and after consulting a friend of mine who is a bit better at math, this is what we came up with. function calculate_dimensions($width,$height,$max){ if($width != $height){ if($width > $height){ $t_height = $max; $t_width = min(($width * $t_height)/$height); } if($height > $width){ $t_width = $max; $t_height = min(($t_width * $height)/$width) } }else{ if($width > $max){ $t_width = $t_height = $max; } } $res = ['height'=>$t_height,'width'=>$t_width] return $res; } This snippet of code is reusable, so knock yourself out. just pass it the maximum smallest dimension allowed, and it will calculate the largest side's dimension, so you will get back a correctly scaled dimension, in which you can then center crop, resulting in a correctly shrinked and cropped image square image. this is useful for things like profile pictures and thumbnails. credit to my friend, Justin Gillett for his brilliant suggestion of cross multiplication.
This example will shrink an image to fit a defined pixel perfect aspect ratio ( 16:9 ) creating an image no larger than a specified limit ( 1200 x 675 ). Set your image ratio and any upper limit: const RATIO_W = 16; const RATIO_H = 9; const RATIO_MULIPLIER_UPPER_LIMIT = 75; Calculate the new image width and height list($imageWidth, $imageHeight) = getimagesize($path_to_image); if( ($imageWidth / $imageHeight) === (self::RATIO_W / self::RATIO_H) ){ return; // Find closest ratio multiple to image size if($imageWidth > $imageHeight){ // landscape $ratioMultiple = round($imageHeight / self::RATIO_H, 0, PHP_ROUND_HALF_DOWN); }else{ // portrait $ratioMultiple = round($imageWidth / self::RATIO_W, 0, PHP_ROUND_HALF_DOWN); } $newWidth = $ratioMultiple * self::RATIO_W; $newHeight = $ratioMultiple * self::RATIO_H; if($newWidth > self::RATIO_W * self::RATIO_MULIPLIER_UPPER_LIMIT|| $newHeight > self::RATIO_H * self::RATIO_MULIPLIER_UPPER_LIMIT){ // File is larger than upper limit $ratioMultiple = self::RATIO_MULIPLIER_UPPER_LIMIT; } $this->tweakMultiplier($ratioMultiple, $imageWidth, $imageHeight); $newWidth = $ratioMultiple * self::RATIO_W; $newHeight = $ratioMultiple * self::RATIO_H; Resize image $originalImage = imagecreatefromjpeg( $tempImagePath ); $newImage = imagecreatetruecolor($newWidth, $newHeight); imagefilledrectangle($newImage, 0, 0, $newWidth, $newHeight, imagecolorallocate($newImage, 255, 255, 255)); imagecopyresampled($newImage, $originalImage, 0, 0, 0, 0, $newWidth, $newHeight, $imageWidth, $imageHeight); imagejpeg($newImage, $tempImagePath, 100); Loop through factors until both dimensions are less than the original image size protected function tweakMultiplier( &$ratioMultiple, $fitInsideWidth, $fitInsideHeight ){ $newWidth = $ratioMultiple * self::RATIO_W; $newHeight = $ratioMultiple * self::RATIO_H; if($newWidth > $fitInsideWidth || $newHeight > $fitInsideHeight){ echo " Tweak "; $ratioMultiple--; $this->tweakMultiplier($ratioMultiple, $fitInsideWidth, $fitInsideHeight); }else{ return; } }
If max height or width given or not, using #(jilles de wit) logic considerations : these should already be defined! $mh = given height limit; //optional $mw = given width limit; //optional $height = $nh =[your original height]; $width = $nw =[your original width]; The Code if($mh || $mw){ if(is_numeric($mh)){$h_fact = $mh / $nh;} if(is_numeric($mw)){$v_fact = $mw / $nw;} if(is_numeric($v_fact) && is_numeric($h_fact) ){$im_fact = min($v_fact, $h_fact);}else{$im_fact=is_numeric($v_fact)?$v_fact:$h_fact;} $nw = $nw * $im_fact; $nh = $nh * $im_fact; } resampling $dst_img = imagecreatetruecolor($nw,$nh); imagecopyresampled ($dst_img, $image, 0, 0, 0, 0, $nw, $nh, $width , $height);
get the nearest Ratio $r=getRatio(820,460);//41:23 $r=getRatio(160,40);//4:1 $r=getRatio(1743,367);//1743:367 function getRatio($num1, $num2){ if(abs($num1-$num2)<10 && $num1>100){ $num1=$num2; } for($i = $num2; $i > 1; $i--) { if((($num1 % $i) == 0 && ($num2 % $i) == 0) ) { $num1 = $num1 / $i; $num2 = $num2 / $i; } } return round($num1,1).':'.round($num2,1); }
class Image_Aspect_Ratio_Resize { var $image_to_resize; var $new_width; var $new_height; var $ratio; var $new_image_name; var $save_folder; function resize() { if (!file_exists($this->image_to_resize)) { exit("File " . $this->image_to_resize . " does not exist."); } $info = GetImageSize($this->image_to_resize); if (empty($info)) { exit("The file " . $this->image_to_resize . " doesn't seem to be an image."); } $width = $info[0]; $height = $info[1]; $mime = $info['mime']; /* Keep Aspect Ratio? */ if ($this->ratio) { $thumb = ($this->new_width < $width && $this->new_height < $height) ? true : false; // Thumbnail $bigger_image = ($this->new_width > $width || $this->new_height > $height) ? true : false; // Bigger Image if ($thumb) { if ($this->new_width >= $this->new_height) { $x = ($width / $this->new_width); $this->new_height = ($height / $x); } else if ($this->new_height >= $this->new_width) { $x = ($height / $this->new_height); $this->new_width = ($width / $x); } } else if ($bigger_image) { if ($this->new_width >= $width) { $x = ($this->new_width / $width); $this->new_height = ($height * $x); } else if ($this->new_height >= $height) { $x = ($this->new_height / $height); $this->new_width = ($width * $x); } } } $type = substr(strrchr($mime, '/'), 1); switch ($type) { case 'jpeg': $image_create_func = 'ImageCreateFromJPEG'; $image_save_func = 'ImageJPEG'; $new_image_ext = 'jpg'; break; case 'png': $image_create_func = 'ImageCreateFromPNG'; $image_save_func = 'ImagePNG'; $new_image_ext = 'png'; break; case 'bmp': $image_create_func = 'ImageCreateFromBMP'; $image_save_func = 'ImageBMP'; $new_image_ext = 'bmp'; break; case 'gif': $image_create_func = 'ImageCreateFromGIF'; $image_save_func = 'ImageGIF'; $new_image_ext = 'gif'; break; case 'vnd.wap.wbmp': $image_create_func = 'ImageCreateFromWBMP'; $image_save_func = 'ImageWBMP'; $new_image_ext = 'bmp'; break; case 'xbm': $image_create_func = 'ImageCreateFromXBM'; $image_save_func = 'ImageXBM'; $new_image_ext = 'xbm'; break; default: $image_create_func = 'ImageCreateFromJPEG'; $image_save_func = 'ImageJPEG'; $new_image_ext = 'jpg'; } // New Image $image_c = ImageCreateTrueColor($this->new_width, $this->new_height); $new_image = $image_create_func($this->image_to_resize); ImageCopyResampled($image_c, $new_image, 0, 0, 0, 0, $this->new_width, $this->new_height, $width, $height); if ($this->save_folder) { if ($this->new_image_name) { $new_name = $this->new_image_name . '.' . $new_image_ext; } else { $new_name = $this->new_thumb_name(basename($this->image_to_resize)) . '_resized.' . $new_image_ext; } $save_path = $this->save_folder . $new_name; } else { /* Show the image without saving it to a folder */ header("Content-Type: " . $mime); $image_save_func($image_c); $save_path = ''; } $process = $image_save_func($image_c, $save_path); return array('result' => $process, 'new_file_path' => $save_path); }} /* Function Call */ $resize_image = new Image_Aspect_Ratio_Resize; $new_width = (int) $_POST['new_width']; $new_height = (int) $_POST['new_height']; $resize_image->new_width = $new_width; $resize_image->new_height = $new_height; $resize_image->image_to_resize = $image; // Full Path to the file $resize_image->ratio = true; // Keep aspect ratio // Name of the new image (optional) - If it's not set a new will be added automatically $resize_image->new_image_name = 'water_lilies_thumbnail'; /* Path where the new image should be saved. If it's not set the script will output the image without saving it */ $resize_image->save_folder = 'thumbs/'; $process = $resize_image->resize(); // Output image
Imagemagick - Contain Image in Crop
I don't use Imagemagick very often, which is why I don't know how to solve this problem. I also don't know how to phrase the question other than: How do I get the image to be cropped like the CSS property: background-size: contain; I haven't been able to find an answer, likely due to my phrasing. I need the image to be 200px, and "resized/cropped" so that it is not stretched, but contained by the width or height (dependent on the orientation of the image width > height = contain by width) What I have so far: $im = new Imagick($path); /* Resizing Operations */ $gm = $im->getImageGeometry(); $w = $gm['width']; $h = $gm['height']; if($h < $w) { $nh = 200; $nw = (200 / $h) * $w; } else { $nw = 200; $nh = (200 / $w) * $h; } $im->resizeImage($nw, $nh, Imagick::FILTER_LANCZOS, true); $im->cropThumbnailImage(200,200); /* End Resizing Operations */ Which produces an image with the center chopped out. Here's a visual example We have this logo: And then we want it to be constrained to 200px wide and 200px high, contained: Essentially like setting the canvas height, while not adjusting the image height.
Came up with this algorithm based on the extent method of ImageMagick, which achieves the same result as CSS's background-size: contain; You can set the 200 value in the resizeImage function to get your end product. Works beautifully! $im = new Imagick($path); /* Resizing Operations */ $gm = $im->getImageGeometry(); $w = $gm['width']; $h = $gm['height']; if($h < $w) { $sr = $w; $horz = TRUE; } else if($h > $w) { $sr = $h; $horz = FALSE; } else { $square = TRUE; } if(!$square && $horz) { $srs = $sr / 2; $extent_amt = $srs - ($h / 2); $im->extentImage($sr, $sr, 0, 0 - $extent_amt); } else if(!$square && !$horz) { $srs = $sr / 2; $extent_amt = $srs - ($w / 2); $im->extentImage($sr, $sr, 0 - $extent_amt, 0); } $im->resizeImage(200, 200, Imagick::FILTER_LANCZOS, true); /* End Resizing Operations */ $im->writeImage($path); /* Clean up time */ $im->clear(); $im->destroy();
it seems like this would work for you, in that it operates in the same way that the background-size:contain; works in CSS $path = __DIR__ . '/img.jpg'; $im = new Imagick($path); $gm = $im->getImageGeometry(); $w = $gm['width']; $h = $gm['height']; if ($w >= $h) { $target_height = 0; $target_width = 200; } elseif ($h > $w) { $target_height = 200; $target_width = 0; } $im->resizeImage($target_width, $target_height, Imagick::FILTER_LANCZOS, true); $im->writeImage($path); $im->clear(); $im->destroy();
Find new proportional dimensions of an image in PHP
I have a site and I want to upload an image and resize it because I have to put it into a div with a certain dimension. For example my max-width is 200px and max-height is 100px I want to upload the image and check width and height, if they are bigger than the max-width or max-height I want to find the size of the image to stay inside that div. How can I resize proportionally the size of the image? I only want to find new width and new height in base of my div 200px*100px This is my script: if(move_uploaded_file($tmp, $path.$actual_image_name)) { list($width, $height, $type, $attr) = getimagesize($tmp); if($width>200){ //too large I want to resize } if($height>100){ //too height I want to resize } echo(base_url().$path.$actual_image_name); }
You can use the function below to stay inside a bounding box. EG 200x200. Just send in the filelocation and the max width and height. It will return an array where $ar[0] is the new width and $ar[1] is the new height. Its written out in full so you can understand the math. <?php function returnSize($maxW,$maxH,$img) { $maxW = ($maxW>0 && is_numeric($maxW)) ? $maxW : 0; $maxH = ($maxH>0 && is_numeric($maxH)) ? $maxH : 0; // File and new size if (!file_exists($img)) { $size[0]=0; $size[1]=0; return $size; } $size = getimagesize($img); if ($maxW>0 && $maxH>0) { if ($size[0]>$maxW) { $scaleW = $maxW / $size[0]; } else { $scaleW = 1; } if ($size[1]>$maxH) { $scaleH = $maxH / $size[1]; } else { $scaleH = 1; } if ($scaleW > $scaleH) { $fileW = $size[0] * $scaleH; $fileH = $size[1] * $scaleH; } else { $fileW = $size[0] * $scaleW; $fileH = $size[1] * $scaleW; } } else if ($maxW>0) { if ($size[0]>$maxW) { $scaleW = $maxW / $size[0]; } else { $scaleW = 1; } $fileW = $size[0] * $scaleW; $fileH = $size[1] * $scaleW; } else if ($maxH>0) { if ($size[1]>$maxH) { $scaleH = $maxH / $size[1]; } else { $scaleH = 1; } $fileW = $size[0] * $scaleH; $fileH = $size[1] * $scaleH; } else { $fileW = $size[0]; $fileH = $size[1]; } $size[0] = $fileW; $size[1] = $fileH; return $size; } ?>
This is the very basics of working out the ratio (keep persistent scale): if($width>200){ $percentage = (200/$width)*100; //Work out percentage $newWidth = 200; // Set new width to max width $newHeight = round($height*$percentage); //Multiply original height by percentage } else if($height>100){ $percentage = (100/$height)*100; //Work out percentage $newHeight = 100; // Set new height to max height $newWidth = round($width*$percentage); //Multiply original width by percentage } I used round() to ensure that you receive integer-only new dimensions
Here are some of the options... First one: http://www.white-hat-web-design.co.uk/blog/resizing-images-with-php/ and the second one: http://www.sitepoint.com/image-resizing-php/ - all the math work is already done
Image resizing going wrong
I am trying to resize an uploaded image using the WideImage library. I need to convert it to the highest resolution possible. The ouput size should be Width:460px Height:345px Here is my source for the resize: list($w, $h) = getimagesize($_FILES['image']['tmp_name']); $wpercent = ($w/460)*100; $hpercent = ($h/345)*100; if ($wpercent >= 100 && $hpercent >= 100) { // Both is over 100% of the allowed size, then resize so the smaller side match. if ($wpercent > $hpercent) { // height is smallest $remove_percent = $hpercent - 100; }else{ // width is smallest $remove_percent = $wpercent - 100; } $new_h_percent = $hpercent - $remove_percent; $new_w_percent = $wpercent - $remove_percent; $new_w = ($w/460)*$new_w_percent; $new_h = ($h/345)*$new_h_percent; $img = $img->resize($new_w, $new_h, 'inside'); $img = $img->crop("center", "middle", 460, 345); }else { // En af dem er for små if ($wpercent > $hpercent) { // height is smallest $add_percent = 100 - $hpercent; }else{ // width is smallest $add_percent = 100 - $wpercent; } $new_h_percent = $hpercent + $add_percent; $new_w_percent = $wpercent + $add_percent; $new_w = ($w/460)*$new_w_percent; $new_h = ($h/345)*$new_h_percent; $img = $img->resize($new_w, $new_h, 'inside'); $img = $img->crop("center", "middle", 460, 345); } $img->saveToFile('uploads/tmp/'.$new_name); It does resize, just to a smaller size then I want. Any ideas? Also it should crop if needed.
list($w, $h) = getimagesize($_FILES['image']['tmp_name']); if ($w != 460 || $h != 345) { $img = $img->resize(460, 345, 'inside'); $img = $img->crop("center", "middle", 460, 345); } $img->saveToFile('uploads/tmp/'.$new_name); What are you trying to accomplish with all these new_h_percent and new_w_percent?
Having issues with GD thumbnail generator
I'm using PHP to generate thumbnails. The problem is that I have a set width and height the thumbnails need to be and often times the images are stretched. What I'd like is the image to remain at the same proportions and just have black filler (or any color) either on the left & right for tall images or top & bottom for wide images. Here is the code I'm currently using: (dumbed down a bit for readability) $temp_image_file = imagecreatefromjpeg("http://www.example.com/image.jpg"); list($width,$height) = getimagesize("http://www.example.com/image.jpg"); $image_file = imagecreatetruecolor(166,103); imagecopyresampled($image_file,$temp_image_file,0,0,0,0,166,103,$width,$height); imagejpeg($image_file,"thumbnails/thumbnail.jpg",50); imagedestroy($temp_image_file); imagedestroy($image_file);
You'll need to calculate the new width & height to keep the image proportionat. Check out example 2 on this page: http://us3.php.net/imagecopyresampled
Okay got it working, here's what I ended up doing: $filename = "http://www.example.com/image.jpg"; list($width,$height) = getimagesize($filename); $width_ratio = 166 / $width; if ($height * $width_ratio <= 103) { $adjusted_width = 166; $adjusted_height = $height * $width_ratio; } else { $height_ratio = 103 / $height; $adjusted_width = $width * $height_ratio; $adjusted_height = 103; } $image_p = imagecreatetruecolor(166,103); $image = imagecreatefromjpeg($filename); imagecopyresampled($image_p,$image,ceil((166 - $adjusted_width) / 2),ceil((103 - $adjusted_height) / 2),0,0,ceil($adjusted_width),ceil($adjusted_height),$width,$height); imagejpeg($image_p,"thumbnails/thumbnail.jpg",50);
Here's a function I wrote that takes a GD image object, max width, max height, and rescales within those parameters: function resized($im, $mx, $my) { $x = $nx = imagesx($im); $y = $ny = imagesy($im); $ar = $x / $y; while ($nx > $mx || $ny > $my) { if ($nx > $mx) { $nx = $mx; $ny = $nx / $ar; } if ($ny > $my) { $ny = $my; $nx = $ny * $ar; } } if ($nx != $x) { $im2 = imagecreatetruecolor($nx, $ny); imagecopyresampled($im2, $im, 0, 0, 0, 0, $nx, $ny, $x, $y); return $im2; } else { return $im; } } If the resulting image doesn't need rescaling then it just returns the original image.
Have a look at this upload class. It does what you want and a lot more besides.
This rescales the image to the larger size of the width and height and then crops it to the correct size. // Crete an image forced to width and height function createFixedImage($img, $id=0, $preFix=false, $mw='100', $mh='100', $quality=90){ // Fix path $filename = '../'.$img; // Check for file if(file_exists($filename)) { // Set a maximum height and width $width = $mw; $height = $mh; // Get new dimensions list($width_orig, $height_orig) = getimagesize($filename); $ratio_orig = $width_orig/$height_orig; if ($width/$height < $ratio_orig) { $width = $height*$ratio_orig; }else{ $height = $width/$ratio_orig; } // Resample $image_p = imagecreatetruecolor($mw, $mh); $image = imagecreatefromjpeg($filename); imagecopyresampled($image_p, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig); // Output imagejpeg($image_p, "../images/stories/catalog/{$preFix}{$id}.jpg", $quality); } }