PHP GD turn background into transparent or alpha - php

I have an jpeg image, I want to use php GD to create 2 boxs.
left box will remove background and set transparent
Right box will set rgba - alpha 80%;
and save it in png transparance
I have try imagesetpixel, but its not transparent,
I also try imagecolortransparent
$transparentcolour = imagecolorallocate($im, 40,220,1);
imagecolortransparent($image, $transparentcolour);
but this will turn everything into transparent in this color.
anyone know how to achieve this?

The straight transparent is easy:
Disable alpha blending
Allocate a colour with alpha - personally I use (255,0,255,127) because magenta is the "standard" transparent colour when working with game sprites, so I just sort of stuck with it
Draw the rectangle
The result will be a block of transparency.
Function reference: imagealphablending, imagecolorallocatealpha, imagefilledrectangle
The "fade by 80%" thing will be trickier.
Disable alpha blending
For each (x,y) in the rectangle... (ie. two nested for loops)
Get the colour of that pixel (imagecolorat and imagecolorsforindex should help)
Multiply $color['alpha'] by 0.2 for an 80% fade
Allocate a new colour with the same RGB as the source, but with the new A value
Draw the pixel
The result will be a block of 80%-faded-to-transparent pixels.
Function reference: imagealphablending, imagecolorat, imagecolorsforindex, imagecolorallocatealpha, imagesetpixel

Related

Imagecolortransparent() for multiple colors

I use this code to make all white pixels transparent:
$img = imagecreatefromjpeg('test.jpg');
$remove = imagecolorallocate($img, 255, 255, 255);
imagecolortransparent($img, $remove);
imagepng($img, 'bla.png');
But I also want some "almost white" pixels to be transparent like 254, 255, 255 etc. How could I add that?
If your question is how to remove a contiguous area with similar color range; I must say that it's hard using PHP's GD library. You should take a look at ImageMagick which is a much more powerful image processing library and has PHP integration.
If you choose to use ImageMagick instead, you'll have access to a lot of third-party scripts that does amazing image processings. One of which is Fred Weinhaus' MagicWand. It does what you're looking for.
You seed it with an x and y coordinate, it can extract the color of that coordinate and make it transparent with a configurable color dissimilarity threshold (fuzz factor). Have a look how it can match a gradient of blue:
I had the same problem. With a black and white image. But white was not very white. So before to set transparency, I do a filter to increase the contrast. And I have an image with real black and real white. And when I use transparency on white color, it's works fine.
Filter's example :
imagefilter($src,IMG_FILTER_CONTRAST,-50);

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

Partial black background when watermarking PNG image with GD PHP

