I need some ways to dynamically optimize images using PHP. Sample codes or a module would be very helpful. Thanks.
you can use thimthumb.php
go to your .htaccess
than add
<IfModule mod_rewrite.c>
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^(.*\.(png|jpg))$ /timthumb.php?q=100&src=$1
</IfModule>
"q=100" is for the quality you can set it betwen 0-100
than creat a new file "img.php" in the home directory eg: www.your-website.com/timthumb.php
http://timthumb.googlecode.com/svn/trunk/timthumb.php
than find this
// Get original width and height
$width = imagesx ($image);
$height = imagesy ($image);
$origin_x = 0;
$origin_y = 0;
// generate new w/h if not provided
if ($new_width && !$new_height) {
$new_height = floor ($height * ($new_width / $width));
} else if ($new_height && !$new_width) {
$new_width = floor ($width * ($new_height / $height));
}
and replace it with this
// Get original width and height
$width = imagesx ($image);
$height = imagesy ($image);
$origin_x = 0;
$origin_y = 0;
// don't allow new width or height to be greater than the original
if( $new_width > $width ) {
$new_width = $width;
}
if( $new_height > $height ) {
$new_height = $height;
}
// generate new w/h if not provided
if ($new_width && !$new_height) {
$new_height = floor ($height * ($new_width / $width));
} else if ($new_height && !$new_width) {
$new_width = floor ($width * ($new_height / $height));
}
so when you go to www.your-website.com/images/pict.png it's like your loading
www.your-website.com/img.php?q=100&src=/images/pict.png
hope you like this! & sorry if i couldn't explaing well because my english is not good. :D
What do you mean by optimize? If you wish to keep the dimensions but reduce the size, take a look at imageJpeg for an example, and specifically the third argument (quality). Consider 100 to be perfect quality, and start decreasing it to find an optimal balance between quality and size.
very simple one is here too:
just change quality value (60) from 1 to 100, as you wish.
after execution of script, look at the filesize, and thats way, define your optimal quality value.
source
Related
I use imagick for thumbnail crop, but sometimes cropped thumbnails are missing top part of the images (hair, eyes).
I was thinking to resize the image then crop it. Also, I need to keep the image size ratio.
Below is the php script I use for crop:
$im = new imagick( "img/20130815233205-8.jpg" );
$im->cropThumbnailImage( 80, 80 );
$im->writeImage( "thumb/th_80x80_test.jpg" );
echo '<img src="thumb/th_80x80_test.jpg">';
Thanks..
This task is not easy as the "important" part may not always be at the same place. Still, using something like this
$im = new imagick("c:\\temp\\523764_169105429888246_1540489537_n.jpg");
$imageprops = $im->getImageGeometry();
$width = $imageprops['width'];
$height = $imageprops['height'];
if($width > $height){
$newHeight = 80;
$newWidth = (80 / $height) * $width;
}else{
$newWidth = 80;
$newHeight = (80 / $width) * $height;
}
$im->resizeImage($newWidth,$newHeight, imagick::FILTER_LANCZOS, 0.9, true);
$im->cropImage (80,80,0,0);
$im->writeImage( "D:\\xampp\\htdocs\\th_80x80_test.jpg" );
echo '<img src="th_80x80_test.jpg">';
(tested)
should work. The cropImage parameters (0 and 0) determine the upper left corner of the cropping area. So playing with these gives you differnt results of what stays in the image.
Based on Martin's answer I made a more general function that resizes and crops Imagick image to fit given width and height (i.e. behaves exactly as CSS background-size: cover declaration):
/**
* Resizes and crops $image to fit provided $width and $height.
*
* #param \Imagick $image
* Image to change.
* #param int $width
* New desired width.
* #param int $height
* New desired height.
*/
function image_cover(Imagick $image, $width, $height) {
$ratio = $width / $height;
// Original image dimensions.
$old_width = $image->getImageWidth();
$old_height = $image->getImageHeight();
$old_ratio = $old_width / $old_height;
// Determine new image dimensions to scale to.
// Also determine cropping coordinates.
if ($ratio > $old_ratio) {
$new_width = $width;
$new_height = $width / $old_width * $old_height;
$crop_x = 0;
$crop_y = intval(($new_height - $height) / 2);
}
else {
$new_width = $height / $old_height * $old_width;
$new_height = $height;
$crop_x = intval(($new_width - $width) / 2);
$crop_y = 0;
}
// Scale image to fit minimal of provided dimensions.
$image->resizeImage($new_width, $new_height, imagick::FILTER_LANCZOS, 0.9, true);
// Now crop image to exactly fit provided dimensions.
$image->cropImage($new_width, $new_height, $crop_x, $crop_y);
}
Hope this may help somebody.
My code. Please vote
// Imagick
$image = new Imagick($img);
// method 1 - resize to max width
if($type==1){
$image->resizeImage($newWidth,0,Imagick::FILTER_LANCZOS,1);
// method 2 - resize to max height
}else if($type==2){
$image->resizeImage(0,$newHeight,Imagick::FILTER_LANCZOS,1);
// method 1 - resize to max width or height
}else if($type==3){
if($image->getImageHeight() <= $image->getImageWidth()){
$image->resizeImage($newWidth,0,Imagick::FILTER_LANCZOS,1);
}else{
$image->resizeImage(0,$newHeight,Imagick::FILTER_LANCZOS,1);
}
// method 4 - resize and crop to center
}else if($type==4){
if($image->getImageHeight() <= $image->getImageWidth()){
$image->resizeImage(0,$newheight,Imagick::FILTER_LANCZOS,1);
}else{
$image->resizeImage($newwidth,0,Imagick::FILTER_LANCZOS,1);
}
$cropWidth = $image->getImageWidth();
$cropHeight = $image->getImageHeight();
$image->cropimage(
$newwidth,
$newheight,
($cropWidth - $newwidth) / 2,
($cropHeight - $newheight) / 2
);
}
$image->setImageFormat("jpeg");
$image->setImageCompression(Imagick::COMPRESSION_JPEG);
$image->writeImages($newImg, true);
$image->clear();
$image->destroy();
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>";
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
For a website I run, users can upload pictures they've drawn to a gallery. We create a thumbnail and a small view of that image to display to other users (clicking the small view image shows the full sized image).
With this in mind, I created a very simple resize script. In most cases this script works perfectly. However, I've come across a single odd case in which the script messes up entirely.
When running the file http://img191.imageshack.us/img191/2268/935full.png (1641x3121) through the script (which creates one thumbnail with a max width or height of 150 and another of 400) we get a perfect thumbnail http://img267.imageshack.us/img267/5803/935thumb.png (78x150) and a small view image sized properly, but which is cut off and stretched http://img28.imageshack.us/img28/4002/935show.png (211 x 400).
With that in mind, my question is: Is this a problem in PHP or a logic error? And how can I fix it?
Thank you for your time. The code I use to create these thumbnails is below.
<?php
/**
* Creates a thumbnail for any type of pre-existing image. Always saves as PNG image
*
* #param string - The location of the pre-existing image.
* #param string - The location to save the thumbnail, including filename and extension.
* #param int - The Maximum Width, Default of 150
* #param int - The Maximum Height, Default of 150
* #return bool - Success of saving the thumbnail.
*/
function imagecreatethumbnail($file,$output,$max_width = 150,$max_height = 150)
{
$img = imagecreatefromstring(file_get_contents($file));
list($width, $height, $type, $attr) = getimagesize($file);
if($height > $max_height || $width > $max_width)
{
if($width > $height)
{
$thumb_width = $max_width;
$thumb_height = ceil(($height * $thumb_width)/$width);
}
else
{
$thumb_height = $max_height;
$thumb_width = ceil(($width * $thumb_height)/$height);
}
} else {
$thumb_width = $width;
$thumb_height = $height;
}
imagesavealpha($img,true);
$thumb = imagecreatetruecolor($thumb_width,$thumb_height);
imagesavealpha($thumb,true);
imagealphablending($thumb,false);
imagecopyresampled($thumb,$img,0,0,0,0,$thumb_width,$thumb_height,$width,$height);
$return = imagepng($thumb,$output);
imagedestroy($img);
imagedestroy($thumb);
return $return;
}
Try this library and tell me if the same occurs:
http://phpthumb.gxdlabs.com/
Have you tried removing the ceil() functions? The image functions will automatically convert floats to integers anyway.
EDIT:
See if this works:
if($width > $max_width && $height * $thumb_width / $width < $max_width)
{
$thumb_width = $max_width;
$thumb_height = $height * $thumb_width / $width;
}
elseif($height > $max_height && $width * $thumb_height / $height < $max_height)
{
$thumb_height = $max_height;
$thumb_width = $width * $thumb_height / $height;
}
else
{
$thumb_width = $width;
$thumb_height = $height;
}
This seems to be a bug in PHP.
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);
}