Want to use imagecopy or imagecopyresampled with 50% opacity - php

I am using PHP GD imagecopy or imagecopyresampled to merge a PNG image with transparency onto another PNG image (basically creating t-shirt mockups with design).
When I use imagecopymerge() it doesn't respect the transparency. but opacity setting option works. But when I use imagecopy() or imagecopyresampled() then transparency works but opacity setting is not available.
So how to merge images which respects transparency and provides 50% opacity as well?
My code is:
$img1 = imagecreatefrompng('m1.png');
$img2 = imagecreatefrompng('m2.png');
imagealphablending( $img2, false );
imagesavealpha( $img2, true );
$x1 = imagesx($img1);
$y1 = imagesy($img1);
$x2 = imagesx($img2);
$y2 = imagesy($img2);
//imagecopyresampled($img1, $img2, 205, 170, 0, 0, $x2-40, $y2-40, $x2, $y2);
imagecopy($img1, $img2, 205, 170, 0, 0, $x2-40, $y2-40);
header('Content-Type: image/png');
imagepng($img1);
Please help.

You can have a look at this link:
https://bugs.php.net/bug.php?id=23815
imagecopymerge doesn't support image alpha. Becuase of that, they have requested the creation of a new function imagecopymergealpha to do this kind of job.
https://github.com/php/php-src/pull/211

imagecopymerge($img1, $img2, 0, 0, 0, 0, $x1, $y1, 50);
header('Content-Type: image/png');
imagepng($img1);

Please check using this sample code
$imageName = 'path/to/your/image/file'
$im_src = create_image_from_type($imageName);
$size = getimagesize($imageName);
$im_dst = create_image_from_type($imageName);
$white = imagecolorallocate($im_dst, 255, 255, 255);
imagecolortransparent($im_dst, $white);
imagefilledrectangle($im_dst, 0, 0, $size[0], $size[1], $white);
$opacityVal = 50;// put the opacity value here
imagecopymerge($im_dst, $im_src, 0, 0, 0, 0,$size[0], $size[1], $opacityVal);
save_image($im_dst, $imageName, 100);

Related

php png merging issue with images

I have two pictures I would like to merge, they are both sized 150x150 pixels.
I want to merge them into a new image, sized 225 width x 150 height. So that image 2 covers half of image 1.
I made some code, but the transparency only works on 150x150 of the new image, the rest just gets a black background.
Both images, do have transparent backgrounds.
background.png is just a png file sized 225x150 pixels, with transparent background.
What am I doing wrong?
$width = "225";
$height = "150";
$dest_image = imagecreatefrompng('background.png');
imagesavealpha($dest_image, true);
$trans_background = imagecolorallocatealpha($dest_image, 0, 0, 0, 127);
imagefill($dest_image, 0, 0, $trans_background);
$a = imagecreatefrompng('9.png');
$b = imagecreatefrompng('90.png');
imagecopy($dest_image, $a, 0, 0, 0, 0, $width, $height);
imagecopy($dest_image, $b, 75, 0, 0, 0, $width, $height);
header('Content-Type: image/png');
imagepng($dest_image);
imagedestroy($a);
imagedestroy($b);
imagedestroy($dest_image);
imagecopy($dest_image, $a, 75, 0, 0, 0, $width, $height);
imagecopy($dest_image, $b, 0, 0, 0, 0, 150, $height);
Just a position problem - fixed:)

How to use imagescale and retain appearance of edge "pixels"

So I have a 3x3 pixel image using imagecreate. I want to scale up the image with imagescale while maintaining the look of a 3x3 grid of "pixels". However, the pixels on the right and bottom edge are not the same size.
Here is my code and output image:
<?php
$image = imagecreate(3, 3);
imagecolorallocate($image, 0, 0, 255);
$red = imagecolorallocate($image, 255, 0, 0);
imagesetpixel($image, 0, 0, $red);
imagesetpixel($image, 1, 1, $red);
imagesetpixel($image, 2, 2, $red);
imagepng(imagescale($image, 200, 200, IMG_NEAREST_NEIGHBOUR));
header("Content-Type: image/png");
This is my output:
Notice how the bottom-right pixel is cut off. I kept playing with the numbers for the new dimensions and arrived at 256x256 at which point the pixels are all the same size.
This is the output after using 256x256:
My question is: How can I derive the dimensions to use for the resized image with the effect I described?
Bonus question: Is an alternative method which will allow me to resize to an arbitrary size and keep the pixels approximately the same size?
I would use imagecopyresampled to achieve this.
http://php.net/manual/en/function.imagecopyresampled.php
<?php
$width = 3;
$height = 3;
$image = imagecreate($width, $height);
imagecolorallocate($image, 0, 0, 255);
$red = imagecolorallocate($image, 255, 0, 0);
imagesetpixel($image, 0, 0, $red);
imagesetpixel($image, 1, 1, $red);
imagesetpixel($image, 2, 2, $red);
$new_width = 200;
$new_height = 200;
$dst = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($dst, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height);
imagepng($dst);
header("Content-Type: image/png");

color error in converting a transparent png to jpg in php with glib

I try to convert a partly transparent png to a jpg in php with gdlib. I found two snippets to help me with that, but both methods have the same problem: The half transparent colors are darker and do not look right. Here a enlarged sample from photoshop: left the png (with white in background instead of transparent), right the converted png to jpg with both snippets I used:
difference png (left) to jpg (right)
Here the original Png-File: golf.png
Any help would be really appreciated!
$input_file = "card/golf.png";
$output_file1 = "card/golf1.jpg";
$output_file2 = "card/golf2.jpg";
$image = imagecreatefrompng($input_file);
$bg = imagecreatetruecolor(imagesx($image), imagesy($image));
imagefill($bg, 0, 0, imagecolorallocate($bg, 255, 255, 255));
imagealphablending($bg, TRUE);
imagecopy($bg, $image, 0, 0, 0, 0, imagesx($image), imagesy($image));
imagejpeg($bg, $output_file1, 100);
imagedestroy($bg);
imagedestroy($image);
list($width, $height) = getimagesize($input_file);
$image = imagecreatefrompng($input_file);
$output = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($output, 255, 255, 255);
imagefilledrectangle($output, 0, 0, $width, $height, $white);
imagecopy($output, $image, 0, 0, 0, 0, $width, $height);
imagejpeg($output, $output_file2, 100);
imagedestroy($output);
You're suffering from quantization. JPEG does not handle this type of image well at all. If you want to lessen the color changes you need to adjust your quantization tables. If you use all 1s for the quantization tables you don't get the color changes.

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:

I can't use transparent background with imagecopymerge

I am calling imagecopymerge($dst_r, $logo, 0, 0, 0, 0, $LogoX, $LogoY, 100); where $logo is a png file with transparent background. From some reason the background comes out white instead.
What am I doing wrong?
Thanks.
You need to use imagealphablending($dst_r, TRUE); to allow copying with retaining the transparent colors. Many more comments (...) in the manual suggest using imagecopy instead, because imagecopymerge was never intended to be used with transparency. If you use pct=100 anyway, then the normal imagecopy might be an option.
This is for text, but you can get the point. It would be more helpful if you post entire code.
$font = 25;
$string = "Hello";
$im = #imagecreatetruecolor(strlen($string) * $font / 1.5, $font);
imagesavealpha($im, true);
imagealphablending($im, false);
$white = imagecolorallocatealpha($im, 255, 255, 255, 127);
imagefill($im, 0, 0, $white);
$lime = imagecolorallocate($im, 204, 255, 51);
imagettftext($im, $font, 0, 0, $font - 3, $lime, "font.ttf", $string);
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);

Categories