Related
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
I am currently trying to create a gallery page for a client. I don't want the client to have to change any code so I am trying to make my gallery import all images from a folder and display them all as thumbnails that are the same size.
I've been able to fetch/display all the images properly and open up the lightbox, my problem is a lot of the thumbnails don't work properly. I'm trying to scale the image down while maintaining the aspect ratio and just cutting off the excess image. It seems that if the image is smaller than the size I set for the thumbnail it works properly, but if it's larger it just seems to scale the image down to the correct width. Here is an image to show what I mean:
I'm really not sure where to go from here.
I would preferably like to keep the aspect ratio
This is my make thumbs function:
function make_thumb($src,$dest,$desired_width, $desired_height, $ext) {
$size=480;
/* read the source image */
if($ext == 'jpg' || $ext = 'jpeg') {
$source_image = imagecreatefromjpeg($src);
}
if($ext == 'png') {
$source_image = imagecreatefrompng($src);
}
$width = imagesx($source_image);
$height = imagesy($source_image);
$ratio = $width / $height;
$targetWidth = $targetHeight = min($size, max($width, $height));
if ($ratio < 1) {
$targetWidth = $targetHeight * $ratio;
} else {
$targetHeight = $targetWidth / $ratio;
}
$srcWidth = $width;
$srcHeight = $height;
$srcX = $srcY = 0;
$targetWidth = $targetHeight = min($width, $height, $size);
if ($ratio < 1) {
$srcX = 0;
$srcY = ($height / 2) - ($width / 2);
$srcWidth = $srcHeight = $width;
} else {
$srcY = 0;
$srcX = ($width / 2) - ($height / 2);
$srcWidth = $srcHeight = $height;
}
/* create a new, "virtual" image */
$virtual_image = imagecreatetruecolor($targetWidth,$targetHeight);
/* copy source image at a resized size */
imagecopyresized($virtual_image,$source_image,0,0,$srcX,$srcY,$targetWidth,$targetHeight,$srcWidth,$srcHeight);
/* create the physical thumbnail image to its destination */
if($ext == 'jpg' || $ext = 'jpeg') {
imagejpeg($virtual_image,$dest);
}
if($ext == 'png') {
imagepng($virtual_image,$dest);
}
}
I figured out my issues.
First, I had $ext = 'jpeg' instead of ==
Second I had to change:
if ($ratio < 1) {
$targetWidth = $targetHeight * $ratio;
} else {
$targetHeight = $targetWidth / $ratio;
}
to
if ($ratio < 1) {
$targetWidth = $targetHeight / $ratio;
} else {
$targetHeight = $targetWidth / $ratio;
}
I am trying to create 2 cropped thumbnails (60x60 and 150x150) from a normal sized image. Everything works fine apart from the cropping, which does not work. That part is producing a thumbnail with a black line down the right side like this:
.............
. ...
. ...
. ...
.............
The resizing works fine, as the end thumbnails have the correct heights of 60 and 150 (working from a landscape image as the original) but they still come out landscape.
What I have:
list($thumb_width, $thumb_height) = getimagesize($thumb_target);
if ($thumb_width > $thumb_height) { // landscape
$thumb1_new_height = 60;
$thumb1_new_width = floor( $thumb_width * ( $thumb1_new_height / $thumb_height ));
$thumb1_crop_x = ceil(($thumb_width - $thumb_height) / 2);
$thumb1_crop_y = 0;
$thumb2_new_height = 150;
$thumb2_new_width = floor( $thumb_width * ( $thumb2_new_height / $thumb_height ));
$thumb2_crop_x = ceil(($thumb_width - $thumb_height) / 2);
$thumb2_crop_y = 0;
}
else if ($thumb_width < $thumb_height){ // portrait
$thumb1_new_width = 60;
$thumb1_new_height = floor( $thumb_height * ( $thumb1_new_width / $thumb_width ));
$thumb1_crop_x = 0;
$thumb1_crop_y = ceil(($thumb_height - $thumb_width) / 2);
$thumb2_new_width = 150;
$thumb2_new_height = floor( $thumb_height * ( $thumb2_new_width / $thumb_width ));
$thumb2_crop_x = 0;
$thumb2_crop_y = ceil(($thumb_height - $thumb_width) / 2);
} else { // square
$thumb1_new_width = 60;
$thumb1_new_height = 60;
$thumb1_crop_x = 0;
$thumb1_crop_y = 0;
$thumb2_new_width = 150;
$thumb2_new_height = 150;
$thumb2_crop_x = 0;
$thumb2_crop_y = 0;
}
$thumb1_tmp_img = imagecreatetruecolor($thumb1_new_width,$thumb1_new_height);
$thumb2_tmp_img = imagecreatetruecolor($thumb2_new_width,$thumb2_new_height);
imagecopyresampled($thumb1_tmp_img, $thumb_img, 0, 0, $thumb1_crop_x, $thumb1_crop_y, $thumb1_new_width, $thumb1_new_height, $thumb_width, $thumb_height);
imagecopyresampled($thumb2_tmp_img, $thumb_img, 0, 0, $thumb2_crop_x, $thumb2_crop_y, $thumb2_new_width, $thumb2_new_height, $thumb_width, $thumb_height);
I think you are going wrong in your thumb1_tmp_img near the end. I made this a class so I didn't have to duplicate so much like you have, but you can see the changes. See if this does it for you:
class ImageFactory
{
public function MakeThumb($thumb_target = '', $width = 60,$height = 60,$SetFileName = false, $quality = 80)
{
$thumb_img = imagecreatefromjpeg($thumb_target);
// size from
list($w, $h) = getimagesize($thumb_target);
if($w > $h) {
$new_height = $height;
$new_width = floor($w * ($new_height / $h));
$crop_x = ceil(($w - $h) / 2);
$crop_y = 0;
}
else {
$new_width = $width;
$new_height = floor( $h * ( $new_width / $w ));
$crop_x = 0;
$crop_y = ceil(($h - $w) / 2);
}
// I think this is where you are mainly going wrong
$tmp_img = imagecreatetruecolor($width,$height);
imagecopyresampled($tmp_img, $thumb_img, 0, 0, $crop_x, $crop_y, $new_width, $new_height, $w, $h);
if($SetFileName == false) {
header('Content-Type: image/jpeg');
imagejpeg($tmp_img);
}
else
imagejpeg($tmp_img,$SetFileName,$quality);
imagedestroy($tmp_img);
}
}
// Initiate class
$ImageMaker = new ImageFactory();
// Here is just a test landscape sized image
$thumb_target = 'http://media1.santabanta.com/full6/Outdoors/Landscapes/landscapes-246a.jpg';
// 60px x 60px
$ImageMaker->MakeThumb($thumb_target,60,60,'image60px.jpg');
// Here is a portrait for testing
$thumb_target = 'http://imgc.allpostersimages.com/images/P-488-488-90/55/5543/L6HLG00Z/posters/warning-you-are-entering-a-fart-zone.jpg';
// 150px x 150px
$ImageMaker->MakeThumb($thumb_target,150,150,'image150px.jpg');
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
Problem: Script seems to be running slow. This script is inside a function that is run four times for different image sizes. Is there any way to speed up the code below?
$outputFile = "../data/assets/temp.jpg";
$maxTempWidth = 45;
$maxTempHeight = 45;
$image_info = getimagesize($setXsmallNewName);
if($image_info['mime'] == 'image/jpeg'){
$image = imagecreatefromjpeg($setXsmallNewName);
}elseif($image_info['mime'] == 'image/gif'){
$image = imagecreatefromgif($setXsmallNewName);
}elseif($image_info['mime'] == 'image/png'||$image_info['mime'] == 'image/x-png'){
$image = imagecreatefrompng($setXsmallNewName);
}
$width = imagesx( $image );
$height = imagesy( $image );
if ($width > $maxTempWidth || $height > $maxTempHeight){
if ( $width > $height ){
$newwidth = $maxTempWidth;
$ratio = $maxTempWidth / $width;
$newheight = floor($height * $ratio);
if ($newheight > $maxTempHeight){
$newheight = $maxTempHeight;
$ratio = $maxTempHeight / $height;
$newWidth = floor($width * $ratio);
}
}else{
$newheight = $maxTempHeight;
$ratio = $maxTempHeight / $height;
$newwidth = floor($width * $ratio);
if ($newwidth > $maxTempWidth){
$newwidth = $maxTempWidth;
$ratio = $maxTempWidth / $width;
$newheight = floor($height * $ratio);
}
}
}else{
$newwidth = $width;
$newheight = $height;
}
$final_image = imagecreatetruecolor($newwidth, $newheight);
imagecopyresampled($final_image, $image, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
Use ImageMagick, which is core to the php family and very speedy.