tags:

views:

729

answers:

1

Alright, I've been hacking around with GD Image for a couple of months, and a task that I wanted to accomplish with it was to create a script that takes an existing image, and then creates a reflection that fades out to translucent beneath it.
The following guide shows how to do it with an opaque color : TalkPHP Forums Link

In that forum, Rendair describes a way to overlay a dynamically drawn gradient using a color, with the following PHP code:

    // Next we draw a GD line into our gradient_line
imageline ($gradient_line, 0, 0, $imgName_w, 0, $gdGradientColor);


$i = 0;
$transparency = 30; //from 0 - 100

    while ($i < $gradientHeight) //create line by line changing as we go
    {
        imagecopymerge ($background, $gradient_line, 0,$gradient_y_startpoint, 0, 0, $imgName_w, 1, $transparency);

        ++$i;
        ++$gradient_y_startpoint;

                if ($transparency == 100) {

                    $transparency = 100;

                }
                else 
                {
         // this will determing the height of the
         //reflection. The higher the number, the smaller the reflection. 
         //1 being the lowest(highest reflection)
                    $transparency = $transparency + 1; 

                }

    }

What I'm attempting to accomplish is an effect where we similarly fade each line to one shade more translucent using the alpha feature, but it seems that I have a hard time applying it one line at a time. So far I can only make a tiny slice of the image (one line large) and then overlay it with translucency, I can't seem to fade each line a bit more. So my intended result should be the initial image, then a reflected copy that fades to 100% alpha transparent, but I can't seem to accomplish this.
Any PHP folks out there who have any genius ideas?
Update: this question has earned me the tumbleweed badge.

+1  A: 

All right, that was intense. To keep a long story short, imagecopymerge does not properly handle alpha channels. Instead, you need to use imagefilter with the IMG_FILTER_COLORIZE filter to lower the opacity of each line. This code is now part of Image_GD (BSD license). I tried to make the code as clear as possible, but let me know if you have any questions.

Usage using the Kohana Image library works like this:

// Makes a 20px tall reflection with a starting opacity of 100%
// and overwrites the original image with the new one
Image::factory($image_file)->reflection(20, 100)->save();

The really important bits are lines 265-287, which handles the actual line-by-line gradient creation. All instances of $this->width can translate into imagesx($image) (and imagesy for $this->height). $this->_image refers to an GD resource that was created from an existing image.

Oh, and make sure you render the image as a PNG or the gradient alpha will not work properly... :)

shadowhand
Awesome! I'm upvoting this for now, but I'll accept it once I check it and get it to work.
NateDSaint
Actually, did you have a code sample, via "I tried to make the code as clear as possible", I didn't see any in this answer.
NateDSaint
Updated my answer with an example... If necessary, I could extract the method from the class as a single function.
shadowhand
In case you missed it, make sure to click the "Image_GD" link above, it has the complete code for implementing this.
shadowhand
Got it! Works like a charm, I just need to hack around with it to make it do what I want in various instances, but this is LEAGUES beyond where I was. Thank you!
NateDSaint
Hooray, another satisfied user! :)
shadowhand
After messing with this on and off for the past month or so, I've found that it doesn't work for the case I specifically needed, but that's because it's a limitation of the way PHP's GD handles PNG transparency. I can't make a copy of an already translucent image with the proper translucency fade... but it works for non-translucent/transparent images. I might have to go with a javascript solution, which is less than ideal, but possible. I'll update the post later with the extracted function I wrote for my purpose.
NateDSaint
My original tests showed that using transparent PNGs worked just fine... and my tests still do, **but** it seems that the alpha channel is written strangely by GD. Preview (OSX) shows the image retraining transparency, as does Photoshop (using drag-n-drop). However, when I save the image to a file, it loses the alpha channel. If I have some time, I will play with the code and see if I can fix the issue.
shadowhand
Sorry for the delay in response time, but yeah I've done some testing as well and I think it's a bug in GD. But I've also found that where you apply the filter, it's only adding a black filter over the pixels, it's not actually making those pixels transparent. I'm not sure if this is the intended functionality for that filter or if its just responding that way because of the alpha transparency. I'm thinking until GD is updated this will not be a workable solution.
NateDSaint