Resizing images with GD without color loss - php

I'm trying to resize an image with GD and am seeing a color loss on the resized image. Here is my code:
$src = imagecreatefromstring(file_get_contents($source));
ImageCopyResized($dst, $src, 0, 0, 0, 0, $t_width, $t_height, ImageSX($src), ImageSY($src));
Imagejpeg($dst, $dest, 90);

Are you using imagecreatetruecolor when declaring $dst?

The right way to do this is:
$dst = imagecreatetruecolor($width, $height);
$image = imagecreatefromjpeg($filename);
imagecopyresampled($dst, $image, 0, 0, 0, 0, $width, $height, $width_orig, $height_orig);

Related

Black color at cropped borders when using it in gdi, but looks transparent in photo editor

Borrowed this code to circle crop an image output.
// create the transparent circle image
$filename = APP_WEB_PATH."img/user/".$_GET['img'].".jpg";
$imagefilenamepng = APP_WEB_PATH."img/user/".$_GET['img']."_c.png";
$image_s = imagecreatefromstring(file_get_contents($filename));
$width = imagesx($image_s);
$height = imagesy($image_s);
$newwidth = 300;
$newheight = 300;
$image = imagecreatetruecolor($newwidth, $newheight);
imagealphablending($image, true);
imagecopyresampled($image, $image_s, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);
//create masking
$mask = imagecreatetruecolor($newwidth, $newheight);
$transparent = imagecolorallocate($mask, 255, 0, 0);
imagecolortransparent($mask,$transparent);
imagefilledellipse($mask, $newwidth/2, $newheight/2, $newwidth, $newheight, $transparent);
$red = imagecolorallocate($mask, 0, 0, 0);
imagecopymerge($image, $mask, 0, 0, 0, 0, $newwidth, $newheight, 100);
imagecolortransparent($image,$red);
imagefill($image, 0, 0, $red);
imagepng($image,$imagefilenamepng);
imagedestroy($image);
imagedestroy($mask);
The image looks good and transparent and even when opened with a photo editor
but when used inside an image using php GDI i get a black border instead of transparent
what am I missing here.. (if I use paint.net image editor and re-save the image, then it works fine..) the below image works fine after saving in the photo editor
I use the code to call it as
self::$im = imagecreatefromjpeg($imgname1);
$im2 = imagecreatefrompng($imgname2);
$sx = imagesx($im2)*$scale;
$sy = imagesy($im2)*$scale;
$stamp = imagescale($im2, $sx);
imagecopy(self::$im, $stamp, $xcord, $ycord, 0, 0, $sx, $sy);
here self::$im is the larger image, and $im2 is the one that is cropped

upload converted imagejpeg to server

This is a function that creates a .jpg file from an uploaded .png file.
$input_file = 'img/uploaded/'.$_SESSION['userid'].'-'.$_SESSION['username'].'.png';
$output_file = 'img/uploaded/'.$_SESSION['userid'].'-'.$_SESSION['username'].'.jpg';
$input = imagecreatefrompng($input_file);
list($width, $height) = getimagesize($input_file);
$output = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($output, 255, 255, 255);
imagefilledrectangle($output, 0, 0, $width, $height, $white);
imagecopy($output, $input, 0, 0, 0, 0, $width, $height);
imagejpeg($output, $output_file);
What I would like to know is how to define a custom "quality" or compression-rate for the new JPEG image. In some other conversion-functions there is a possibility to choose between 0(max compression) and 100(max quality). Does anybody know how to do this in my case?
The last parameter of imagejpeg() is "quality":
This should set it to max quality:
imagejpeg($output, $output_file, 100);
For more info. check this out:
http://php.net/manual/en/function.imagejpeg.php

PHP GD Complex stacking multiple layers

