Jump to content

Code Question ... Transparent Fade


Recommended Posts

I thought I could write a simple CodeLab effect to make an image fade from fully opaque to fully transparent. I wrote the code that I think should work, but it just is not working! I have no idea what is wrong. I've looked over my code many many many times, but I cannot figure it out. Hopefully someone can point out my error and I will learn something important from it...

Here's the code as it is 8:14 on 3/29/06:

 

Spoiler

void Render(Surface dst, Surface src, Rectangle image)
{
//Environment values for fore/back colors placed into variables
ColorBgra TopColor = (ColorBgra)EnvironmentParameters.ForeColor;
ColorBgra BottomColor = (ColorBgra)EnvironmentParameters.BackColor;

//Alpha information extracted from the fore/back colors
int TopAlpha = TopColor.A;
int BottomAlpha = BottomColor.A;

//The difference between the two alpha values is calculated
int Difference = BottomAlpha - TopAlpha;

//The height of the image is placed into a variable
float maxy = image.Bottom;

//Two variables used in the effect's loops are created
ColorBgra PixelColor;
float yratio;

for (int y = image.Top; y < image.Bottom; y++)
{
	for (int x = image.Left; x < image.Right; x++)
	{
		//The color of the current pixel is taken from the source surface
		PixelColor = src[x, y];

		//The distance from the top of the image in ratio (percentage/100) form is found
		yratio = (y / maxy);

		//The alpha value of the color is modified to account for the distance from the top
		PixelColor.A = (byte)(  (yratio * Difference) + TopAlpha  );

		//The modified color is put onto the destination surface
		dst[x, y] = PixelColor;
	}
}
}

 

 
Link to post
Share on other sites

Three things...

1. You didn't state what results you're getting, just that it's "not working right". So you have no idea what is wrong, but neither do I!

2. "Maximum Y" and "Bottom" are different things. Maximum Y is Bottom-1, so you should do "maxy = image.Bottom - 1

3. This code assumes you are working with opaque pixels. What you should do is calculate an intermediate alpha value, "a" the same way you are currently calculating PixelColor.A. Then, "PixelColor.A = (PixelColor.A * a) / 255;" (plus any type casts that are necessary). This will properly compute the new alpha for pixels whos original alpha value is not 255.

(... and why is the rectangle named 'image' ? It should be called roi (for rectangle-of-interest))

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to post
Share on other sites

I forgot to mention that the opacity of the foreground color must be set to what should be the opacity of the top of the image, and the bottom of the image corresponds with the background color's opacity.

For my trials, I am using a forecolor opacity of 255 and a backcolor opacity of 0.

#1. It's fading...sorta. Zoomed out, it looks like it's fading just the first 50-or-so rows of pixels from opaque to transparent. Upon a closer look, it is revealed that the fade is not really a fade at all, but the alpha values go up and down quite a bit. It's entirely crazy...I cannot figure out how these results are generated. If I could figure out why it is doing this crazy stuff, I could find my problem...I think...

#2. I will fix that. Thanks for the advice. I should have picked that up through the syntax of the for loop. That is, it loops as long as (y

#3 I want to get my simpler alpha-ignorant algorithm to work first. I was already planning to adapt it to deal with pixels that already have an alpha value once I got the basics working. Thanks for pointing out how I might do this.

About the image rectangle....that's just what the default is for CodeLab...I thought it was the proper way to do it. I will edit my code to make it "roi". Should I let Tom know about this?

argh...this code is still not working...

-John

Three things...

1. You didn't state what results you're getting, just that it's "not working right". So you have no idea what is wrong, but neither do I!

2. "Maximum Y" and "Bottom" are different things. Maximum Y is Bottom-1, so you should do "maxy = image.Bottom - 1

3. This code assumes you are working with opaque pixels. What you should do is calculate an intermediate alpha value, "a" the same way you are currently calculating PixelColor.A. Then, "PixelColor.A = (PixelColor.A * a) / 255;" (plus any type casts that are necessary). This will properly compute the new alpha for pixels whos original alpha value is not 255.

(... and why is the rectangle named 'image' ? It should be called roi (for rectangle-of-interest))

Link to post
Share on other sites

I just added a bit of debugging code right before the "dst[x,y] = PixelColor;"

Here's what I added:

		if (maxy < 100)
		{
			PixelColor.R = 255;
			PixelColor.A = 255;
		}

The pixels before 100 have a red tint, and those after don't. I changed the 100 to 200, and the same thing was seen but for pixels before/after 200. Somehow, the maxy is being changed to something close to the y value every time the loop executes. Could this have to do with multi-threading? I'm running this on a Pentium 4 with Hyper-Threading.

Link to post
Share on other sites