I have pieced together a PHP class to perform various image related functions using GD functions of PHP.
It works great for all image types. Rotate, flip, resize, crop and to a lesser extent, watermark.
All but the latter work perfectly. For example after a few changes, rotated PNG images retained their transparency whereas before they were losing that and the background turning black. Common problem, it appears. But all working now.
Where I'm still getting stuck is watermarking a PNG image with another PNG image. It appears to work fine with JPG and other images. This is the code (simplified):
public function writeWatermarkSimple()
{
$watermarkFile = 'watermark.png';
$watermarkImage = imagecreatefrompng($watermarkFile);
imagealphablending($watermarkImage, false);
imagesavealpha($watermarkImage, true);
$imageFile = 'image.png';
$baseImage = imagecreatefrompng($imageFile);
imagealphablending($baseImage, false);
imagesavealpha($baseImage, true);
$marginH = imagesx($baseImage) - imagesx($watermarkImage);
$marginV = imagesy($baseImage) - imagesy($watermarkImage);
$cut = imagecreatetruecolor(imagesx($watermarkImage), imagesy($watermarkImage));
imagecopy($cut, $baseImage, 0, 0, $marginH, $marginV, imagesx($watermarkImage), imagesy($watermarkImage));
imagecopy($cut, $watermarkImage, 0, 0, 0, 0, imagesx($watermarkImage), imagesy($watermarkImage));
imagecopymerge($baseImage, $cut, $marginH, $marginV, 0, 0, imagesx($watermarkImage), imagesy($watermarkImage), 80);
if (!imagepng($baseImage, 'watermarked_image.png'))
{
return false;
}
return true;
}
This has been pieced together with various guides and advice people have given based on a similar issue. Again, working perfectly with JPG images and PNG watermarks, but not PNG & PNG.
Some example images:
http://i.imgur.com/hHRWinj.png - This is the watermark I'm using.
http://i.imgur.com/6sy8Ncs.png - This is the image I'm applying the watermark to.
http://i.imgur.com/ghovYLm.png - This is the end result.
The bit I find interesting is that any part of the watermark that is overlaid on a non-transparent portion of the image is working fine. Just the rest of it has the black background.
This leads me to believe I'm close, and I hope that the expertise of you fine people may lead me to the solution.
Thanks ever so for reading.
So, I'm not giving up on finding the correct answer to do this using GD. However, I was overjoyed to find that what needed up to 30 lines of code with GD can be achieved using much less with ImageMagick:
$image = new Imagick();
$image->readimage($this->_image);
$watermark = new Imagick();
$watermark->readimage($this->_watermark->_getImage());
$watermark->evaluateImage(Imagick::EVALUATE_DIVIDE, 2, Imagick::CHANNEL_ALPHA);
$image->compositeImage($watermark, imagick::COMPOSITE_OVER, $marginH, $marginV);
So this is before (with GD):
http://i.imgur.com/AlS0TcO.png
And after (with ImageMagick and the code above):
http://i.imgur.com/zBxlC3R.png
If anyone has an answer that is purely GD then I'd be immensely grateful.
Ran into some similar issues recently and while this may not exactly solve your problem, these were some useful discoveries that I made.
In my case, I have an original .jpg image and a watermark .png image. The watermark image has a fully transparent background. I wanted to specify the opacity in my script and have it change the watermark opacity before placing it on top of the origina image. Most posts out there regarding PHP watermarking assume that the original watermark .png file already has the solid watermark portion set to the correct opacity rather than changing it via the script.
gd didn't like a 24 bit .png and caused some goofy issues. Switching to 8 bit resolved that with gd. On the other hand, imagick works very well with a 24 bit .png and the final result seems to be better.
For me, using gd worked just fine if I was opening the original watermark .png and using imagecopymerge() to set the watermark transparency. If however I tried to scale the original watermark .png (which has transparent background) first, then I would get similar results as you with black or white background portion of where watermark image is. See How do I resize pngs with transparency in PHP? for a partial solution by filling the new wm image with transparent rectangle first. For me this still produced an opaque white background on the final result no matter what I tried.
I switched to imagick and was using setImageOpacity() to change the transparency of my watermark .png before applying it on top of my original image and I was still getting the same effect with a black background. Finally read in the PHP doc for setImageOpacity() that if the original .png has any transparent pixels and you try to lower the opacity, those pixels become opaque (black) with the new transparency applied. Instead, need to use the evaluateImage() function. This will instead evaluate each pixel's alpha channel only and divide by the specifid number.
I assume the black / white background issue with gd is likely due to similar ways that it treats alpha channels when scaling / combining as compared to imagick and if you want to do it all in gd you just need to find some similar way to evaluate and manipulate the alpha channel per-pixel because the "easy" ways seem to take an already transparent background and make it opaque.
So, the solution:
Assuming you want to apply your watermark at an opacity of 45% and you're using imagick, then instead of this:
$watermark->setImageOpacity(.45);
do this
$watermark->evaluateImage(Imagick::EVALUATE_DIVIDE, (1/.45), Imagick::CHANNEL_ALPHA);
You need to divide 1 by your opacity to get the demoninator by which the function will divide the alpha channel value for each pixel. In this case, 1/.45 = 2.2222, so then the function will divide the alpha channel of each pixel by 2.2222. This means a solid pixel (alpha of 1) would result in 1/2.2222 or .45 alpha or transparency when finished. Any pixels that were already transparent (alpha 0) would stay transparent because 0 divided by anything is always what? Zero!
After you change the watermark transparency then you can use compositeImage() to merge the watermark onto the original image.

Transparency issue with png images

I 've got this image:
i use php5 and gd2 library to achieve a transparent background, but the result is not what i have expected(you need a dark background to see the difference):
and here is my code:
$size = getimagesize($img_url);
$img = imagecreatefrompng($img_url);
$im_tc = imagecreatetruecolor($size[0],$size[1]);
imagecopyresampled($im_tc,$img,0,0,0,0,$size[0],$size[1],$size[0],$size[1]);
imagedestroy($img);
$white = imagecolorallocatealpha($im_tc, 255, 255, 255,127);
imagecolortransparent($im_tc, $white);
imagepng($im_tc,'image.png');
Any help would be appreciated! :)
Your original image doesn't have a transparent background, but you're trying to create one by changing all pure-white pixels to transparent. As the text has a shadow/glow around it, those pixels aren't quite white, and won't become transparent. You have a couple options here:
Use an image editor (GIMP, Photoshop, etc.) and their fine-grained selection tools to perform a smart selection of the "background", then remove that. Photoshop, at least, has extremely useful options available on its magic wand tool to choose threshold, feathering, and more.
Pick more colours to make "transparent." Instead of just white, choose all of the shades of gray, minus the exact colour that ".gr" is set in. This should make all of the shadowed parts of the image transparent as well, although the edges may be less than perfect (i.e.: not feathered, slightly jagged.)

change shirt color with gd library

i m trying to change color of a shirt. here is my code in its simplest form.
$imgname = "me.jpg";
$im = imagecreatefromjpeg ($imgname);
imagetruecolortopalette($im,false, 255);
$index = imagecolorclosest ( $im, 96, 132, 194 ); // get COlor
imagecolorset($im,$index,92,92,92); // SET NEW COLOR
$imgname = "result.jpg";
imagejpeg($im, $imgname ); // save image as gif
//imagedestroy($im);
but this code does change only specific color. You can see in attached image.
i want whole shirt color changed from blue to grey. is it possible with GD library or any other library? If yes how??
Using GD to accomplish this seems like using chainsaw to slice bread. An easier (and I think better) way to handle this would be to have the shirt be a transparent PNG with transparent shadows in the correct places. Then you can simply change the background color of the image container using any number of freely available color pickers. Since the shirt is transparent, it then becomes the color of the background (blue, gray, whatever). Once the user has selected a color that works, you can pass that hex color to the back-end along with the rest of the order information (size, etc).

Categories