I have an image stacking process that I am trying to accomplish with PHP GD. What I have is the following:
3 Images:
Masked clipart
Clipart texture
Final background
My masked clipart has black in place of where transparency will be after the texture is applied to the clipart and is transparent for layering over a texture.
The following code sorta works for this:
$im = imagecreatetruecolor($width,$height);
imagecopy($im, $texture, 0, 0, 0, 0, $width, $height);
imagecopy($im, $clipart, 0, 0, 0, 0, $width, $height);
imagecolortransparent($im, imagecolorclosest($clipart, 0, 0, 0));
Output is an image with transparent background and the clipart with the texture applied.
However, when I open that file in photoshop, the transparent areas are black which also brings me to the rest of this function:
Now that I have this image, I need to layer it on top of the "Final background" image which will make all the transparency of the previous output now be this "Final background" texture. My thoughts were something like:
$im = imagecreatetruecolor($width,$height);
imagecopy($im, $texture, 0, 0, 0, 0, $width, $height);
imagecopy($im, $clipart, 0, 0, 0, 0, $width, $height);
imagecolortransparent($im, imagecolorclosest($clipart, 0, 0, 0));
$img = imagecreatetruecolor($width,$height);
imagecopy($img, $background, 0, 0, 0, 0, $width, $height);
imagecopy($img, $im, 0, 0, 0, 0, $width, $height);
imagedestroy($im);
return $img;
The problem with this is that is outputs the image with a black background instead of my final texture layer. I believe this code for the final layering may actually work fine and that the black background from the final output and in photoshop is from missing some alpha line in the first part. I have tried to play around with:
imagealphablending( $im, false );
imagesavealpha( $im, true );
Mixing and matching the true / false and alternating only using one of them didn't seem to matter.
If anyone could shed some light on my mistakes here, it would be greatly appreciated.
UPDATE
The images: http://imgur.com/a/7SN1S
The code:
// Layer clipart over texture and convert black to transparent (works)
$im = imagecreatetruecolor($width,$height);
imagecopy($im, $texture, 0, 0, 0, 0, $width, $height);
imagecopy($im, $clipart, 0, 0, 0, 0, $width, $height);
imagecolortransparent($im, imagecolorclosest($clipart, 0, 0, 0));
// Layer above image with transparency over background (non-working)
$img = imagecreatetruecolor($width,$height);
imagecopy($img, $background, 0, 0, 0, 0, $width, $height);
imagecopy($img, $im, 0, 0, 0, 0, $width, $height);
header('Content-Type: image/png');
//imagepng($im); // Correctly outputs first step
imagejpeg($img); // Incorrectly outputs final result
imagedestroy($im);
imagedestroy($img);
As noted on the imagecolortransparent() manual page:
Transparency is copied only with imagecopymerge() and true color images, not with imagecopy() or pallete images.
So, changing the following two lines (16 & 17 in index.php)...
imagecopy($img, $background, 0, 0, 0, 0, $width, $height);
imagecopy($img, $im, 0, 0, 0, 0, $width, $height);
...to this...
imagecopymerge($img, $background, 0, 0, 0, 0, $width, $height, 100);
imagecopymerge($img, $im, 0, 0, 0, 0, $width, $height, 100);
...gives (very close to) the desired result:

Resize image doesn't work with PHP-GD

Following my code:
list($width, $height) = getimagesize("dir");
$src = imagecreatefromjpeg("dir");
$im = imagecreatetruecolor(300, 300);
imagecopyresampled($im, $src, 0, 0, 0, 0, 300, 300, $width, $height);
imagejpeg($src, 'img.jpg');
It saves the image, but with the same size of originary image and not 300x300. How to solve?
You have used wrong image handler with imagejpeg function. Use:
imagejpeg($im, 'img.jpg');

PHP resizing working for PNGs and JPGs but not GIFs

I have a script that resizes uploaded images. It works fine for PNGs and JPGs but not GIFs. For the GIFs, it's supposed to convert them into JPGs and then resize them. The conversion works, but then they fail to be resized...
function resize_image($file, $maxWidth, $maxHeight) {
$jpgFile = substr_replace($file, 'jpeg', -3);
$fileType = strtolower(substr($file, -3));
...
if ($fileType == 'gif') {
$test = imagecreatefromgif($file);
imagejpeg($test, $jpgFile);
$src = imagecreatefromjpeg($jpgFile);
$dst = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagejpeg($dst, $jpgfile);
}
}
I don't think you need to output the image after it's created from a gif - imagecreatefromgif reads an image into memory, you should be able to do this:
$src = imagecreatefromgif($file);
$dst = imagecreatetruecolor($newWidth, $newHeight);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagejpeg($dst, $jpgfile);
What version of the GD library are you using? According to the official PHP documentation:
GIF support was removed from the GD library in Version 1.6, and added
back in Version 2.0.28. This function is not available between these
versions.
I ended up bypassing the conversion of GIF to JPG, and resized the GIF directly. However, to maintain the transparency (by default it turns the transparent background to black, which is the reason I originally converted it to JPG first before resizing), I had to add in a few instructions.
$src = imagecreatefromgif($file);
$dst = imagecreatetruecolor($newWidth, $newHeight);
imagecolortransparent($dst, imagecolorallocatealpha($dst, 0, 0, 0, 127));
imagealphablending($dst, false);
imagesavealpha($dst, true);
imagecopyresampled($dst, $src, 0, 0, 0, 0, $newWidth, $newHeight, $width, $height);
imagegif($dst, $file);

Categories