php resize image zoomcrop without border (logic) - php

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.

Related

Calculating value depending on width or height of an image

I want to check if the height or the width of an image is bigger. Depending on that, a maximum value is defined. If it is a landscape image $limit = 1000; if it is a vertical format $limit = 600;
After this the image can be scaled correctly (maximum width 1000px or 600px depending on the format of the image). If the image is smaller than that, the image values are used. (Just downscaling).
Depending on Get dimensions to transform image to a maximum value I don't know how to realize these two different limit values:
$tmp = max($width, $height); # give me the bigger value
$limit = min($limit, $tmp); # if image dimension is lower, take that value
$factor = $tmp / $limit; # calculate factor to get the new dimensions
$new_width = $width / $factor;
$new_height = $height / $factor;
So this works great if there is only one limit-value (ie. 1000).
I just need the values, no real transforming of the image...
min(1, is only needed if you want only reduce big images and not resize smaller images:
$maxWidth = 1000;
$maxWidthIfVertical = 600;
$factor = $width > $height ? min(1, $maxWidth / $width) : min(1, $maxWidthIfVertical / $width);
$newWidth = $width * $factor;
$newHeight = $height * $factor;
Caution with this method, see the examples I added here: http://jsfiddle.net/Wornet/z3z6fcr3/4/ I think it's not realy what you want.
So I recommand this (limit 1000 in width, 800 in height):
http://jsfiddle.net/Wornet/z3z6fcr3/6/

Resize images of every size to fixed width and height

I tried a lot of methods to do that, but I still have a lot of troubles with that.
Is it possible to resize all images to fixed width and height?
I want every uploaded image with width>=200px and height>=260px to be resized to width=200px and height=260px, but I want to keep a bit of proportionality and if image is bigger than 200x260px to resize it proportionally and then to capture center of image 200x260px.
I just need idea to know where to start and what to do, but if you have an example I would like to see it. Thanks.
If you want to trim the image you can do in the following way:-
//Your Image
$imgSrc = "image.jpg";
//getting the image dimensions
list($width, $height) = getimagesize($imgSrc);
//saving the image into memory (for manipulation with GD Library)
$myImage = imagecreatefromjpeg($imgSrc);
// calculating the part of the image to use for thumbnail
if ($width > $height) {
$y = 0;
$x = ($width - $height) / 2;
$smallestSide = $height;
} else {
$x = 0;
$y = ($height - $width) / 2;
$smallestSide = $width;
}
// copying the part into thumbnail
$thumbSize = 100;
$thumb = imagecreatetruecolor($thumbSize, $thumbSize);
imagecopyresampled($thumb, $myImage, 0, 0, $x, $y, $thumbSize, $thumbSize, $smallestSide, $smallestSide);
//final output
header('Content-type: image/jpeg');
imagejpeg($thumb);
To begin writing the function, we have to declare it as such… Then we have to throw in our attributes. We want to restrict our image, so we have to let the function know the dimensions to which we want to restrict it, and we have to know what the original image size is to begin with (we’ll get to that part in a second).
<?php
function imageResize($width, $height, $target) {
//takes the larger size of the width and height and applies the
formula accordingly...this is so this script will work
dynamically with any size image
if ($width > $height) {
$percentage = ($target / $width);
} else {
$percentage = ($target / $height);
}
//gets the new value and applies the percentage, then rounds the value
$width = round($width * $percentage);
$height = round($height * $percentage);
//returns the new sizes in html image tag format...this is so you
can plug this function inside an image tag and just get the
return "width=\"$width\" height=\"$height\"";
}
?>
Before we take our new function on a test drive, we need to get the width and height of the image that we want to display. There is a magical command in PHP called getimagesize(). This command, used properly, will return the image width, height, type, and even the width and height in HTML image tag format (width=”x” height=”y”).
$mysock = getimagesize("images/sock001.jpg");
Now, $mysock is an array that holds vital information about the particular image we want to display. In index 0, we have the width ($mysock[0]), and in index 1, we have the height ($mysock[1]). That’s really all we need, in order to get what we want done. Want to see the function… well, function? Here we go!
Let’s say you want to display a list of your beautiful socks, but you want room on the page to show them neatly in a row, and to do that they cannot be larger than 150 pixels tall or wide.
<?php
//get the image size of the picture and load it into an array
$mysock = getimagesize("images/sock001.jpg");
?>
<!-using a standard html image tag, where you would have the
width and height, insert your new imageResize() function with
the correct attributes -->
<img src="images/sock001.jpg" <?php imageResize($mysock[0],
$mysock[1], 150); ?>>
That’s it! Now, no matter what the original file size, it will be restricted to no more than 150 pixels in width or height (or whatever you specify).

How to restrict image width or height on upload

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.

PHP thumbnail generation

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.

PHP Thumbnail Image Resizing with proportions

As a brief run down, I am currently making a dating type site. Users can create accounts and upload profile pictures (up to 8). In order to display these in the browse area of the website, I am looking for a way in PHP (with third party processor/scripts) to resize all images uploaded to have thumbnails that adhere to certain dimensions.
As an example, I will want "profile" images (thumbnails) to be NO larger than 120*150px. The scripting needs to resize uploaded images (regardless of whether they are portrait or landscape, and regardless of proportions) to adhere to these dimensions without getting stretched.
The width (eg. 120pixels) should always remain the same, but the height (eg. 150px) can vary in order to keep the image in proportion. If it's a landscape photo, I'm assuming the script would need to take a chunk out of the middle of the image?
The reason that all images to be resized is so that when profiles are display in a grid that all thumbnails are roughly the same size.
Any input would be greatly appreciated.
$maxwidth = 120;
$maxheight = 150;
$img = imagecreatefromjpeg($jpgimage);
//or imagecreatefrompng,imagecreatefromgif,etc. depending on user's uploaded file extension
$width = imagesx($img); //get width and height of original image
$height = imagesy($img);
//determine which side is the longest to use in calculating length of the shorter side, since the longest will be the max size for whichever side is longest.
if ($height > $width)
{
$ratio = $maxheight / $height;
$newheight = $maxheight;
$newwidth = $width * $ratio;
}
else
{
$ratio = $maxwidth / $width;
$newwidth = $maxwidth;
$newheight = $height * $ratio;
}
//create new image resource to hold the resized image
$newimg = imagecreatetruecolor($newwidth,$newheight);
$palsize = ImageColorsTotal($img); //Get palette size for original image
for ($i = 0; $i < $palsize; $i++) //Assign color palette to new image
{
$colors = ImageColorsForIndex($img, $i);
ImageColorAllocate($newimg, $colors['red'], $colors['green'], $colors['blue']);
}
//copy original image into new image at new size.
imagecopyresized($newimg, $img, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
imagejpeg($newimg,$outputfile); //$output file is the path/filename where you wish to save the file.
//Have to figure that one out yourself using whatever rules you want. Can use imagegif() or imagepng() or whatever.
This will shrink any images down proportionally based on whichever side is longer (width or height), to the maximum size. It will also blow up any images smaller than max, which you can stop with a bit of checking on whether or not both width and height are less than their max. So, a 200x300 image will be shrunk to 100x150, and a 300x200 image will be shrunk to 120x80.
Hmm, you want the width to always be 120, so it would change a bit, and yeah, it would have to cut something out in the case of an image like 200x300, because that would shrink to 120x180 without any distortion, or it would have to shrink it farther and letterbox it, but that should get you started nicely.
Letterboxing this example would just involve figuring out what the proper x and y to start the drawing to the new image would be in the imagecopyresized() function. In the case of something like 100x150, the X would be 10, I think, so there would be 10px of blank space on each side for 120x150 in the end. Letterboxing 120x80 X would be 0 but Y would be 35, so there would be 35px of blank space above and below for 120x150.
You'd also want to make $newimg with $maxwidth,$maxheight rather than $newwidth,$newheight, but the imagecopyresized() would still use both $new values.
Since I'm bored and don't have anything else to do, these changes would do it:
if ($height > $width)
{
$ratio = $maxheight / $height;
$newheight = $maxheight;
$newwidth = $width * $ratio;
$writex = round(($maxwidth - $newwidth) / 2);
$writey = 0;
{
else
{
$ratio = $maxwidth / $width;
$newwidth = $maxwidth;
$newheight = $height * $ratio;
$writex = 0;
$writey = round(($maxheight - $newheight) / 2);
}
$newimg = imagecreatetruecolor($maxwidth,$maxheight);
//Since you probably will want to set a color for the letter box do this
//Assign a color for the letterbox to the new image,
//since this is the first call, for imagecolorallocate, it will set the background color
//in this case, black rgb(0,0,0)
imagecolorallocate($newimg,0,0,0);
//Loop Palette assignment stuff here
imagecopyresized($newimg, $img, $writex, $writey, 0, 0, $newwidth, $newheight, $width, $height);
That should work, haven't tried it yet.
GD or Imagick functions are what you need depending on your PHP configuration.
Sorry I'm a newbie I can't post both links in the same message :(
I have recently needed php resizing (thumbnail) solution and found Zebra_Image library, which is a lightweight image manipulation library written in PHP. The code is really clean and it's also easy to use. I highly recommend using this library. The example code is just enough to get you started.
Be make sure that you have enough memory limit set in php.ini file to manipulate images which have relatively big resolution (e.g 2560x1600). I had an error with big images and there was no error to print. I debugged the problem down to imagecreatefrom{gif,jpeg,png} calls in function _create_from_source in lines 1262, 1279, and 1288. The calls were silented with # so I couldn't have a change to get the error. I removed # lines and saw a PHP error that memory limit has been exceeded. The original memory limit was set to 32MB and I increased it to 64MB. Now I can manipulate 2560x1600 and I refuse to manipulate images which are bigger.
Below is the example code for controlling the image resolution.
$image_properties = getimagesize($UPLOADED_FILE_PATH);
$file_width = $image_properties[0];
$file_height = $image_properties[1];
if ($file_width > 2560 || $file_height > 1600) {
// handle your error whichever you like, I simply 'die' just to show
die('Cannot manipulate image bigger than 2560x1600');
}
(Note: I use Zebra Image version 2.2.2)
You can do this with ImageMagick:
convert susan.jpg -resize x200 susan_thumb.jpg
This runs with a shell command, so in PHP you'd use shell_exec() to run the above command. I don't think you need any PHP extensions.
A few flags can be found in the ImageMagick documentation to control the resizing operation. If I recall correctly, the x200 before the number means "scale with the same aspect ratio to 200px".
I wrote an install guide for ImageMagick (and ghostscript): How to install, test, convert, resize PDF using ImageMagick, Ghostscript, Windows Vista/7 x64 based on my bumbling around, maybe it can help you.
The other option is the GD library (detailed in dqhendricks answer). This is faster and apparently better documented, used for basic operations.
you don't need imagick. here is a link that will take you to a function that will resize any image using PHP GD to any arbitrary size. the function has options to use letterboxing or crop-to-fit methods to resize to the new aspect ratio. the function is also explained thoroughly. check it out.
http://www.spotlesswebdesign.com/blog.php?id=1
if this is what you are looking for, please select the check mark next to this answer. thanks!
Some says imagic faster, i use next
function resizeImageProportional($imagePath, $destinationPath, $width = false, $height = false, $filterType = \Imagick::FILTER_POINT, $blur = 1, $bestFit = false, $cropZoom = false)
{
if (!$width && !$height) {
trigger_error("WTF_IMAGE_RESIZE");
return false;
}
//The blur factor where > 1 is blurry, < 1 is sharp.
$imagick = new \Imagick(realpath($imagePath));
if (!$width || !$height) {
$orig_width = $imagick->getImageWidth();
$orig_height = $imagick->getImageHeight();
$proportion = $orig_height/$orig_width;
if (!$width) {
$width = $height*$proportion;
} elseif (!$height) {
$height = $width*$proportion;
}
}
if ($bestFit) {
$imagick->resizeImage($width, $height, $filterType, $blur, $bestFit);
} else {
$imagick->resizeImage($width, $height, $filterType, $blur);
}
if ($cropZoom) {
$cropWidth = $imagick->getImageWidth();
$cropHeight = $imagick->getImageHeight();
$newWidth = $cropWidth / 2;
$newHeight = $cropHeight / 2;
$imagick->cropimage(
$newWidth,
$newHeight,
($cropWidth - $newWidth) / 2,
($cropHeight - $newHeight) / 2
);
$imagick->scaleimage(
$imagick->getImageWidth() * 4,
$imagick->getImageHeight() * 4
);
}

Categories