ImageTrueColorToPalette losing colors - php

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);

Related

ImageMagick / Imagick: Convert a PNG with Alpha channel into a 2 color image (Color, Transparent)

I would like to know and find out, how I can colorize/replace any pixel of an image, that is not (fully) transparent with an opaque pixel.
For example, having a multicolored Logo with transparent pixels, I would like to convert it in to a logo with only the color #ff0000, and not change the transparent background.
I want to achieve this with the PHP Imagick Library. I cannot find any good documentation.
I thought that Imagick::thresholdImage would be a helper, but there is no documentation about the threshold parameter.
Best results are achieved with this fragment of code. But still not working perfectly. Some pixels - i guess those with alpha > 0 and < 1 are not replaced.
$image = new \Imagick($source);
$image->setImageFormat('png');
$fill = new \ImagickPixel('#ff0000');
$image->thresholdImage(0);
$image->paintOpaqueImage('#ffffff', $fill, 1);
$image->writeImage($destination);
I would like to know and find out, how I can colorize/replace any pixel of an image, that is not (fully) transparent with an opaque pixel.
You almost certainly don't.
The code below does what you are asking (I think) and the output looks terrible. Perhaps you should give an example input image, and a hoped for example output image, that you have edited in Photoshop, to show what you were hoping for.
Input image:
Output image:
$imagick = new Imagick("fnord.png");
// Get the alpha channel of the original image.
$imagick->separateImageChannel(\Imagick::CHANNEL_ALPHA);
// Make all the colors above this pure white.
$imagick->whiteThresholdImage("rgb(254, 254, 254)");
// Make all the colors below this pure black.
$imagick->blackThresholdImage("rgb(254, 254, 254)");
// We want the mask the other way round
$imagick->negateImage(false);
$imagickCanvas = new \Imagick();
$imagickCanvas->newPseudoImage(
$imagick->getImageWidth(),
$imagick->getImageHeight(),
"xc:rgb(255, 0, 0)"
);
// Copy the mask back as the alpha channel.
$imagickCanvas->compositeImage($imagick, \Imagick::COMPOSITE_COPYOPACITY, 0, 0);
// Write out the image.
$imagickCanvas->setImageFormat('png');
$imagickCanvas->writeImage("./output.png");

image resizing in PHP

While i was doing some image processing, i found out that GD and Imagick in PHP does not resize image to color pixel identical level, which in most cases, were not needed.
Now in case, i need a image from whatever dimension to scale to 256*256
To make sure the TEST results are consistent, i used a 256*256 image and resize it to it's own size.
what i've attempted:
imagecopyresized($new, $img, 0, 0, $x, 0, $width, $height, $w, $h); //256 , 256
and
$compression_type = imagick::COMPRESSION_NO;
$images_ima = new Imagick($image_path); //$image_path = path to image...
$images_ima->setImageCompression($compression_type);
$images_ima->setImageCompressionQuality(100);
$images_ima->sampleImage($X_SIZE,$Y_SIZE); // 256 ,256
$images_ima->writeImages($dest_path, true); //destination path
none of them worked, if i compare the output with the original image, it will look something like this:
it looks like the functions i've used are resampling the image since the variations in the RGB value between both image are small
i can achieve pixel to pixel identical resizing from 256*256 to 256*256 in photoshop, OSX preview, and even Pixelformer.
i was wondering how can that be done i PHP?
Since your image format (jpeg - assumed from 100 quality setting) is a lossy format you won't get a lossless throughput this way as you're recompressing the image.
You should try to detect image dimensions and use the original image if the dimensions are already correct.
When you don't change the dimensions (original dimensions = dimensions after resizing) in Photoshop or OSX preview they won't recompress the image, that's why you won't see any change.

PHP GD :image re size with some black rectangles?

