PHP GD imagecopyresampled horrible quality - php

Not sure why it looks so bad, but when I copy an image over another image, it looks extremely terrible, like it lost almost all its colors for some reason.
$img = imagecreate(240, 140);
$wall = imagecreatefrompng($src);
imagecopyresampled($img, $wall, 0, 0, 40, 340, 240, 140, 240, 140);
I've been trying to find a solution myself but I can't seem to find one, anybody really good with GD that can help? I can't use imagemagick.

You need to create your canvas image with imagecreatetruecolor() rather than imagecreate() as the former creates a palette based canvas with limited colour support.
I presume you are then using imagepng() to save our output the image. The third argument accepted by this function defines the quality of the image, or the compression level (0-9)

Related

PHP GD and transparent images sometimes work

While reading up on the issues merging transparent images in PHP, it seems that everyone is in the "it works" or "it doesn't work" camps. I have found a way to demonstrate each case.
I wish to take a PNG, cut an ALPHA hole in it and then merge it on top of another image. In this case, I cut a hole in an image from google maps, and paste it over a red block. I have two images from google maps. One is of Manhattan and one is of my house. One works, and one does not. The only difference is one was "saved" via a browser.
If you run the code below, you will see the difference in outputs. Does anyone know why the same code would treat two PNG files completely differently? It must be the difference in the PNG files themselves, but then what would it be?
<?php
sometimesworks("https://maps.googleapis.com/maps/api/staticmap?center=40.714728,-73.998672&zoom=12&size=400x400&maptype=hybrid", "google");
sometimesworks("https://lh4.googleusercontent.com/UQvV_dpBa3_rVf25pvLXKD3OwzF4FtPnHBHkzdWqjCQ5mlFqcFfId9echIgDMv_xYRRYzLaKEXphw7g=w2447-h1106", "myhouse");
function sometimesworks($p_image, $p_prefix)
{
$image_top =imagecreatefrompng($p_image);
$brush = imagecolorallocate($image_top, 0, 0, 0); //create a black brush
imagefilledpolygon($image_top, explode(",", "10,10, 120,22, 80,280, 200, 191"), 4, $brush); //fill a polygon
imagecolortransparent($image_top, $brush); //turn the black to be transparent
imagepng($image_top, './'.$p_prefix.'.transparent.png'); //save the file to confirm that it is working.
//create a big red square
$image_bottom = imagecreatetruecolor(imagesx($image_top), imagesy($image_top));
$red = imagecolorallocate($image_bottom, 255, 0, 0);
imagefill($image_bottom, 0, 0, $red);
imagepng($image_bottom, './'.$p_prefix.'.red.png');
//merge the top onto the bottom.
$out = imagecreatetruecolor(imagesx($image_top), imagesy($image_top));
imagecopy($out, $image_bottom, 0, 0, 0, 0, imagesx($image_top), imagesy($image_top));
imagecopy($out, $image_top, 0, 0, 0, 0, imagesx($image_top), imagesy($image_top));
imagepng($out, './'.$p_prefix.'.out.png');
}
The issue with the above code is that the PNG files were of different type. One was a truecolor image and the other was a palette. The code to merge files differs depending on what is being done.
This is a good reference for the merging of "palette" based PNG files with transparency.

PHP Image manipulation moire effect

