Get dimensions to transform image to a maximum value - php

I need to get some dimensions to display images.
I want to display the image in a maximum pixel-size for the longest side of the image.
So, if the maximum length should be 1000px, I have to check if the height or the width is bigger. After that I resize the dimensions in the correct proportions.
If the image dimensions are smaller then 1000px, nothing should happen.
This is my solution, which already works. But I don't feel well with it. Is there a smarter solution?
dimensions(1000);
function dimensions($limit) {
if ($width >= $height) {
if ($width < $limit) $limit = $width;
$factor = $width / $limit;
}
else {
if ($height < $limit) $limit = $height;
$factor = $height / $limit;
}
$new_width = $width / $factor;
$new_height = $height / $factor;
}

Well my example code:
function dimensions($limit) {
$tmp = max($width, $height);
$limit = min($limit, $tmp);
$factor = $tmp / $limit;
$new_width = $width / $factor;
$new_height = $height / $factor;
}

Related

PHP image scaling algorithm to fixed height and width confusion

list($orig_width, $orig_height) = getimagesize($filename);
$width = $orig_width;
$height = $orig_height;
# taller
if ($height > $max_height) {
$width = ($max_height / $height) * $width;
$height = $max_height;
}
# wider
if ($width > $max_width) {
$height = ($max_width / $width) * $height;
$width = $max_width;
}
My confusion with the below algorithm is if, for example, we have an image that we want to downsize that has a resolution of 5600 * 1200 (Width = 5600, height = 1200) and we want to downsize it to say 560 * 460 (max-width = 560, max-height = 460) in this case max size is less than both sizes which condition will be applied. Which one will be taken and why check height before width.

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

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

Alter my scale and crop class to work properly? [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

How to get the images aspect ratio using PHP?

I was wondering if a user uploads an image how can I get the aspect ratio of that image when creating the thumb. I know my width will be 180px but how can I get the height.
Here is the code I got so far listed below.
list($width, $height) = getimagesize($file) ;
if ($width >= 180){
$modwidth = 180;
$modheight = ;
} else {
$modwidth = $width;
$modheight = $height;
}
Are you trying to do something like this?
$targetsize = $x = $y = 180;
list($width, $height) = getimagesize($file);
if($width > $targetsize || $height > $targetsize) {
$aspect = $width / $height;
if($aspect < 1) $x *= $aspect; // portrait
else $y /= $aspect; // landscape
resizeImageFunctionHere($file, $x, $y);
}
But if you always want 180 wide regardless of whether the photo is portrait or not:
$targetwidth = $x = $y = 180;
list($width, $height) = getimagesize($file);
if($width > $targetsize) {
$aspect = $width / $height;
$y *= $aspect;
resizeImageFunctionHere($file, $x, $y);
}
you want to keep the same aspect ratio
so something like that $modheight = ((180.0/$width) * $height);
it would give you a picture with 180 wide and whatever height but with same ratio as the original one.

Categories