My code below creates the thumb but it is pretty grainy and although not black and white looks pretty washed out.
Any ideas how I can create a better quality thumb?
$thumb = $targetPath."Thumbs/".$fileName;
$image = imagecreatefromjpeg($targetFile);
$width = 200; //New width of image
$height = 92; //This maintains proportions
$thumbWidth = 200;
$thumbHeight = 92;
$sourceImage = imagecreatefromjpeg($targetFile);
$targetImage = imagecreate($thumbWidth,$thumbHeight);
imagecopyresampled($targetImage,$sourceImage,0,0,0,0,$thumbWidth,$thumbHeight,imagesx($sourceImage),imagesy($sourceImage));
//imagejpeg($targetImage, "$thumbPath/$thumbName");
imagejpeg($targetImage, $thumb, 100);
chmod($thumb, 0755)
;
thanks R.
use imagick, it will give way better results http://lt.php.net/manual/en/function.imagick-thumbnailimage.php
Use this: ini_set("gd.jpeg_ignore_warning", 1);
Related
Usually, transparent goes black on the questions I found over the Internet. But for me it's the contrary.
I'm trying to split a big image in several ones. It works quite fine but the main problem is that the result can contain black color which is turned to transparent... Please Help ! :)
// I get the image to split and dimensions
$source = #imagecreatefrompng('images/'."full_to_split.png");
$source_width = imagesx( $source );
$source_height = imagesy( $source );
// Setting alpha for transparency
imageAlphaBlending($source, true);
imageSaveAlpha($source, true);
// I will split the image vertically by height of 100px
$width = $source_width;
$height = 100;
for( $row = 0; $row < $source_height / $height; $row++)
{
// I get the template image (a "part") which is a 100px height and full width of the source image
$fn_d = sprintf( 'images/'."part_%02d.png", $row+1 );
$destination = imagecreatefrompng($fn_d);
imagecopyresampled( $destination, $source, 0, 0,
0, $row * $height, $width, $height,
$width, $height );
imagepng( $destination, $fn_d );
imagedestroy( $destination );
}
Like this : my parts have transparent backgrounds (so this is perfect) but if there is a (true-)black "spot" in the full image this one is turned to transparent.
If I use the alpha blending on $destination I don't have anymore transparency (it goes black).
I tried with imagecopyresized and imagecopyresampled... It breaks my nerves :p
Thank you
Original colors
Result after split
full_to_split.png
part_01.png
part_02.png
part_03.png
I have an image file that is stored within the variable $image I want to resize this image so it would fit within an area of 380px by 380px (so which means that the tallest side of the image must be 380px on the other side smaller than 380px).
Has anyone a suggestion on how to do this?
Thanks
here is what I use to keep it under 800x600
$orig_image = imagecreatefromjpeg($file['tmp_name']);
list($width,$height) = getimagesize($file['tmp_name']);
if(max($width,$height) > 800){
$scale = 800/max($width,$height);
$new_width = floor($width*$scale);
$new_height = floor($height*$scale);
$save_image = imagecreatetruecolor($new_width,$new_height);
imagecopyresampled($save_image,$orig_image,0,0,0,0,$new_width,$new_height,$width,$height);
imagejpeg($save_image,self::$FILE_DIRECTORY."$year_month/$fileId.jpg");
$orig_image = $save_image;
$width = $new_width;
$height = $new_height;
}
hopefully you can extrapolate a solution off that.. also not that my $file variable is coming from an uploaded file in the $_FILE array.
I have made two GIFs to explain what I am trying to do. Where the grey border is the dimensions I am after (700*525). They are at the bottom of this question.
I want for all images that are larger than the given width and height to scale down to the border (from the centre) and then crop off the edges. Here is some code I have put together to attempt this:
if ($heightofimage => 700 && $widthofimage => 525){
if ($heightofimage > $widthofimage){
$widthofimage = 525;
$heightofimage = //scaled height.
//crop height to 700.
}
if ($heightofimage < $widthofimage){
$widthofimage = //scaled width.
$heightofimage = 700;
//crop width to 525.
}
}else{
echo "image too small";
}
Here are some GIFs that visually explain what I am trying to achieve:
GIF 1: Here the image proportions are too much in the x direction
GIF 2: Here the image proportions are too much in the y direction
image quality comparison for #timclutton
so I have used your method with PHP (click here to do your own test with the php) and then compared it to the original photo as you can see there is a big difference!:
Your PHP method:
(source: tragicclothing.co.uk)
The actual file:
(source: mujjo.com)
The below code should do what you want. I've not tested it extensively but it seems to work on the few test images I made. There's a niggling doubt at the back of mind that somewhere my math is wrong, but it's late and I can't see anything obvious.
Edit: It niggled enough I went through again and found the bug, which was that the crop wasn't in the middle of the image. Code replaced with working version.
In short: treat this as a starting point, not production-ready code!
<?php
// set image size constraints.
$target_w = 525;
$target_h = 700;
// get image.
$in = imagecreatefrompng('<path to your>.png');
// get image dimensions.
$w = imagesx($in);
$h = imagesy($in);
if ($w >= $target_w && $h >= $target_h) {
// get scales.
$x_scale = ($w / $target_w);
$y_scale = ($h / $target_h);
// create new image.
$out = imagecreatetruecolor($target_w, $target_h);
$new_w = $target_w;
$new_h = $target_h;
$src_x = 0;
$src_y = 0;
// compare scales to ensure we crop whichever is smaller: top/bottom or
// left/right.
if ($x_scale > $y_scale) {
$new_w = $w / $y_scale;
// see description of $src_y, below.
$src_x = (($new_w - $target_w) / 2) * $y_scale;
} else {
$new_h = $h / $x_scale;
// a bit tricky. crop is done by specifying coordinates to copy from in
// source image. so calculate how much to remove from new image and
// then scale that up to original. result is out by ~1px but good enough.
$src_y = (($new_h - $target_h) / 2) * $x_scale;
}
// given the right inputs, this takes care of crop and resize and gives
// back the new image. note that imagecopyresized() is possibly quicker, but
// imagecopyresampled() gives better quality.
imagecopyresampled($out, $in, 0, 0, $src_x, $src_y, $new_w, $new_h, $w, $h);
// output to browser.
header('Content-Type: image/png');
imagepng($out);
exit;
} else {
echo 'image too small';
}
?>
Using Imagick :
define('PHOTO_WIDTH_THUMB', 700);
define('PHOTO_HEIGHT_THUMB', 525);
$image = new Imagick();
$image->readImage($file_source);
$width = $image->getImageWidth();
$height = $image->getImageHeight();
if($width > $height){
$image->thumbnailImage(0, PHOTO_HEIGHT_THUMB);
}else{
$image->thumbnailImage(PHOTO_WIDTH_THUMB, 0);
}
$thumb_width = $image->getImageWidth();
$thumb_height = $image->getImageHeight();
$x = ($thumb_width - PHOTO_WIDTH_THUMB)/2;
$y = ($thumb_height - PHOTO_HEIGHT_THUMB)/2;
$image->cropImage(PHOTO_THUMB_WIDTH, PHOTO_THUMB_HEIGHT, $x, $y);
$image->writeImage($thumb_destination);
$image->clear();
$image->destroy();
unlink($file_source);
I have used GD library to accomplish the resize. Basically what I did is, I calculated the image dimension and then resized the image to dimension 700x525 from the center.
<?php
/*
* PHP GD
* resize an image using GD library
*/
//the image has 700X525 px ie 4:3 ratio
$src = 'demo_files/bobo.jpg';
// Get new sizes
list($width, $height) = getimagesize($src);
$x = 0;
$y = 0;
if($width < $height){
$newwidth = $width;
$newheight = 3/4 * $width;
$x = 0;
$y = $height/2 - $newheight/2;
}else{
$newheight = $height;
$newwidth = 4/3 * $height;
$x=$width/2 - $newwidth/2;
$y=0;
}
$targ_w = 700; //width of the image to be resized to
$targ_h = 525; ////height of the image to be resized to
$jpeg_quality = 90;
$img_r = imagecreatefromjpeg($src);
$dst_r = ImageCreateTrueColor( $targ_w, $targ_h );
imagecopyresampled($dst_r,$img_r,0,0,$x,$y,$targ_w,$targ_h,$newwidth,$newheight);
header('Content-type: image/jpeg');
imagejpeg($dst_r,null,$jpeg_quality);
exit;
?>
i used http://phpthumb.sourceforge.net to have a beutiful solution also with transparent curved edges.
this is an alternative route to solution, might suit someone's need with little configuration.
I'm generating thumbnail images from the original jpeg files when they are being uploaded. I could actually create and move those thumbnail files to another directory, but the problem is that those thumbnail files displays only the black color while uploading.
My code.
if(isset($_POST['upload'])){
$img = $_FILES['origin']['name'];
move_uploaded_file($_FILES['origin']['tmp_name'], 'image/'.$img);
define("SOURCE", 'image/');
define("DEST", 'thumb/');
define("MAXW", 120);
define("MAXH", 90);
$jpg = SOURCE.$img;
if($jpg){
list($width, $height, $type) = getimagesize($jpg); //$type will return the type of the image
if(MAXW >= $width && MAXH >= $height){
$ratio = 1;
}elseif($width > $height){
$ratio = MAXW / $width;
}else{
$ratio = MAXH / $height;
}
$thumb_width = round($width * $ratio); //get the smaller value from cal # floor()
$thumb_height = round($height * $ratio);
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
$path = DEST.$img."_thumb.jpg";
imagejpeg($thumb, $path);
echo "<img src='".$path."' alt='".$path."' />";
}
imagedestroy($thumb);
}
and the thumbnail file looks like this:
From php manual:
imagecreatetruecolor() returns an image identifier representing a black image of the specified size.
So the problem is that you actually create this black image and save it.
$thumb = imagecreatetruecolor($thumb_width, $thumb_height);
For solution on resizing, please refer to this question on stackoverflow.
Hmm, I just found my bug right now. The problem is that I use $jpg = SOURCE.$img; instead of $jpg = imagecreatefromjpeg($jpg); and also I need to copy the sample image to the new thumbnail image using
imagecopyresampled( $thumb, $jpg, 0, 0, 0, 0, $thumb_width, $thumb_height, $width, $height );
Then it works!!!
Thanks Alex for your answer which lead me to this solution.
I am creating thumbnails of fixed height and width from my PHP script using the following function
/*creates thumbnail of required dimensions*/
function createThumbnailofSize($sourcefilepath,$destdir,$reqwidth,$reqheight,$aspectratio=false)
{
/*
* $sourcefilepath = absolute source file path of jpeg
* $destdir = absolute path of destination directory of thumbnail ending with "/"
*/
$thumbWidth = $reqwidth; /*pixels*/
$filename = split("[/\\]",$sourcefilepath);
$filename = $filename[count($filename)-1];
$thumbnail_path = $destdir.$filename;
$image_file = $sourcefilepath;
$img = imagecreatefromjpeg($image_file);
$width = imagesx( $img );
$height = imagesy( $img );
// calculate thumbnail size
$new_width = $thumbWidth;
if($aspectratio==true)
{
$new_height = floor( $height * ( $thumbWidth / $width ) );
}
else
{
$new_height = $reqheight;
}
// create a new temporary image
$tmp_img = imagecreatetruecolor( $new_width, $new_height );
// copy and resize old image into new image
imagecopyresized( $tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height );
// save thumbnail into a file
$returnvalue = imagejpeg($tmp_img,$thumbnail_path);
imagedestroy($img);
return $returnvalue;
}
and I call this function with following parameters
createThumbnailofSize($sourcefilepath,$destdir,48,48,false);
but the problem is the resulting image is of very poor quality, when I perform the same operation with Adobe Photo shop, it performs a good conversion.. why it is so? I am unable to find any quality parameter, through which I change the quality of output image..
Use imagecopyresampled() instead of imagecopyresized().
if it is image quality you are after you need to give the quality parameter when you save the image using imagejpeg($tmp_img,$thumbnail_path,100) //default value is 75
/*creates thumbnail of required dimensions*/
function
createThumbnailofSize($sourcefilepath,$destdir,$reqwidth,$reqheight,$aspectratio=false)
{
/*
* $sourcefilepath = absolute source file path of jpeg
* $destdir = absolute path of destination directory of thumbnail ending with "/"
*/
$thumbWidth = $reqwidth; /*pixels*/
$filename = split("[/\\]",$sourcefilepath);
$filename = $filename[count($filename)-1];
$thumbnail_path = $destdir.$filename;
$image_file = $sourcefilepath;
$img = imagecreatefromjpeg($image_file);
$width = imagesx( $img );
$height = imagesy( $img );
// calculate thumbnail size
$new_width = $thumbWidth;
if($aspectratio==true)
{
$new_height = floor( $height * ( $thumbWidth / $width ) );
}
else
{
$new_height = $reqheight;
}
// create a new temporary image
$tmp_img = imagecreatetruecolor( $new_width, $new_height );
// copy and resize old image into new image
imagecopyresized( $tmp_img, $img, 0, 0, 0, 0, $new_width, $new_height, $width, $height );
// save thumbnail into a file
$returnvalue = imagejpeg($tmp_img,$thumbnail_path,100);
imagedestroy($img);
return $returnvalue;
}
You could also consider using ImageMagick (http://us3.php.net/manual/en/book.imagick.php) instead of Gd. I had the same problem just a couple of days ago with Java. Going for ImageMagick instead of Java Advanced Images resultet in a huge quality difference.
tried using the php.Thumbnailer ?
$thumb=new Thumbnailer("photo.jpg");
$thumb->thumbSquare(48)->save("thumb.jpg");
Result photo will be 48x48px. Easy right? :)
You might also want to take a look at the Image_Transform PEAR package. It takes care of a lot of the low-level details for you and makes creating and manipulating images painless. It also lets you use either GD or ImageMagick libraries. I've used it with great success on several projects.