Can someone help me with an equation. I'd like to resize an image down so that it has a minimum width or height of 200px. So, if the original is 500 x 300 it'd end up being 333 x 200 and if the original was 500 x 900 it'd end up being 200 x 360 and so on. If either of the original dimensions are smaller than 200px, no resizing is done.
I'd appreciate any input on this. I am sure its quite simple, I just can't seem to work it out.
You just need to work out the existing image ratio and do the math from that. The ratio is the images width compared to height or vice versa (usually which ever is longer is divided by the shorter to give you a ratio >= 1). for example width 450 and height 300 has a ratio of 1.5 wide. meaning that the image is 1.5 times wider than it is tall. Then you can multiply your "minimum" value by the ratio to get the other size or as in the example if your height is 200 the other side will be minimum * ratio or 200 * 1.5 which makes the size 300 wide and 200 tall.
$height = 500;
$width = 300;
$min = 200;
if($width > $height){
$ratio = $width/$height;
$height = $min;
$width = round($min * $ratio);
} else {
$ratio = $height/$width;
$width = $min;
$height = round($min * $ratio);
}
echo "Width: $width<br>";
echo "Height: $height<br>";
http://codepad.viper-7.com/RsxAsC
Aparently, you'd like to have the smallest side to fit 200px, but dont upscale. I'd do something like this
if ($width > 200 || $height > 200) {
if ($width > $height) {
$ratio = (200 / $height);
} else {
$ratio = (200 / $width);
}
$resizedWidth = $ratio * $width;
$resizedHeight = $ratio * $height;
}
Not complete code, just a starting point, hope this helps
if your server has the php imagick extension installed you can use the function cropThumbnailImage()
http://php.net/manual/en/imagick.cropthumbnailimage.php
I altered Jonahtan answer to be a bit shorter and where you only calculate a ratio once:
// Set image dimensions for testing
$imgWidth = 100;
$imgHeight = 250;
// Minimal dimension requirements
$minDim = 300;
if ($imgWidth < $minDim || $imgHeight < $minDim) {
$ratio = $imgWidth / $imgHeight;
if( $ratio > 1) { // Width is greater
$imgHeight = $minDim;
$imgWidth = round($minDim * $ratio);
}
else { // Height is greater
$imgWidth = $minDim;
$imgHeight = round($minDim / $ratio);
}
}
echo "Width: $imgWidth<br>";
echo "Height: $imgHeight<br>";
Related
The Instagram image ratio requirements are:
1:1
4:5
1.91:1
16:9
Readed here and here. The documentation also says:
(...) Advise the app user to try again with an image that falls withing a
4:5 to 1.91:1 range.
Althought the documentation doesn't say, I know for a fact that publishing a photo with 1:1 ratio works.
So I would like to check if the image uploaded meets the requirements and if not resize to meet them (either by downsizing or upsizing). I'm using Laravel with Image Intervention library.
To check the aspect ratio, I'm using the following code:
public function isRatioValid($img)
{
$manager = new ImageManager(['driver' => 'imagick']);
$image = $manager->make($img);
$width = $image->width();
$height = $image->height();
for ($i = $height; $i > 1; $i--)
{
if (($width % $i) == 0 && ($height % $i) == 0)
{
$width = $width / $i;
$height = $height / $i;
}
}
$ratio = "{$width}:{$height}";
if (!in_array($ratio, ['1:1', '4:5', '1.91:1', '16:9']))
return false;
return true;
}
Problems:
This code strictly checks for the ratio values it does not entirely meet the Instagram documentation that says "(...) withing a 4:5 to 1.91:1 range". Is this ok?
In case the ratio is not valid, how can I use the Resize functionality to apply the best ratio that fits the Instagram requirements?
Solved.
The code to check the aspect ratio was not correct. To check it properly all we need to do is divide the width for the height and see if it fits the range of Instagram requirements.
function isRatioValid(...)
{
$width = 400;
$height = 711;
// 1:1 - squares
if ($width == $height)
return true;
$ratio = round($width / $height, 3);
// Portrait: min 0.8 | max 0.99
// Landscape: min 1.01 | max 1.91
if ($width < $height)
if ($ratio >= 0.8 && $ratio <= 0.99)
return true;
if ($width > $height)
if ($ratio >= 1.01 && $ratio <= 1.91)
return true;
return false;
}
To resize it, I added 0.10 to either the width (portraits) or height (landscapes) until the aspect ratio was within the range. You should limit the amount of tries so it won't burn the CPU / max execution time.
I've been trying to figure out how to resize an uploaded image in PHP so that it is not smaller than a given size (650x650). However if a user uploads an image that is already smaller than my 650 minimum on either edge, no action is to be taken.
Scenario 1 - a 2000px width by 371px image is updloaded - this would not be resized as 371px is already less than my minimum.
Scenario 2 - a 2000px by 1823px image is uploaded - here I should resize the image as close to the minimum as possible, but not allow the width or height to be below 650px.
Here's the lines I've been thinking along so far (I'm using the excellent simpleImage script to help with resizing and getting dimensions):
$curWidth = $image->getWidth();
$curHeight = $image->getHeight();
$ratio = $curWidth/$curHeight;
if ($curWidth>$minImageWidth && $curHeight>$minImageHeight)
{
//both dimensions are above the minimum, so we can try scaling
if ($curWidth==$curHeight)
{
//perfect square :D just resize to what we want
$image->resize($minImageWidth,$minImageHeight);
}
else if ($curWidth>$curHeight)
{
//height is shortest, scale that.
//work out what height to scale to that will allow
//width to be at least minImageWidth i.e 650.
if ($ratio < 1)
{
$image->resizeToHeight($minImageWidth*$ratio);
}
else
{
$image->resizeToHeight($minImageWidth/$ratio);
}
}
else
{
//width is shortest, so find minimum we can scale to while keeping
//the height above or equal to the minimum height.
if ($ratio < 1)
{
$image->resizeToWidth($minImageHeight*$ratio);
}
else
{
$image->resizeToWidth($minImageHeight/$ratio);
}
}
However this gives me some strange results, at times it will still scale below the minimum. The only part of it that works as expected is the test for the dimensions being above the minimum - it won't scale anything that's too small.
I think my biggest problem here is that I don't fully understand the relationship between the image aspect ratio and the dimensions, and how to work out what dimensions I'd be able to scale to that are above my minimums. Any suggestions?
try this:
$curWidth = $image->getWidth();
$curHeight = $image->getHeight();
$ratio = min($minImageWidth/$curWidth,$minImageHeight/$curHeight);
if ($ratio < 1) {
$image->resize(floor($ratio*$curWidth),floor($ratio*$curHeight));
}
or this:
$image->maxarea($minImageWidth, $minImageHeight);
Try this:
$curWidth = $image->getWidth();
$curHeight = $image->getHeight();
if ($curWidth>$minImageWidth && $curHeight>$minImageHeight) {
$ratio = $curWidth/$curHeight;
$zoom = image_ratio > 1
? $minImageHeight / $curHeight
: $minImageWidth / $curWidth
;
$newWidth = $curWidth * $zoom;
$newHeight = $curHeight * $zoom;
}
I have 2 variables available about a photo i'm importing, width and height.(I could use imagesx etc, but i'm importing in bulk and it takes way too long)
eg..
$w = 720;
$h = 540;
How can I workout the correct height for the photo if I say the max width is 180px, I know the correct height should be 135px (on a standard landscape photo). But the starting width and height i'm given will change depending on the photo.
Keeping the image in proportion what calculation do I need to do to workout the reduced width and height?
Final result will be in pixels so can not have any decimal places.
(I do not actually need to re-size the photo, just calculate the size.)
Thanks in advance :)
720x = 540 * 180
It is a simple cross-multiplying rule. Then round the numbers to get rid of the decimal portion.
Here's one I use:
function scaleDimensions($orig_width, $orig_height, $max_width, $max_height) {
if ($orig_width < $max_width && $orig_height < $max_height) {
return array($orig_width, $orig_height);
}
$ratiow = $max_width / $orig_width;
$ratioh = $max_height / $orig_height;
$ratio = min($ratiow, $ratioh);
$width = intval($ratio * $orig_width);
$height = intval($ratio * $orig_height);
return array($width, $height);
}
Usage:
list($width, $height) = scaleDimensions($w, $h, 180, 135);
And this is the javascript version of #fire's answer
scaleDimensions : function(orig_width, orig_height, max_width, max_height) {
if (orig_width < max_width && orig_height < max_height) {
return [orig_width, orig_height];
}
var ratiow = max_width / orig_width;
var ratioh = max_height / orig_height;
var ratio = Math.min(ratiow, ratioh);
var width = (ratio * orig_width).toFixed(0);
var height = (ratio * orig_height).toFixed(0);
return [width, height];
}
I php need to resize an image so that both width and height after resize should be less than or equal to the expected resized values.
consider the source image is 680x520
The needed thumbmail size should be <= 300x200
I want to find the resized proportional value which should be less than or equal to 300x200.
it can be like 299x199 or 300x200 but not greater than 300 in width and 200 in height.
So both should be less than or equal to the needed size.
What could be the formula?
//height - original image height;
//width - original image width;
if ($height > $width) {
$thumb_height = 200;
$thumb_width = round(($width * $thumb_height) / $height);
} else {
$thumb_width = 300;
$thumb_height = round(($height * $thumb_width) / $width);
}
EDIT:
//height - original image height;
//width - original image width;
$thumb_height = 0;
$thumb_width = 0;
if ($height > $width) {
$thumb_height = 200;
} else {
if ($height > ($width * 200)/300)
$thumb_height = 200;
else
$thumb_width = 300;
}
if ($thumb_height > 0) {
$thumb_width = round(($width * $thumb_height) / $height);
} else {
$thumb_height = round(($height * $thumb_width) / $width);
}
I didn't find any example for the reversed that you gave me. If you have one, please tell me and I will check to see if the above script needs any modifications.
Maybe offtopic, but for image manipulation realy easy to use:
Wide Image
What would be the best way to resize images, which could be of any dimension, to a fixed size, or at least to fit within a fixed size?
The images come from random urls that are not in my control, and I must ensure the images do not go out of an area roughly 250px x 300px, or 20% by 50% of a layer.
I would think that I would first determine the size, and if it fell outside the range, resize by a factor, but I am unsure how to work out the logic to resize if the image size could be anything.
edit:I do not have local access to the image, and the image url is in a variable with is output with img src=..., I need a way to specify the values of width and height tags.
It's easy to do with ImageMagick. Either you use convert command line tool via exec or you use http://www.francodacosta.com/phmagick/resizing-images .
If you use 'convert' you can even tell ImageMagick to just resize larger images and to not convert smaller ones: http://www.imagemagick.org/Usage/resize/
If you don't have local access, you won't be able to use ImageMagick:
<?php
$maxWidth = 250;
$maxHeight = 500;
$size = getimagesize($url);
if ($size) {
$imageWidth = $size[0];
$imageHeight = $size[1];
$wRatio = $imageWidth / $maxWidth;
$hRatio = $imageHeight / $maxHeight;
$maxRatio = max($wRatio, $hRatio);
if ($maxRatio > 1) {
$outputWidth = $imageWidth / $maxRatio;
$outputHeight = $imageHeight / $maxRatio;
} else {
$outputWidth = $imageWidth;
$outputHeight = $imageHeight;
}
}
?>
Have you looked at the GD library documentation, particularly the imagecopyresized method?
If you have to keep the aspect ratio of the image intact then you should scale it by a factor so that the longer side of the image (height or width) fits inside the limitations for that side.
You could use the following:
$maxWidth = 250;
$maxHeight = 500;
$validSize = true;
$imageinfo = getimagesize($filename);
if ($imageinfo) {
$validSize &= $imageinfo[0] <= $maxWidth;
$validSize &= $imageinfo[1] <= $maxHeight;
}
The &= is a combined operator of the bitwise-and operator & and the assignment operator =. Thus $foo &= *expr* and $foo = $foo & *expr* are equivalent.
I'm not sure of the exact solution to your answer, but I know a project written in PHP which has the solution. Go and take a look at the ImageCache built for the Drupal CMS, which is written in PHP.
It basically let's you define some actions to take on an arbitrary image, and produce almost whatever scaling/cropping you want to the image.
You'd have to learn a few of the Drupal API's to be able to understand this example, but it is extensive and if you understand their algorithms, you'd be able to solve other more complicated problems.
I created the following function to do intelligent resizing of images with respect to ratio and even has a parameter to upscale smaller images (which is critical if your HTML layout screws up when thumbnails are wierd sizes).
function ImageIntelligentResize( $imagePath, $maxWidth, $maxHeight, $alwaysUpscale )
{
// garbage in, garbage out
if ( IsNullOrEmpty($imagePath) || !is_file($imagePath) || IsNullOrEmpty($maxWidth) || IsNullOrEmpty($maxHeight) )
{
return array("width"=>"", "height"=>"");
}
// if our thumbnail size is too big, adjust it via HTML
$size = getimagesize($imagePath);
$origWidth = $size[0];
$origHeight = $size[1];
// Check if the image we're grabbing is larger than the max width or height or if we always want it resized
if ( $alwaysUpscale || $origWidth > $maxWidth || $origHeight > $maxHeight )
{
// it is so let's resize the image intelligently
// check if our image is landscape or portrait
if ( $origWidth > $origHeight )
{
// target image is landscape/wide (ex: 4x3)
$newWidth = $maxWidth;
$ratio = $maxWidth / $origWidth;
$newHeight = floor($origHeight * $ratio);
// make sure the image wasn't heigher than expected
if ($newHeight > $maxHeight)
{
// it is so limit by the height
$newHeight = $maxHeight;
$ratio = $maxHeight / $origHeight;
$newWidth = floor($origWidth * $ratio);
}
}
else
{
// target image is portrait/tall (ex: 3x4)
$newHeight = $maxHeight;
$ratio = $maxHeight / $origHeight;
$newWidth = floor($origWidth * $ratio);
// make sure the image wasn't wider than expected
if ($newWidth > $maxWidth)
{
// it is so limit by the width
$newWidth = $maxWidth;
$ratio = $maxWidth / $origWidth;
$newHeight = floor($origHeight * $ratio);
}
}
}
// it's not, so just use the current height and width
else
{
$newWidth = $origWidth;
$newHeight = $origHeight;
}
return array("width"=>$newWidth, "height"=>$newHeight);
}