The default variable name that Tom gives is "rect", not "image".

Anyway, you're right on that last point. Effects are not rendered all at once -- otherwise it would not be possible to do things like progressive rendering ("35% done"), multithreaded rendering, and clipping to a selection region.

You should not use rect.Bottom as the bottom of the image. That rectangle defines the current rectangle that is being rendered. Paint.NET will divide the whole rendering area into 200 rectangles per logical processor (so 400 for your P4 w/ HT), and pass each one to the effect rendering function. Because of threading, multiple rectangles will be rendered in parallel, but you don't have anything that would have trouble with that (everything is self contained in your function).

What you want is maxy = dst.Height-1.

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to post
Share on other sites

You're right about the "rect"/"image" thing. I have NO idea how it got changed when I started writing this script, but it must have. CodeLab is giving me a default rectangle called "rect" now.

Thanks sooo much for the info on the rendering process! The script runs beautifully thanks to your help!

The default variable name that Tom gives is "rect", not "image".

Anyway, you're right on that last point. Effects are not rendered all at once -- otherwise it would not be possible to do things like progressive rendering ("35% done"), multithreaded rendering, and clipping to a selection region.

You should not use rect.Bottom as the bottom of the image. That rectangle defines the current rectangle that is being rendered. Paint.NET will divide the whole rendering area into 200 rectangles per logical processor (so 400 for your P4 w/ HT), and pass each one to the effect rendering function. Because of threading, multiple rectangles will be rendered in parallel, but you don't have anything that would have trouble with that (everything is self contained in your function).

What you want is maxy = dst.Height-1.

Link to post
Share on other sites
The script runs beautifully

So does this mean you have a working script now? If so, where can we get it? :D

*EDIT* Or, can you post the complete sequence of code?

BK_BloodSaw_sig.png

- DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day.

Link to post
Share on other sites

Lol. Thanks for the interest!

Below is the code and a link to the code file. It is meant to be run in CodeLab. If you want, I can make it into a .dll for Paint.Net so it lists it in the "Effects" menu. To use the script, make the transparency of the foreground color what you want to be the transparency of the top of the image, and make the transparency of the background color be what you want to be the transparency of the bottom of the image. It currently only fades vertically. If you want to fade an image horizontally, just rotate it 90 degrees, use the script, then rotate it back.

void Render(Surface dst, Surface src, Rectangle rect)
{
    //Environment values for fore/back colors placed into variables
    ColorBgra TopColor = EnvironmentParameters.PrimaryColor;
    ColorBgra BottomColor = EnvironmentParameters.SecondaryColor;

    //Alpha information extracted from the fore/back colors
    int TopAlpha = TopColor.A;
    int BottomAlpha = BottomColor.A;

    //The difference between the two alpha values is calculated
    int difference = BottomAlpha - TopAlpha;

    //The height of the image is placed into a variable
    float maxy = dst.Height - 1;

    //Two variables used in the effect's loops are created
    ColorBgra PixelColor;
    float yratio;
    float IntermediateAlpha;

    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        for (int x = rect.Left; x < rect.Right; x++)
        {
            //The color of the current pixel is taken from the source surface
            PixelColor = src[x, y];

            //The distance from the top of the image in ratio form is found
            yratio = (y / maxy);

            //The alpha value of the color is modified to account for the distance from the top
            //Previous alpha value is considered.
            IntermediateAlpha = (byte)(  (yratio * difference) + TopAlpha  );
            PixelColor.A = (byte)((PixelColor.A * IntermediateAlpha) / 255);

            //The modified color is put onto the destination surface
            dst[x, y] = PixelColor;
        }
    }
}
 

http://searedice.rchomepage.com/images/internet/TransFade1.cs

Enjoy :)

-John

Link to post
Share on other sites

I can't get the darn thing to work! LOL

I opened up CodeLab, loaded the source... and nothing happens. What am I doing wrong here SI?

Can you give me a step by step example?

BK_BloodSaw_sig.png

- DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day.

Link to post
Share on other sites

Make sure that you set the transparency of the foreground color to be the transparency of what you want to be the top of the image. The background transparency determines the transparency of the bottom of the image.

I've tried to run the script several times, and upon seeing it not work, having thought "Oh, bloody potato, it's broken again." Then only do I realize that I did not set a foreground/background transparency...

Link to post
Share on other sites

Choose your foreground and background colors in Paint.net (like the default black and white), "open" the colors window and set the "transparency-alpha" value to 0 for the foreground/background color.

And don't forget to select the layer you want to fade. I had to run the script many times to understand that :wink:

I hope that helped you

443e54916a971.jpg
Link to post
Share on other sites
Choose your foreground and background colors in Paint.net (like the default black and white)

