PHP GD poor thumb quality - php

$tmp_im = imagecreatetruecolor($width, $height);
$x = $this->getX();
$y = $this->getY();
$w = floor($resize_height * ($x / $y));
$h = $resize_height;
$this->tmp_im = imagecreatetruecolor($w, $h);
imagealphablending($this->tmp_im, false);
imagesavealpha($this->tmp_im, true);
imagecopyresampled($this->tmp_im, $this->im, 0, 0, 0, 0, $w, $h, $this->getX(), $this->getY());
$this->im = $this->tmp_im;
$hs = floor(($width - $this->getX())/2);
$vs = floor(($height - $this->getY())/2);
imagecopy($tmp_im, $this->im, $hs, $vs, 0, 0, $this->getX(), $this->getY());
$this->im = $tmp_im;
the results is a poor quality resized image, what im doing wrong? i also tried to use a imagejpeg with quality = 100

Use imagecopytruecolor() instead of
imagecopy($tmp_im, $this->im, $hs, $vs, 0, 0, $this->getX(), $this->getY());
This is a Notice on the official PHP documentation page:
There is a problem due to palette image limitations (255+1 colors).
Resampling or filtering an image commonly needs more colors than 255,
a kind of approximation is used to calculate the new resampled pixel
and its color. With a palette image we try to allocate a new color, if
that failed, we choose the closest (in theory) computed color. This is
not always the closest visual color. That may produce a weird result,
like blank (or visually blank) images. To skip this problem, please
use a truecolor image as a destination image, such as one created by
imagecreatetruecolor().

Related

PHP GD : Can i just fill transparent part?

There is an image which has transparent area. (png image)
Now, while doing a imagecopy, can we just fill that transparent area?
Imagemagick can do this easily. Is that possible in php gd?
A layered approach via imagecopymerge() is one route. The concept is to merge your source image onto a new image, with a pre-set background image, which will show through the source image's transparency once merged.
//create main image - transparent, with opaque red square in middle
$img = imagecreate(60, 60);
$white = imagecolorallocate($img, 255, 255, 255);
imagecolortransparent($img, $white); //make background transparent
$red = imagecolorallocate($img, 255, 0, 0);
imagefilledrectangle($img, imagesx($img) / 4, imagesy($img) / 4, imagesx($img) - (imagesx($img) / 4), imagesy($img) - (imagesy($img) / 4), $red);
//create new image, with pre-filled background, then merge first image across
$img2 = imagecreate(60, 60);
$blue = imagecolorallocate($img2, 0, 0, 255);
imagecopymerge($img2, $img, 0, 0, 0, 0, imagesx($img), imagesy($img), 100);
//output
imagepng($img2);
So the first image creates a transparent image (the white) with a red square in the middle. The second image is simply a blue fill.Merge the two, and the blue shows through the transparent part of the first image, so our red square now sits on the blue fill. Effectively, we've filled the transparent part.
Here's the three states in sequence.
There is nothing to 'fill' where there is transparency. Transparency in a png (or gif) is not the absence of a color, but a single color specifically marked to be shown as transparent. Therefore you want to remove that marker.
Take a look at the php gds function 'imagecolortransparent':
Nope, you can't.
Instead that, you can try to create a copy from a colored rectangle. This code worked for me:
$input = imagecreatefrompng($file_input);
list($width, $height) = getimagesize($file_input);
$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);
imagepng($output, $file_output);

Merge images with PHP

I have written a code for merge two images.
My code is:
$rnd = rand("99000", "99999");
$dst_path = "/home/maxioutl/public_html/images/urunler/";
$dst_file_name = "tresim-{$rnd}.jpg";
$dst_file = $dst_path.$dst_file_name;
$dst = imagecreatetruecolor(250, 375);
imagefill($dst, 0, 0, imagecolorallocate($dst, 255, 255, 255));
$src = imagecreatefromjpeg("http://www.goldstore.com.tr/upload/product/raw/3.72925.0332.JPG");
imagecopymerge($dst, $src, 40, 60, 0, 0, 250, 375, 100);
imagejpeg($dst, $dst_file, 90);
Result:
Black background. Where is it?
It's the imagecopymerge($dst, $src, 40, 60, 0, 0, 250, 375, 100); statement that's doing it.
You're passing it the dimensions 250x375, which isn't the watch's actual dimensions. Therefore the merge bounding box continues on and it uses black. You can see this easily if you comment it out because you'll get your white square from the fill like you were expecting.
you need to get the exact dimensions of your watch graphic (i.e. through getimagesize) and pass those to imagecopymerge so it cuts it exactly when it merges.
$arrSize = getimagesize($originalFile);
imagecopymerge($dst, $src, 40, 60, 0, 0, $arrSize[0], $arrSize[1], 100);
The code you wrote superimposes the images. It does not remove the white pixels from the image with the watch.
They are basically overlapped.
You should cycle through both image dimensions and replace each *white pixel with a black pixel or a transparent pixel.
*white pixel may not necessarily mean rgb(255,255,255) you can choose to treat all pixels with rgb(>235,>235,>235) as being "white".
Function imagecreatetruecolor creates completely black image
Taken from here :
imagecreatetruecolor() returns an image identifier representing a
black image of the specified size.