I am making a site where people can upload their own background images. One of the things users really having a problem understanding is image sizes and resolution. If I say 'Make sure your background is at least 1080x1920 pixels (Full HiDef)' I am guessing a good 70% of people will not know what this means or how to do it.
So what I would like to do is enlarge small images in a nicer way than just making them blurry. What I would like to do is something like this:-
http://nanotux.com/plugins/fullscreenr/index.html
where basically every other dot is a black pixel, that way small images will be twice the size when they are stretched to 1080x1920 and generally look better.
Does anyone know of a way to do this with PHP's image functions?
(as an aside does anyone know what this type of effect should be called? Moire? would that be accurate?)
Thanks in advance
If I understood you well, you want to set every second pixel in x and y dimensions to black on the stretched image?
This should do the trick (not tested, I relied on PHP documentation).
$initialImage = ... // handle to the image
$srcWidth = imagesx($initialImage);
$srcHeight = imagesy($initialImage);
$maxX = 1920;
$maxY = 1080;
$newImage = imagecreatetruecolor($max_x, $max_y);
imagecopyresampled ($newImage, $initialImage, 0,0,0,0, $maxX, $maxY, $srcWidth, $srcHeight);
$BLACK = imagecolorallocate($newImage, 0, 0, 0);
for($x=0; $x+=2; $x<$max_x){
for($y=0; $y+=2; $y<$max_y){
imagesetpixel($newImage, $x, $y, $BLACK);
}
}
Documentation: imagesetpixel, imagecolorallocate, imagecopyresampled,
imagecreatetruecolor.
Read PHP documentation and examples there. Remember to use imagecopyresampled instead of imagecopyresized to have better quality.
The most optimal way would be to create a transparent raster (.png) "by hand" (i.e. create it programmatically as in jakub.gieryluk's solution), and overlay that, multiple times if needed, via imagecopy().
Drawing pixel by pixel is painfully slow.

How to correctly resize png images

I use the following combination of functions
$img_r = imagecreatefrompng($src);
$dst_1 = imagecreate( $targ_w_1, $targ_h_1 );
imagecopyresampled($dst_1,$img_r,0,0,0,0,$targ_w_1,$targ_h_1,$size_test[0],$size_test[1]);
imagepng($dst_1, $final_source_1,9);
Final result comes with very low quality, as I understand imagepng max quality is 9. You cannot write 100 there. But still quality is very bad. maybe I use wrong functions to manipulate with image ? Any suggestions ?
original 220x220 image
resized image to size 120x120
resized image with the same size 220x220
SOLVED
Look in the manual. It has this to say on imagepng()'s $quality parameter:
Compression level: from 0 (no compression) to 9.
So 9 seems to be the worst quality level. Try a lower setting.
As far as I know, there is no such thing as a quality setting in the PNG-format, nor in the underlying c-library. There is compression, but since PNG is a loss-less format, compressing the image does not degenerate the quality.
The compression setting of 9 gives the best compression (=smallest file size).
The issue you run into likely is that your destination image is created with imagecreate(); a paletted image.
You are more likely looking for imagecreatetruecolor()
Problem was with alpha . After I read Jaccos comment I went to google and found this
imagealphablending($dst_1, false);
imagesavealpha($dst_1,true);
$transparent = imagecolorallocatealpha($dst_1, 255, 255, 255, 127);
imagefilledrectangle($dst_1, 0, 0,$targ_w_1, $targ_h_1, $transparent);
This peace of code must be put right after imagecreatetruecolor ad everything will be just fine :)

Open a GIF image, increase the 'canvas' by 100 pixels

Hay, I want to use PHP's GD library to open a GIF image and increase the canvas's height by 100 pixels, then fill the new space with the hex colour #EEEEEE.
Does anyone have any idea how i would do this?
Get the original size with getimagesize
Use imagecreate to create your "new" image with the desired size
Fill the new image with #eeeeee using imagecolorallocate (see note)
Use imagecopy to copy your original image into the new one
If your question is "Does anyone have any idea how i would do this?" Then the answer is yes. Most probably someone have an idea how you could do it. :)
Otherwise this should do the trick:
$image = imagecreatefromgif('file.gif');
list($imageWidth, $imageHeight) = getimagesize('file.gif');
$newimage=imagecreatetruecolor($imageWidth, $imageHeight+100);
$gray=imagecolorallocate($newimage, 0xEE, 0xEE, 0xEE);
imagefill($newimage,0,0,$gray);
imagecopy($newimage, $image, 0, 0, 0, 0, imageWidth, $imageHeight);
imagegif($newimage,'newimage.gif');

ImageTrueColorToPalette losing colors

I have a PHP script that converts true color images to palette images if the number of different colors in the image is less than or equal to 256.
In my test case, I have an image that contains 79 colors. After running ImageTrueColorToPalette on it without dither and the $ncolors parameter set to 79, I have an image that only has 15 colors in it. I have even tried running ImageColorMatch on it after converting it to palette, and I still end up with only 15 colors.
Using GD in PHP, how can I convert my true color image to a palette image without losing all of those colors?
It appears I can convert the true color image to a palette image by creating a palette image using ImageCreate and then copying the true color image to that one. This produces much better results than ImageTrueColorToPalette.
Why ImageTrueColorToPalette gives me a crappy looking image, I'm not really sure, but this seems like an adequate workaround.
$palette = ImageCreate($width, $height);
ImageCopy($palette, $truecolor, 0, 0, 0, 0, $width, $height);

Categories