SearedIce Posted March 30, 2006 Share Posted March 30, 2006 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 comment Share on other sites More sharing options...
Rick Brewster Posted March 30, 2006 Share Posted March 30, 2006 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 Link to comment Share on other sites More sharing options...
SearedIce Posted March 30, 2006 Author Share Posted March 30, 2006 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 comment Share on other sites More sharing options...
SearedIce Posted March 30, 2006 Author Share Posted March 30, 2006 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 comment Share on other sites More sharing options...
Rick Brewster Posted March 30, 2006 Share Posted March 30, 2006 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 Link to comment Share on other sites More sharing options...
SearedIce Posted March 31, 2006 Author Share Posted March 31, 2006 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 comment Share on other sites More sharing options...
BuzzKill Posted March 31, 2006 Share Posted March 31, 2006 The script runs beautifully So does this mean you have a working script now? If so, where can we get it? *EDIT* Or, can you post the complete sequence of code? - DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day. Link to comment Share on other sites More sharing options...
Litchi Posted March 31, 2006 Share Posted March 31, 2006 So does this mean you have a working script now? If so, where can we get it? *EDIT* Or, can you post the complete sequence of code? I agree, it would be nice to have it Link to comment Share on other sites More sharing options...
SearedIce Posted April 1, 2006 Author Share Posted April 1, 2006 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 comment Share on other sites More sharing options...
Litchi Posted April 1, 2006 Share Posted April 1, 2006 It works well I could make a transparent fading reflection for my avatar orb (the fading isn't really visible, but it is here) Link to comment Share on other sites More sharing options...
SearedIce Posted April 1, 2006 Author Share Posted April 1, 2006 Sweet! Looks great! Now I should find another Effect to code... Link to comment Share on other sites More sharing options...
BuzzKill Posted April 2, 2006 Share Posted April 2, 2006 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? - DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day. Link to comment Share on other sites More sharing options...
SearedIce Posted April 2, 2006 Author Share Posted April 2, 2006 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 comment Share on other sites More sharing options...
BuzzKill Posted April 2, 2006 Share Posted April 2, 2006 Where do I set them at? In the code itself? If so, what line(s) of code? - DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day. Link to comment Share on other sites More sharing options...
Litchi Posted April 2, 2006 Share Posted April 2, 2006 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 Link to comment Share on other sites More sharing options...
BuzzKill Posted April 2, 2006 Share Posted April 2, 2006 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. @ 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! - DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day. Link to comment Share on other sites More sharing options...
Rick Brewster Posted April 2, 2006 Share Posted April 2, 2006 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 Link to comment Share on other sites More sharing options...
BuzzKill Posted April 3, 2006 Share Posted April 3, 2006 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? - DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day. Link to comment Share on other sites More sharing options...
tk Posted April 3, 2006 Share Posted April 3, 2006 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 comment Share on other sites More sharing options...
BuzzKill Posted April 3, 2006 Share Posted April 3, 2006 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. - DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day. Link to comment Share on other sites More sharing options...
SearedIce Posted April 3, 2006 Author Share Posted April 3, 2006 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 comment Share on other sites More sharing options...
BuzzKill Posted April 3, 2006 Share Posted April 3, 2006 A form (dialog) with adjustable controls would be nice. Something like this maybe... 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. - DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day. Link to comment Share on other sites More sharing options...
BuzzKill Posted April 3, 2006 Share Posted April 3, 2006 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. - DO NOT contact me asking for the .pdn of my avatar or the PDN logo. Thank you. Have a nice day. Link to comment Share on other sites More sharing options...
tk Posted April 3, 2006 Share Posted April 3, 2006 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. SWEET! Thanks, that's exactly what I needed! Thanks, tk Link to comment Share on other sites More sharing options...
Litchi Posted April 4, 2006 Share Posted April 4, 2006 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 Link to comment Share on other sites More sharing options...
Recommended Posts