I am framing ads with a curved border.
Here is a sample ad: http://imageshack.us/f/20/4e5f5fe94b327new60seciq.png/
I am trying to replicate what would be done in Photoshop, place one on top of the other. Here is the code I'm using:
// create destination canvas
$dest_img = imagecreatetruecolor(176, 75);
// Make the background transparent
$black = imagecolorallocate($dest_img, 0, 0, 0);
imagecolortransparent($dest_img, $black);
imageAlphaBlending($dest_img, false);
imageSaveAlpha($dest_img, true);
// copy ad into destination
imagecopy($dest_img, $ad_image, 0, 0, 0, 0, 176, 75);
// copy frame onto first half of image
imagecopy($dest_img, $curve_image, 0, 0, 0, 0, 88, 75);
What is happening is that the last copy to take place (the frame) is taking priority and instead of seeing the ad, im getting a transparent block. Here is a blown up image of what GD is doing:
http://imageshack.us/f/684/unled1to.png/
I'm hoping there is a simple solution to get the lower layer to remain visible - if not I think I will have to write a function and go pixel by pixel and compare...
if (bottom_px == trans && top_px == trans) {
dest_px = trans;
}
else {
dest_px = top_px;
}
Set imagealphablending to true. From the manual, emphasis added:
In blending mode, the alpha channel component of the color supplied to all drawing function, such as imagesetpixel() determines how much of the underlying color should be allowed to shine through. As a result, gd automatically blends the existing color at that point with the drawing color, and stores the result in the image. The resulting pixel is opaque. In non-blending mode, the drawing color is copied literally with its alpha channel information, replacing the destination pixel. Blending mode is not available when drawing on palette images.
Also, you are not actually coloring the background transparent. You are just telling that $black is transparent. Instead, use imagefill with imagecolorallocatealpha:
imagefill($dest_img, 0, 0, imagecolorallocatealpha($dest_img, 0, 0, 0, 127));
Related
I'm trying to create images from dynamic text data in GD and put a logo in the top corner. The background color of the image will change based on the data passed in so I can't just save the logo as an image with no alpha channel.
I create the image, fill it with the dynamic background color using imagefill(), then add the text using imagettftext() and then load my logo in. I'm having a problem getting the logo into the image without it keeping its background color of 'transparent'. So I would like it to have the dynamic background color behind it that is set with imagefill(). However, it keeps the transparency background it was loaded in with and so writes this part of the png as transparent. I tried calling imagefill() on the logo after it had been loaded in (using the same rgb that sets the background of the destination image) but this didn't do anything.
Below is my code:
$background = $_GET['background'];
$data1 = $_GET['data1'];
$data2 = $_GET['data2'];
$r = $_GET['r'];
$g = $_GET['g'];
$b = $_GET['b'];
$png_image = imagecreate(400, 200);
$gd_text_color = imagecolorallocate($png_image, 255, 255, 255);
$gd_background_color = imagecolorallocate($png_image, $r, $g, $b);
imagefill($png_image, 0, 0, $gd_background);
$text1 = "test test $data1";
$text2 = "test test again $data2";
$font = 'Lato-regular.ttf';
imagettftext($png_image, 18, 0, 20, 20, $gd_text_color, $font, $text1);
imagettftext($png_image, 18, 0, 20, 50, $gd_text_color, $font, $text2);
//trying to get this logo and place it in the corner.
$logo = imagecreatefrompng("images/logo.png");
imagecopy($png_image, $logo, 10, 10, 0, 0, 100, 30);
header('Content-type: image/png');
imagepng($png_image, $filename);
imagedestroy($png_image);
Here's the output of that code: http://i.imgur.com/n25h9Js.png
And here's what the image looks like when loaded into a program that accepts an alpha channel: http://i.imgur.com/3OIRupN.png
Does anyone know how I'd achieve what I'm attempting?
Thanks for your time.
EDIT
To try and explain what I want here's another image. The top image is what I currently get, and the bottom image is what I want. I'm simply trying to load in a transparent PNG that can sit ontop of different colored backgrounds. However I either get it like how it is shown here (transparent background) or as a black background (because I guess the alpha channel isn't being looked at?). Hope this helps. Image:
Edit 2
As per the comment below, I changed it from imagecreate() to imagecreatetruecolor() and now it works fine! I would love an explanation why this solved it if anyone has the time but for now, thank you all who commented or even spent your time looking at this question.
I suspect your imagecreate() may be causing you problems as it creates a palettised image which doesn't have the flexibility or breadth of expression of a true-colour image.
I suggest you replace it with imagecreatetruecolor().
I have an image customizing plugin having stage of 1000x700 where user can upload his/her pic and design it with in stage area.
Now if user doesn't use full staging area and use only some part of stage let say 800x400. My final image will be of 1000x700 with transparent background having user's design in middle of it.
Now question is, I want to stretch user design on full canvas with out white background.
How can I do this using php GD or imagick (not manually)?
$dstImage = imagecreatetruecolor(1000, 700);
$black = imagecolorallocate($dstImage, 0, 0, 0);
// Make the background transparent
imagecolortransparent($dstImage, $black);
$srcImage = imagecreatefrompng('srcImg.png');
imagecopymerge($dstImage, $srcImage, 0, 0, 0, 800, 400, 1000, 700);
imagepng($dstImage, 'outputNewImg.png');
I am trying to create a transparent image canvas and then place other random images on top of this canvas. I then finally save the final image as a gif. I have tried the below:
$canvas = imagecreatetruecolor($this->canvas_width, $this->canvas_height);
imagesavealpha($canvas, true);
imagealphablending($canvas, false);
$trans_colour = imagecolorallocatealpha($canvas, 0, 0, 0, 127);
imagefill($canvas, 0, 0, $trans_colour);
However, if there is some unused space left on the canvas then this part is black. I thought this area should be transparent?
Am I applying transparency correctly with the above?
imagesavealpha can not be used for images you eventually intend to save as GIF because GIF images do not have alpha channels. From the docs:
imagesavealpha — Set the flag to save full alpha channel
information (as opposed to single-color transparency) when saving PNG
images
So it only works if you are going to save the image as PNG. GIF images can do transparency, but not with an alpha channel; they can only be "transparent" or "not transparent" by defining a particular color as transparent. In PHP you can do that using imagecolortransparent. For example, to make all black transparent, you could do:
$black_color = imagecolorallocate($canvas, 0, 0, 0);
imagecolortransparent($canvas, $black_color);
I wonder if it is possible to have "opacity" effect when drawing images on top of other images with the PHP GD extension? Are there any built-in functions that can get the results I want or do I have to go for my own implementation using imagesetpixel way?
A pseudo-code to illustrate what I am trying to do right now:
// Background image
$image_bg = imagecreatetruecolor(100, 100);
imagesavealpha($image_bg, true);
// Making background image fully transparent
imagefill($image_bg, 0, 0, imagecolorallocatealpha($image_bg, 0, 0, 0, 127));
// Now the actual image I want to draw with opacity (true color PNG)
$image = imagecreatefrompng(...);
// Drawing with 50 "merge" value
imagecopymerge($image_bg, $image, ..., 50);
The trouble with above code is that imagecopymerge will not respect background image alpha value and will merge the image with the background as if it was opaque black color (the resulting image will not be 50% transparent).
Edit: I ended up implementing my own function using imagecolorat and imagesetpixel way.
Take a look at imagecolortransparent() and imagealphablending() (or this question).
I'm using GD to resize and convert images, however during my tests I found a weird behavior when converting transparent PNG's to JPEG's. According to the manual ImageAlphaBlending() is on by default but in order to preserve the transparency I must set ImageSaveAlpha() to true (which in turn requires that I set ImageAlphaBlending() to false). So the correct way should be:
$result = ImageCreateFromPNG(...);
ImageAlphaBlending($result, false);
ImageSaveAlpha($result, true);
ImageFill($result, 0, 0, IMG_COLOR_TRANSPARENT);
ImageJPEG($result);
ImageDestroy($result);
However if I do it the "correct" way all the transparency area comes up black in the JPEG. This seems to work (JPEG with white background on transparent areas) on my tests:
$result = ImageCreateFromPNG(...);
ImageAlphaBlending($result, true); // true by default, but still...
ImageSaveAlpha($result, true);
ImageFill($result, 0, 0, IMG_COLOR_TRANSPARENT);
ImageJPEG($result);
ImageDestroy($result);
Can someone please enlighten me on this subject?
It probably depends on your PNG. A PNG file can contain a background color, which can be used when transparency doesn't work. Your PNG probably has a white background. When you set imageaplhablending to true it picks up the background color from your PNG and uses that when writing the JPEG. When you set it to false it picks the default for GD which is black.
You can try it for yourself. Create a transparent PNG and save it with an orange or pink background color. Your second example should show that color.
By the way, the PNG background color trick is a nice one for IE6 images. IE6 does not support transparent PNGs so it will display them with whatever background color you saved them with. When saving transparent PNGs, save them with the same background color as your website. It will look better than white or black boxes around your PNG images in IE6.
If you are converting from PNG (or GIF) to JPG, you should probably copy the final image to another image that is filled with white, using imagecopy ($image is any image already created with GD):
// Create a new background
$bg = imagecreatetruecolor(imagesx($image), imagesy($image));
// Allocate the color
$color = imagecolorallocate($bg, 255, 255, 255);
// Fill the background with white
imagefill($bg, 0, 0, $color);
// Alpha blending must be enabled on the background!
imagealphablending($bg, TRUE);
// Copy the current image onto the opaque background
if (imagecopy($bg, $image, 0, 0, 0, 0, imagesx($image), imagesy($image)))
{
// Replace the image with the background copy
imagedestroy($image);
$image = $bg;
}
Hope that helps.