PHP+GD: imagecopymerge not retaining PNG transparencies - php

I have two PNG files, "red.png" and "blue.png"; they are both mostly transparent, but there is a few pixels of red or blue splotches in various places.
I want to make a PHP script that merges the two; it should be as simple as something like:
$original = getPNG('red.png');
$overlay = getPNG('blue.png');
imagecopymerge($original, $overlay, 0,0, 0,0, imagesx($original), imagesy($original), 100);
header('Content-Type: image/png');
imagepng($original);
When I run this script, all I get is the blue dots -- with the transparency lost. I saw that I should add these:
imagealphablending($original, false);
imagesavealpha($original, true);
(on both the original and the overlay?) And that doesn't seem to help any.
I saw a few workarounds on PHP.net, something to the tune of:
$throwAway = imagecreatefrompng($filename);
imagealphablending($throwAway, false);
imagesavealpha($throwAway, true);
$dstImage = imagecreatetruecolor(imagesx($throwAway), imagesy($throwAway));
imagecopyresampled($dstImage, $throwAway,0,0,0,0, imagesx($throwAway), imagesy($throwAway), imagesx($throwAway), imagesy($throwAway));
, which should convert the PNG to a "truecolor" image and retain transparency. It does seem to do so, but now all I see is blue on a black background.
What do I do?!

This works perfectly for me:
$img1 = imagecreatefrompng('red.png');
$img2 = imagecreatefrompng('blue.png');
$x1 = imagesx($img1);
$y1 = imagesy($img1);
$x2 = imagesx($img2);
$y2 = imagesy($img2);
imagecopyresampled(
$img1, $img2,
0, 0, 0, 0,
$x1, $y1,
$x2, $y2);
imagepng($img1, 'merged.png', 0);
PHP Version 5.3.2
GD Version 2.0
libPNG Version 1.2.42
Have you tried saving the image to a file and checking that?

Related

Fill png transparency with background color

I'm refactoring an old image crop/resize library i wrote about 5 years ago and i'm stuck trying to restore one of it's functionalities. The funny part is that i'm not even sure it worked back then since i probably never actually used it.
I need to be able to work on png images while keeping transparency (which works), but i also wan't to be able to fill the transparent part of the image with a color.
Creating a blank image and filling it with a color works fine, but when i try to paste my png over it, the background is transparent again.
Here's a simplified version of my code:
<?php
$src = imagecreatefrompng($pathToSomePngFile);
imagealphablending($src, false);
imagesavealpha($src, true);
$output = imagecreatetruecolor($width, $height);
if ($backgroundColor) {
$fillColor = imagecolorallocate(
$output,
$backgroundColor['r'],
$backgroundColor['g'],
$backgroundColor['b']
);
imagefilledrectangle(
$output,
0,
0,
$width,
$height,
$fillColor
);
} else {
imagealphablending($output, false);
imagesavealpha($output, true);
}
imagecopyresampled(
$output,
$src,
0,
0,
0,
0,
$width,
$height,
$width,
$height
);
imagepng($output, $pathToWhereImageIsSaved);
UPDATE
Updated with delboy1978uk's solution to get it to work without changing my other settings.
Something like this should work.
<?php
// open original image
$img = imagecreatefrompng($originalTransparentImage);
$width = imagesx($img);
$height = imagesy($img);
// make a plain background with the dimensions
$background = imagecreatetruecolor($width, $height);
$color = imagecolorallocate($background, 127, 127, 127); // grey background
imagefill($background, 0, 0, $color);
// place image on top of background
imagecopy($background, $img, 0, 0, 0, 0, $width, $height);
//save as png
imagepng($background, '/path/to/new.png', 0);

Invert color and preserve transparency with PHP

I'm trying to create a function that receives a PNG image and returns it with inverted colors. However, I'm having trouble with the transparency/alpha channel: basically, transparent pixels are coming back as either black or white, and thus transparency is not retained.
This is an example of a source image (which will of course vary), a PNG with a transparent background:
I would like to invert those colors while preserving transparency/alpha channel, like a CTRL+I in Photoshop. I'm using GD imagefilter function with the IMG_FILTER_NEGATE parameter
With the code:
$im = imagecreatefrompng($image_file);
imagefilter($im, IMG_FILTER_NEGATE);
header('image/png');
imagepng($im,NULL,0);
But it yields:
As you can see, transparent pixels turned black.
I then tried adding the alpha channel to the function imagecreatefrompng (like this):
$im = imagecreatefrompng($image_file);
imagealphablending($im, false);
imagesavealpha($im, true);
imagefilter($im, IMG_FILTER_NEGATE);
header('image/png');
imagepng($im,NULL,0);
But now I get white instead of black:
Now the issue seems to happen after the imagefilter function is applied. For example, if I run this code:
$im = imagecreatefrompng($image_file);
imagealphablending($im, false);
imagesavealpha($im, true);
//imagefilter($im, IMG_FILTER_NEGATE);
header('image/png');
imagepng($im,NULL,0);
The output image retains its transparent background, while remaining identical to the original image.
How can I invert colors of transparent PNGs without losing the transparent background?
NOTE: this is not the same question as imagecreatefrompng() Makes a black background instead of transparent? - the inversion step is the tricky part here
Here's what worked for me, dealing with transparent background and inverting image. Note that I'm using base64.
$im = imagecreatefromstring(base64_decode(str_replace('data:image/png;base64,', '', $base64)));
$width = imagesx($im);
$height = imagesy($im);
$dest_image = imagecreatetruecolor($width, $height);
imagealphablending($dest_image, FALSE);
imagesavealpha($dest_image, TRUE);
imagefilter($im, IMG_FILTER_NEGATE);
imagecopyresampled($dest_image, $im, 0, 0, 0, 0, $width, $height, $width, $height);
//optional output back to base64 or use imagepng with destination
ob_start();
imagepng($dest_image);
$contents = ob_get_contents();
ob_end_clean();
$base64 = 'data:image/png;base64,'.base64_encode($contents);