Thank you Litchi! As soon as I read... "like the default black and white" I knew exactly what you were talking about. :D

@ SearedIce

When I was reading "foreground" and "background" it made me think in layers. As in, having a background layer and a foreground layer and then having the picture in a layer between the two. Now, if I would have read Primary color and Secondary color that would have made more sense to me.

Anyway, nice work my friend! I will be using it quite a bit. Thank You! :D

CodeLab_reflect.png

BK_BloodSaw_sig.png

- DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day.

Link to post
Share on other sites

We changed the terminology from "foreground/background" to "primary/secondary" with our v2.5 release. The reasoning was that fg/bg had no relevance to how the colors were actually being used :)

The Paint.NET Blog: https://blog.getpaint.net/

Donations are always appreciated! https://www.getpaint.net/donate.html

forumSig_bmwE60.jpg

Link to post
Share on other sites

Ahhh, that's why I didn't understand fg/bg right away. I first came across PDN in the 2.6rc stage.

BTW, what can we be expecting in the next major release? Oh, did you get that PM reply I sent you?

BK_BloodSaw_sig.png

- DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day.

Link to post
Share on other sites
Choose your foreground and background colors in Paint.net (like the default black and white), "open" the colors window and set the "transparency-alpha" value to 0 for the foreground/background color.

Here's the steps I'm going through:

- Open image

- set prim/sec colors to b/w (click little b/w icon below left of colors)

- Open color pallet, change Transparency - Alpha to 0

- Effects/Code Lab...

- Load Source

- TransFade1.cs

- (ok)

Sometimes it fades up, sometimes it fades down. :shock: :?

How do I control that?

Thanks,

tk

Link to post
Share on other sites
Sometimes it fades up, sometimes it fades down. :shock: :?

How do I control that?

If the primary color's transparency is set to 255 and the secondary color's transparency is set to 0 you'll get a fade going from opaque to transparent.

If the primary color's transparency is set to 0 and the secondary color's transparency is set to 255 you'll get a fade going from transparent to opaque.

BK_BloodSaw_sig.png

- DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day.

Link to post
Share on other sites

Sweet image Buzzkill! Sorry for calling it foreground/background color. I only know about what to call the colors from the code, and in the code, they are "forecolor" and "backcolor" (yes, even with the sourcecode for the newer versions).

I'm so glad that this is being useful. Perhaps I will make a little dialog for it. Maybe I could expand it to be a sort of "Levels Adjustment" for alpha channels. Or, I could make that be a separate effect.

Link to post
Share on other sites

A form (dialog) with adjustable controls would be nice. Something like this maybe...

TransFade_form.png

BTW, I recently downloaded Visual Basic Express and C# Express along with the tutorial vids for both so hopefully I can start contributing to the plugins... or at least try to. :lol:

BK_BloodSaw_sig.png

- DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day.

Link to post
Share on other sites

Also, it would be nice to see the effect recognize a selection and only the selection if there is a selection present, rather than just the canvas size as it currently does. I think that should be a key feature.

Hmm, I wonder if this can be done manually by making the selection, cutting the selection out, pasting the selection onto a new layer inside a new PDN window (app), run the effect, copy it, and then pasting back it into the original image.

Checking...

Ok, it works pretty good but only if the selection has a level straight edge either on top or bottom depending on the direction of the fade. An ellipse section doesn't come out too well.

That test just made me think of another possible transparency effect in which the trasparency ran from the borders of an image (or selection) inward or outward. It would be like a frame, the image would be opaque on all sides and gradually fade to transparent in the middle of the image.

I wonder if that too can be done manually... I'll get back to you on that one.

BK_BloodSaw_sig.png

- DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day.

Link to post
Share on other sites
If the primary color's transparency is set to 255 and the secondary color's transparency is set to 0 you'll get a fade going from opaque to transparent.

If the primary color's transparency is set to 0 and the secondary color's transparency is set to 255 you'll get a fade going from transparent to opaque.

:D SWEET! Thanks, that's exactly what I needed!

Thanks,

tk

Link to post
Share on other sites
Also, it would be nice to see the effect recognize a selection and only the selection if there is a selection present, rather than just the canvas size as it currently does. I think that should be a key feature.

That test just made me think of another possible transparency effect in which the trasparency ran from the borders of an image (or selection) inward or outward. It would be like a frame, the image would be opaque on all sides and gradually fade to transparent in the middle of the image.

I totally agree with these 2 points, even if I don't know if it would be hard or not.

Of course, a dialog would be great too :)

443e54916a971.jpg
Link to post
Share on other sites
Guest
This topic is now closed to further replies.
×
×
  • Create New...