Is it possible to resize an image in PHP, to a specified size in Kilobytes, with large images?
Example: IMGonline.com.ua
You can absolutely resize to a certain size using resize so if you know a certain number of pixels will be within that size you could set a pixel size. I've used 100x100 for reference.
$resize = new ResizeImage('image.png');
$resize->resizeTo(100, 100, 'exact');
$resize->saveImage('/resized/image.png');
Using this theory you could take the same approach and if an image is already that size or below you could resize it.
if ($file_size < 5000) {
$resize = new ResizeImage('image.png');
$resize->resizeTo(100, 100, 'exact');
$resize->saveImage('/resized/image.png');
} else {
// Error
}
So you could run it like this
// Upload Image
// Resize image
$resize = new ResizeImage('image.png');
$resize->resizeTo(100, 100, 'exact');
$resize->saveImage('/resized/image.png');
// Save image
// Open saved image
// Check image size
// Confirm or resize progressively smaller.
Hopefully the resize property is of some use. You've provided no code in your question but I think the best approach would be to check the size and save if it's fine then if not you would resize again and check again. Obviously you'd have to do this until it was at the correct size so execution time could take longer. I can't think of a direct way to compress the image with a php function unless you compressed the images instead of resizing them.
Related
I have an upload form which allows multiple files to be selected. The original files are quite heavy - approx. 10MB each.
Each uploaded file goes through the same resizing and saving process:
<?php
$file = $request->file('qqfile'); // Huge JPG file in the request
$image = Image::make($file); // Building an Intervention Image object
$sizes = array(2560, 1980, 1366, 1024, 768, 480, 320);
foreach ($sizes as $size) {
$image = $image->widen($size->width);
Storage::put('public/image_'.$size.'.jpg', $image->encode('jpg', 90));
}
Now, my understanding is that in the foreach loop it's the 10MB, original image object that's being reused. So, during each iteration, the 10MB image object gets resized to a smaller size - e.g. from 4200x2460 to 320x187 in the last iteration, and then saved on the disk.
If I'm correct (am I?) then it's not very efficient, as the GD library operations are quite expensive and the server CPU can get hit stronger than it should.
Is there any way I can optimize the resizing process? E.g. for each iteration use already-resized image object, instead of the huge original one?
I would avoid this, though: resize - save - read from disk - resize again, as the disk I/O can get hit as well. What I have in mind is this: resize the original - resize to the next size - ... - resize the last size, then save each. This means I need a way to store a resized Intervention object in a variable, but not save it yet (as it will be saved in the last step).
Does this make sense? Any ideas?
Thank you.
found this which is nice and quick to implement. It works great but what I want it before the images are uploaded, that they get resized to a max width but keeping the ratio.
Let say i am uploading an image with a width of 5000px, i want this to be resized to 1000px width but keep the height ratio and then save the final image.
Example usage:
/* shrink() - will shrink/resize the image according to the given dimensions (in pixels)
* NOTE, a folder called 'shrinked_images' will be created first to store the uploaded image
*/
$bulletProof
->fileTypes(array("jpg", "gif", "png", "jpeg"))
->uploadDir("shrinked_images")
->shrink(array("height"=>100, "width"=>200))
->upload($_FILES["pictures"]);
The GitHub:
https://github.com/samayo/bulletproof
I have read through the docs but cant find anything about resizing. All i can find in the code is the shrinking function but cant see how to add the keep ratio option with that?
Thanks. Craig.
Second parameter of shrink is $ratio which allows to preserve aspect ratio.
Try
->shrink(array("height"=>100, "width"=>200), true)
or if you want your images resized using width only set height to PHP_INT_MAX as both parameters are required
->shrink(array("height"=> PHP_INT_MAX, "width"=>200), true)
I had troubles resizing a PNG and maintaining small file sizes. Solution found here.
When resizing the PNG, however, I ran into problems regarding image quality. As far as I could see, GD uses indexed 8-bit-color palette which distorts text and colors get lost, see:
Original Image
Resized Image with solution given above
Resized Image with a tweak²
²The idea for the tweak I found here in stackoverflow: Create truecolor-image, resize it, and copy it to a new image, so the palette is determined based on the resampled result and the image quality is better as you can see in the image above.
// create new image
$newImageTmp = imagecreatetruecolor($newwidth,$newheight);
// we create a temporary truecolor image
// do the image resizing by copying from the original into $newImageTmp image
imagecopyresampled($newImageTmp,$src,0,0,0,0,$newwidth,$newheight,$width,$height);
// create output image
$newImage = imagecreate($newwidth,$newheight);
// copy resized truecolor image onto index-color image
imagecopy($newImage,$newImageTmp,0,0,0,0,$newwidth,$newheight);
// write image to buffer and save in variable
ob_start(); // stdout --> buffer
imagepng($newImage,NULL,6);
$newImageToSave = ob_get_contents(); // store stdout in $newImageToSave
ob_end_clean(); // clear buffer
// remove images from php buffer
imagedestroy($src);
imagedestroy($newImageTmp);
imagedestroy($newImage);
Problem: None of both results are satisfactory.
I am quite sure that there must be a way to 1. determine the color palette, and 2. maintain most of the image's colors, so that 3. the PNG looks similar to the original and has an acceptable file size.
Now, I only see going for JPG instead of PNG. But if you know a solution, it would greatly be appreciated if you let me/us know.
Thank you!
All you need is to replace
$newImage = imagecreate($newwidth,$newheight);
With
$newImage = imagecreatetruecolor($newwidth, $newheight);
Output $maxImgWidth = 200;
PHP's fork of GD doesn't have usable palette generation, so you only get PNG32 with vanialla libpng compression.
For small PNG8 with palette use pngquant, e.g. http://pngquant.org/php.html
And then compress it further with advpng or zopfli-png.
While resizing an image, I have noticed that Imagick and Gmagick produce images with different filesize on HDD with the same options:
$image = new Imagick("c.jpg");
$image->thumbnailImage(260,195);
$image->writeImage("c_imagick.jpg");
outputs an Image with 88kb
$image = new Gmagick("c.jpg");
$image->thumbnailImage(260,195);
$image->writeImage("c_gmagick.jpg");
outputs an Image with 15kb
Does someone have any idea, why the difference is so huge?
Try setting the image compression settings prior to resizing.
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
$image->setImageCompressionQuality(80);
Additionally, check the size of the resulting image. Comments in the PHP documentation lead me to believe that the automatic fit portion of thumbnailImage does not work as you would expect in IMagick.
From PHP Docs:
The fit functionality of thumbnailImage doesn't work as one would anticipate. Instead, use >this to make a thumbnail that has max of 200x82:
// Create thumbnail max of 200x82
$width=$im->getImageWidth();
if ($width > 200) { $im->thumbnailImage(200,null,0); }
$height=$im->getImageHeight();
if ($height > 82) { $im->thumbnailImage(null,82,0); }
I want images to resize after upload in 4 different formats. If i resize it to best fit(i.e aspect ratio) some images come too small if height or width is too large than the other and if i resize it to fixed size then images get skewed. So what is the best way to resize a image. I am currently doing this using via imagemagik thumbnailImage() but i think it's a general problem. What are sites like google or facebook doing. what is the best thing to do in that case
You can use resize functionality for resize image in different size during upload image.
For example:
include('SimpleImage.php');
$image = new SimpleImage();
$image->load($_FILES['uploaded_image']['tmp_name']);
$image->resizeToWidth(300);
$image->resizeToHeight(200);
$image->save('resizeImage.jpg'
Similarly, you can save image in different size.
For more in detail you can find here:
http://sanjeevkumarjha.com.np/how-to-resize-and-crop-image/
You can also use ImageWorkshop: http://phpimageworkshop.com/doc/17/resizing.html
$layer = new ImageWorkshop(array("fileObject" => $_FILES["uploadedImage"]));
$layer->resizeInPixel(200, 150, true); // Conserve proportion !
$layer->save(__DIR__."/web/uploads/2012", "thumb.png", true, null, 95);
You will have a resized picture of 200px/150px with conserved proportion !