Grayscale PHP imagefilter issues

I'm having issues incorporating imagefilter in the following. Output is a color image. I've tried a few different options, based on php.net documentation but I either get a black image or a color image, not grayscale.
$data = file_get_contents($_FILES['image']['tmp_name']);
$vImg = imagecreatefromstring($data);
$dstImg = imagecreatetruecolor($nw, $nh);
imagefilter($dstImg, IMG_FILTER_GRAYSCALE); // imagefilter added
imagecopyresampled($dstImg, $vImg, 0, 0, $x1, $y1, $nw, $nh, $w, $h);
imagejpeg($dstImg, $path);
imagedestroy($dstImg);
I know my usage is complete wrong, so any help would be much appreciated!
you need to make the source grayscale.
replace
imagefilter($dstImg, IMG_FILTER_GRAYSCALE);
with
imagefilter($vImg, IMG_FILTER_GRAYSCALE);

Put a PNG over a PNG and preserve transparency with PHP [duplicate]

So I found some code on PHP Doc, and edited it slightly to merge two images I have. The image is then saved in a folder on the server. However there is a slight problem and I am unable to figure out why it is happening.
Firstly my code:
$glassurl = $_GET['GlassImg'];
$frameurl = $_GET['FrameImg'];
$filename = (int)date("H:i:s");
$src = imagecreatefromgif($frameurl);
$dest = imagecreatefromjpeg($glassurl);
imagecolortransparent($src, imagecolorat($src, 0, 0));
imagealphablending($dest, false);
imagesavealpha($dest, true);
imagealphablending($src, false);
imagesavealpha($src, true);
$src_x = imagesx($src);
$src_y = imagesy($src);
imagecopymerge($dest, $src, 0, 0, 0, 0, $src_x, $src_y, 100);
// Output and free from memory
imagepng($dest, 'uploads/imagetest.png');
imagegif($dest);
imagedestroy($dest);
imagedestroy($src
);
Secondly some information about the images:
Both Images are exactly the same size
The 'pattern' image is just a block colour/pattern
The frame image has transparent parts within the frame (to allow pattern to show through)
The area around the frame is white to hise the excess pattern
I was hoping that when I overlayed the frame onto the pattern because of these parts that it would produce a window frame, with the glass pattern inside, and the white would hide the remaining patten.
To illustrate I have provided the images. and what happens.
Pattern:
Frame:
Result:
As you can see it doesn't result in what I expected. Can anyone please tell me where I am going wrong? I want to overlay the frame onto the pattern, keeping the transparent center and using the excess white to cover the rest of the patter. Any help is greatly appreciated.
Please note that your frame has white edges and if you sill want the windows to be wite you need to crop it and remove the imagecolortransparent added below if not you can use this
$imgl = "thumb/pattern.png";
$img2 = "thumb/frame.png";
$dest = imagecreatefrompng($imgl);
$src = imagecreatefrompng($img2);
imagecolortransparent($src, imagecolorat($src, 0, 0));
$src_x = imagesx($src);
$src_y = imagesy($src);
imagecopymerge($dest, $src, 0, 0, 0, 0, $src_x, $src_y, 100);
// Output and free from memory
header('Content-Type: image/png');
imagegif($dest);
imagedestroy($dest);
imagedestroy($src);
Output
You can also have
$imgl = "thumb/pattern.png";
$img2 = "thumb/frame.png";
$dest = imagecreatefrompng($imgl);
$src = imagecreatefrompng($img2);
$src_x = imagesx($src);
$src_y = imagesy($src);
$srcNew = imagecreatetruecolor($src_x, $src_y);
ImageColorTransparent($srcNew, imageColorAllocate($srcNew, 0, 0, 0));
imagecopy($srcNew, $src, 70, 50, 78, 60, 473, 293);
imagecopymerge($dest, $srcNew, 0, 0, 0, 0, $src_x, $src_y, 100);
header('Content-Type: image/png');
imagegif($dest);
imagedestroy($dest);
imagedestroy($src);
Output
Your image is not transparent as you described, try using this instead if I understood what you described correctly.
also you should find a program which does not transform transparency to white when saving (or check for options regarding this) if you really made those transparent in the first place.

Image transparency not preserved when merging two images in PHP

When using examples from other posts to try and merge one PNG that has transparent parts on it with another non-transparent PNG, the foreground PNGs transparency is lost and defaults to white.
The code so far:
$width = 349;
$height = 250;
$base_image = imagecreatefrompng($_GET['bg']);
$top_image = imagecreatefrompng($_GET['fg']);
$merged_image = "merged.png";
imagesavealpha($top_image, true);
imagealphablending($top_image, true);
imagecopy($base_image, $top_image, 0, 0, 0, 0, $width, $height);
imagepng($base_image, $merged_image);
Can anyone suggest where I may be going wrong?
Coming out like this
Should look like this
Copy from Can PNG image transparency be preserved when using PHP's GDlib imagecopyresampled?
Codes should be like this:
imagesavealpha($base_image, true);
imagealphablending($base_image, false);
$image = imagecreatefrompng($_GET['bg']);
$frame = imagecreatefrompng($_GET['fg']);
imagealphablending($frame,true);
imagecopymerge($image, $frame, 0, 0, 0, 0, 0, 100, 100);
# Save the image to a file
imagepng($image, 'file-xyz.png');

Categories