ImageGD not filling correctly

Hay, I'm using this code to generate an image and fill it with a gray colour.
$canvas = imagecreatetruecolor(100, 100);
$gray = imagecolorallocate($canvas, 0xEE, 0xEE, 0xEE);
imagefill($canvas, 0, 0, $gray);
imagegif($canvas);
This works fine, but if i change the canvas size to a 'long' image, it fails to fill.
$canvas = imagecreatetruecolor(1, 100);
Is this a common bug? Or do i need some other option? How do i fill the whole canvas?
Looks like a bug. I confirm the same behavior. It fills only top 2 pixels, if you specify the width to be 1. The similar for 2 or 3. 4 seems like a magic value - it begins to work there.
On the other hand this bug doesn't seem to appear if you use a 1px-high image, i.e. I tried this and it worked as expected:
$canvas = imagecreatetruecolor(100, 1);
$red = imagecolorallocate($canvas, 0xEE, 0, 0);
imagefill($canvas, 0, 0, $red);
imagegif($canvas, "output.png");
So this might be a kind of a workaround.

Set a color as transparent in palette-based image

I want to convert a alpha transparent png image to palette based png image.
In GD I can do it easy:
// We have already the image loaded in $source_img
$w=200; $h=200; // We supose that img dimensions are 200x200
$img = imagecreatetruecolor($w, $h); // New black image
list($r, $g, $b) = array(200, 200, 200); // Some color that doesn't appear in image to avoid conflict
$color = imagecolorallocate($img, $r, $g, $b);
imagefill($img, 0, 0, $color); // Fill the black image with the chosen color.
imagecolortransparent($img, $color); // Set the chosen color as transparent
$res = imagecopyresampled($img, $source_img, 0, 0, 0, 0, $w, $h, $w, $h);
But in Imagick I don't know how set a color as transparent (imagecolortransparent() in GD). I have spent hours searching on the internet, but the help in the php site isn't very comphrensive and there are many undocumented functions.
Thanks.
On the command line I would do something like this:
convert test.png -transparent-color white PNG8:converted.png
But there seems to be a problem in some IM versions with this type of conversion, I found this usergroup post by some guy who seems to have similiar problems: http://studio.imagemagick.org/pipermail/magick-users/2009-May/022534.html
Are you using the command line when working with IM or do you use the PHP module ( http://de.php.net/manual/en/book.imagick.php )?

PHP/GD Gaussian Blur Effect

I need to obfuscate a certain area of an image using PHP and GD, currently I'm using the following code:
for ($x = $_GET['x1']; $x < $_GET['x2']; $x += $pixel)
{
for ($y = $_GET['y1']; $y < $_GET['y2']; $y += $pixel)
{
ImageFilledRectangle($image, $x, $y, $x + $pixel - 1, $y + $pixel - 1, ImageColorAt($image, $x, $y));
}
}
This basically replaces the selected area with squares of $pixel pixels. I want to accomplish some kind of blur (gaussian preferably) effect, I know I can use the ImageFilter() function:
ImageFilter($image, IMG_FILTER_GAUSSIAN_BLUR);
But it blurs the entire canvas, my problem is that I just want to blur a specific area.
You can copy a specific part of the image into a new image, apply the blur on the new image and copy the result back.
Sort of like this:
$image2 = imagecreate($width, $height);
imagecopy ( $image2 , $image , 0 , 0 , $x , $y , $width , $height);
imagefilter($image, IMG_FILTER_GAUSSIAN_BLUR);
imagecopy ($image, $image2, $x, $y, 0, 0, $width, $height);
I did not check the documentation for imagefilter and I don't know if this is impossible or if there is an equivalent to applying this to (a part) of an image. But assuming there isn't, why not:
Copy the part you want to blur to a new (temporary) GD image (no need to write it to disk, just assign it to a new temp variable).
Apply gaussian blur filter to this temporary image.
Copy the resulting (filtered) image right back where it came from (functionality to do this is definitely in the GD library)

Categories