I'm trying to generate thumbnails of the images my users upload. I have got the basic functionality to work by having my thumbnail class generate a thumbnail that is 50% of the width and height of the original image. However, I'd like to extend its functionality and enforce a hard limit on thumbnails that will be larger than 400px on either side after the 50% reduction.
This is what I have so far:
$x = $image_info[0]; // width of original image
$y = $image_info[1]; // height of original image
$x_t = $x/2; // width of 50% thumbnail
$y_t = $y/2; // height of 50% thumbnail
$biggest = ($x_t > $y_t) ? $x_t : $y_t; // determine the biggest side of the thumbnail
if($biggest > 400)
{
// Enforce a 400px limit here
/// somehow :(
}
With this hard limit, I want the original image to be scaled down so that no side exceeds 400px, and I want the other side to be scaled down relative so the image doesn't look distorted.
Being as terrible with math as I am, I can't work out a way to calculate the image dimensions that my thumbnail class should resize the image to.
Any ideas?
You'd have to compute a scaling factor:
$factor = $biggest / 400; // if 503, then factor = 1.2575;
$new_x = $x / $factor;
$new_y = $y / $factor;
and use those two new dimensions for your scaling. That'll reduce whatever side is $biggest to 400, and proportionally reduce the other dimension to something less than 400.
You will have to check for each length, not both at once:
if ($x > 400) {
$x_t = 400;
$y_t = $y * (400 / $x);
}
if ($y > 400) {
...
If $x is 600 for example, the calucalation would become $y_t = $y * (400 / 600), thus reducing $y to 2/3 of its original value.
And add the same condition for the $y side. Additionally you might want to apply the calculations concurrently, if neither side is allowed to be larger than 400.
Related
I have 2 dimensions, (width & height) and I need to take another image, and resize it until both width and height are greater than the 2 dimensions. If the image is already larger than the 2 dimensions, I still need to resize it to be slightly larger than the given dimensions.
I also need to keep the image aspect ratio the same.
I've been trying the following:
$masksize = getimagesize($maskpath);
// Reverse the sizes as it's landscape and we're always checking portrait
$maskwidth = $masksize[1];
$maskheight = $masksize[0];
$currentsize = getimagesize($target_path);
$currentwidth = $currentsize[0];
$currentheight = $currentsize[1];
$thumwidth = 0;
$thumbheight = 0;
do {
$thumbwidth += 10;
$thumbheight = $currentheight*($thumbheight+10/$thumbwidth);
}while (($thumbwidth < $maskwidth) && ($thumbheight < $maskheight));
However it's not working, it only loops once and the width stays at 10.
So say for instance I have an image at 1000 x 2000, and the dimensions I have are 500 x 1000, I need the image to be resized to 510 x 1010 (i.e always bigger than the given dimensions, but only by a max of 10)
I just want to know if it is possible to get different images' sizes, and create fixed thumbnail dimension measurements for these pictures without losing their accurate aspect ratios.
So far, I have made these:
Resize different images
Maintain their aspect ratios
NOT supplying the same size (for example: 100px- height and 100px- width)
Here's the code that I am working with:
<?php
require("dbinfo.php");
$allPhotosQuery = mysql_query (" SELECT * FROM `placesImages` ");
while ($allPhotosArray = mysql_fetch_assoc ($allPhotosQuery))
{
$filename= $allPhotosArray['fileName'];
$placeId = $allPhotosArray['placeId'];
$imagePath = "placesImages/" . $placeId . "/" . $filename;
$imageSize = getimagesize($imagePath);
$imageWidth = $imageSize[0];
$imageHeight = $imageSize[1];
$newSize = ($imageWidth + $imageHeight)/($imageWidth*($imageHeight/45));
$newHeight = $imageHeight * $newSize;
$newWidth = $imageWidth * $newSize;
echo "<img src='".$imagePath."' width='".$newWidth."' height='".$newHeight."' />";
}
?>
Short of cropping, the simplest way to maintain aspect ratio while making a thumbnail is to do something similar to what you have, but set one fixed:
For example, if you want all your tumbs to be 100px wide:
$imageWidth = $imageSize[0];
$imageHeight = $imageSize[1];
$ratio=ImageWidth/$imageHeight;
$newHeight=(int)$ratio*100;
$newWidth=100;
The caveat with this is that you might end up with some funny sizes if the image has a funny ratio - as in it will happily go ahead and just do it. It might be a good idea to put some sort of check on the ratio in your code - if it it too low or too high, do something else, otherwise use this standard process.
feed this function your original image width and heights followed by the maximum constraints of your thumbnail limits and it will spit out an array with x/y of what you should set your thumbnail at to maintain aspect ratio. (anything smaller than the thumbnail will be enlarged)
function imageResizeDimensions($source_width,$source_height,$thumb_width,$thumb_height)
{
$source_ratio = $source_width / $source_height;
$thumb_ratio = $thumb_width / $thumb_height;
if($thumb_ratio > $source_ratio)
{
return array('x'=>$thumb_height * $source_ratio,'y'=>$thumb_height);
}
elseif($thumb_ratio < $source_ratio)
{
return array('x'=>$thumb_width,'y'=>$thumb_width/$source_ratio);
}
else
{
return array('x'=>$thumb_width,'y'=>$thumb_width);
}
}
Let’s begin with two constants, thumb_width and thumb_height, which are the desired width and height of your thumbnail images. They can be equal, but don’t have to be.
If you have an image that’s wider than it is tall (landscape) we can set the width to the desired width of the thumbnail, thumb_width, and adjust the height to maintain the aspect ratio.
new_width = thumb_width
new_height = thumb_height * old_height / old_width
See imagecreatetruecolor.
Then you can move the image to center it vertically within the limits of the thumbnail, producing a letterbox effect. See imagecopyresampled.
new_y = (thumb_height - new_height) / 2
For images that are taller than they are wide (portrait) the procedure is the same, but the math is a little different.
new_height = thumb_height
new_width = thumb_width * old_width / old_height
Then you can center it horizontally within the limits of the thumbnail.
new_x = (thumb_width - new_width) / 2
For more information on the basics of creating thumbnail images see Resizing images in PHP with GD and Imagick
I would like manipulate/resize images in a similar way to Pinterest but I am not sure what is the best way to approach it. The goal is to allow a mix of both portrait and landscape images but put some restrictions on the maximum height and width.
The problem i can see is that if I resize to a width, a portrait image may become too thin, and the opposite it true for a landscape image.
Any ideas on how to achieve those sort of results with PHP?
You just need to understand which of the two edges of the image is longer, and compute the other dimension proportionally. If the maximum long-egde is 1024, then if one of the two edges is larger you will set that to 1024, and compute the other to fit the proportions. Then you will pass those two values to your image management functions.
Like here:
http://www.white-hat-web-design.co.uk/blog/resizing-images-with-php/
Or here:
http://www.9lessons.info/2009/03/upload-and-resize-image-with-php.html
try with this
$needheight = 1000;
$needwidth = 1000;
$arrtest = getimagesize($upload_image_physical_path);
$actualwidth = $arrtest[0];
$actualheight = $arrtest[1];
if($needwidth > $actualwidth || $needheight > $actualheight){
//uplaod code
}
cheers
Check for a max size and then resize based on a ratio. Here's a pseudo code example:
if($imageHeight > $maxHeight) {
$newHeight = $maxHeight;
$newWidth = $imageWidth * ($maxHeight / $imageHeight);
}
if($imageWidth > $maxWidth) {
$newWidth = $maxWidth;
$newHeight = $imageHeight * ($maxWidth / $imageWidth);
}
resize($image, $newWidth, $newHeight);
It first checks the height and if the height is greater, it scales it down. Then it checks the width. If the width is too big, it scales it down again. The end result, both height and width will be with in your bounds. It uses the ratio to do the scaling.
Note, this is pseudocodish. The actual resize function call will depend on your image manipulation library -- same goes for calls to obtain image size.
i have a image manipulation class, i want to create images that always fill the entire new width and height so there are no borders/solid color background, i just cant understand how i can make it always fill the height and width (mantaining the aspect ratio of the uploaded image) if the image width AND height are smaller than the new image size..
just like the zoomcrop (zc=1) from phpthumb class (i looked the code from it but i couldnt mimic the behavior)
public function resizeCrop($newwidth, $newheight) {
...
$x = $this->getX();
$y = $this->getY();
...
else if ($x < $newwidth && $y < $newheight)
{
// logic ??
}
}
You need to make sure that the smaller (relative to the aspect ratio of the original image and that of container) side is zoomed to maximum. Have a look at this code:
public function resizeCrop($newwidth, $newheight) {
...
$x = $this->getX();
$y = $this->getY();
// old images width will fit
if(($x / $y) < ($newwidth/$newheight)){
$scale = $newwidth/$x;
$newX = 0;
$newY = - ($scale * $y - $newheight) / 2;
// else old image's height will fit
}else{
$scale = $newheight/$y;
$newX = - ($scale * $x - $newwidth) / 2;
$newY = 0;
}
// new image
$dest = imagecreatetruecolor($newwidth, $newheight);
// now use imagecopyresampled
imagecopyresampled($dest, $src, $newX, $newY, 0, 0, $scale * $x, $scale * $y, $x, $y);
return $dest;
}
Update: Corrected the function. It is now working perfectly, I have tested it on my dev machine.
To maintain aspect ratio, you need to choose: either make the image too big and then crop the original, or you make it fit just right and then fill in the parts that don't reach the edges with a solid color.
The former, you can compare the percentage change for width and height respectively, then use the larger percentage as a multiplier against both dimensions. For a 1 x 1 unit image that you want to fit into a 2w x 3h unit area and maintain aspect ratio: you can use a 3x multiplier, get a 3 x 3 unit image, and crop .5 units left/right.
The latter, you use the smaller percentage as a multiplier. For a 1 x 1 unit image that you want to fit into a 2w x 3h unit area and maintain aspect ratio: you can use a 2x multiplier, get a 2 x 2 unit image, and add .5 units of solid color top/bottom.
I want the new height and width to which the image needs to be resized. There are two conditions
Width needs to be around 180px(170-180) but < 180px (uploaded image is always > 180)
Height should be max 180px (uploaded image may or may not be > 180)
If you are writing program for Linux I would recommend using ImageMagick. It is more memory efficient and probably faster than any PHP based method. Almost all servers have it installed. Following code will do the trick.
function resizeTo($source, $dest, $w=180, $h=180) {
system("convert $source -resize {$w}x{$h} $dest");
}
It will mind the aspect ratio.
Edit:
Sorry for the confusion. I think the following should do what you are looking for. It is not tested and might need a little bit debugging, if you run into trouble I can try and post again.
//accepts and returns point object (having ->x and ->y)
function resizeTo($current, $max) {
if($current->x <= $max->x && $current->y <= $max->y) //you will not need this but
return $current; // still its good to have
if( ($current->y / $max->y) > ($current->x / $max->x) ) { //y axis needs more trimming
$r=$current->y / $max->y;
$current->y = $max->y;
$current->x = $current->x / $r;
} else {
$r=$current->x / $max->x;
$current->x = $max->x;
$current->y = $current->y / $r;
}
return $current;
}
You just need a few steps:
1. scale = imageWidth / 180;
2. scale = (imageHeight/scale>180) ? imageHeight/180 : scale;
The first one will set the scale factor you need to make the width 180 (based on your comment that it is ALWAYS larger then 180)
The second one will check if the height will be larger then 180 with that scale. If it is, then the scale will be height/180. If its not, you already have the max height.
Then you also need steps to get the actual width and height:
width = imageWidth/scale;
height = imageHeight/scale;
Considering you want to make the imageWidth between 170 and 180 I guess cropping the image is also a possibility. If that is the case you need an additional check
if (width<170) {
width = 170;
height = imageHeigh / (imageWidth/170);
//resize image to width and height
//crop image to height = 180
}