I am trying to accomplish this task for 2 days, read various stuffs online but still can't find out what is happen, also read all here at SO about similar problems but nothing.
I have image 400x400 and want to generate 120x120 using php gd. using this code:
$image_p = imagecreatetruecolor(120,120);
$image = imagecreatefromstring($X_IMAGE);
imagecopyresampled($image_p, $image, 0, 0, 0, 0, 120, 120, 400, 400);
// RETURN
header('Content-Type: image/jpeg');
imagejpeg($image_p, null, 70);
//destroy...
$X_IMAGE is 400x400 JPG that is stored as string.
All images are generated in 120x120 but most of them have some BLACK rectangle at bottom at some pictures it is larger on some it is smaller but 50% of images are with that square. So all are VISIBLE, just some part of image is covered with that black color. What would be solution for my problem? All source images are JPG and also those 120x120 that I need are JPG as you can see...
The problem is that your original image is not a square! You pass 400x400 to imagecopyresampled, but the height of the original image maybe is not 400px!
In the image you posted, for example, you have a not-squared original image. When you tell PHP to resample a square on anther image resource, you will resample the image plus a non-existent rectangle at the bottom.
The solution depends on what you want to output.
Do you want a scaled image that keeps ratio? For example, from 400x300 to 120x90.
Or a scaled image that not keeps ratio? For example, from 400x300 to a distorted 120x120?
Or a cropped thumbnail? 400x300 to a 120x120 with left and right parts trimmed out a little?
Do you want to replace the black rectangle with a white one, so fill the resampled image in that way?

PHP. Imagecolorallocate returns false

I use some code:
$colors = array ();
$colors['test'] = imagecolorallocate($img, 0 ,1 ,2);
....
It works until I change picture to other
After that imagecolorallocate and imagecolorallocatealpha return false
$img is correct image, i.e imagepng print it correctly
How to make imagecolorallocate work?
Comment on the documentation of this function:
If you even in a situation where it's
not allocating the color you want it
could be because of your images color
allocation table. GIF and 8-bit PNG
images are very susceptible to this.
If your using an GIF and PNG try
dropping a color from the table,
should let you allocate another.
If the source image in an indexed image (8-bit or less) then make sure there is room for additional colors. E.g. an 8-bit image might not be using all 256 colors from the palette in that case the function should succeed and it will not otherwise.
Edit
I looked at your image and it is infact an 8-bit PNG image that uses all 256 colors. Try converting it to a true color image (either via photoshop or by copying the image into a GD image created via imagecreatetruecolor()); do all the editing, then save as GIF.

Bad quality of GIF image in PHP GD

I have a watermark script I am working on, the results are good on PNG and on JPG images however a gif image, not so good. I am using PHP and GD
Below you can see the difference in quality of the watermark.
Anyone know how to improve this?
For the gif version I am using
$image = imagecreatefromgif($source_file);
imagecopymerge($image, $watermark, $x, $y, 0, 0, $water_width, $water_height, 65);
imagegif($image, $source_file);
gif image = bad quality
gif image http://img2.pict.com/fd/46/00/1471179/0/gif.gif
jpg image = good
jpg image http://img2.pict.com/82/a1/5a/1471181/0/jpg.jpg
GIF images have a fixed palette that can contain a maximum of 256 colors. The issue here is probably that the image your inserting uses colors that isn't available in the target image.
I have never tried this, but it might be worth a shot. You could try converting the gif image to a true color image first, then do the watermarking and after that converting it back to gif.
$image = imagecreatefromgif($source_file);
// create a true color image of the same size
$image2 = imagecreatetruecolor(imagesx($image), imagesy($image));
// copy the original gif image on to the true color image
imagecopy($image2, $image, 0, 0, 0, 0, imagesx($image), imagesy($image));
// copy the watermark onto the new true color image
imagecopymerge($image2, $watermark, $x, $y, 0, 0, $water_width, $water_height, 65);
// write the new image to disk
imagegif($image2, $source_file);
Try it and see if it makes a difference.
There's also a couple of palette manipulation functions available that might help:
imagecolormatch()
imagetruecolortopalette()
imagepalettecopy()
I'm not sure how you would apply them, but I'm guessing that there's a few things you could do to improve the results.
GIF only supports a color palette of 256 colors. Therefore, the colors of your watermark image have to be mapped to this palette. This caused them to be rendered and saved with different colors than before. Due to this small palette, GIF is not recommended for photos in general, anyways.
GIF images will never look great, as the colour palette is 256 colours. As MrMage says, colour mapping causes a severe approximation of the true colours of the image. You are better off with PNGs, they do support transparency.

Categories