MJW Posted May 20, 2015 Share Posted May 20, 2015 (edited) This is a plugin I wrote to test a method for computing the color gradient, but which might be useful for non-testing reasons. I call it (the rather unwieldy) "Display Color Change Direction" because "color gradient" has another common meaning for plugins, and I didn't want to be confusing. The maximum direction of the color change is shown by the hue. It's in the Effects>Stylize menu. The interface is: The Color Scale controls control the color brightness. To allow for a wide range, I have coarse and fine controls. Color Range expands or compresses the range of colors. Because the colors no longer form a continuous circle, some anomalies may a occur when adjacent colors with almost the same color-change direction are colored with colors at the opposite ends of the color range. This problem can be reduced by using Reflected Color Range. Color Shift shifts the hue around the color circle. Color Phase changes which color is associated with which color-change direction. When the full range of colors is used, it duplicates the function of the Color Shift control. When used with a restricted range, the Color Shift selects which colors are used, and the Color Phase selects how the current range of colors are associated with the color change directions. Reverse Color Order reverses the order around the color circle. Full Circle assigns a direction to the color change. Normally, since the color changes as rapidly in the opposite direction, the direction of maximum color change is between 0° and 180°. When this option is set, a direction is assigned to the color, based on the change in intensity of the back-and-white image. I made True the default, both because I think the images generally look better, and because it makes the encoded color change direction correspond to the PDN color wheel. Reflected Color Range reflects the current color range so instead of the going from the beginning color to the ending color, it goes from the beginning color to the ending color at mid-range, then in the opposite order, back to the beginning color. (E.g., Red->Yellow->Green->Yellow->Red.) This makes the color range continuous around the circle of color-directions, avoiding color anomalies when using restricted color ranges. Transparent Background colors makes the background transparent instead of black. As I've mentioned, the purpose was to test the algorithm, but it can be used to produce some interesting effects. For example, the background for this sig was produced using only Clouds and this plugin: The plugin can also be used for edge detection. For example, by running the plugin, then converting to black-and-white and inverting the colors. Here is the CodeLab code: Hidden Content: // Author: MJW // Name: Display Color Change Direction // Title: Display Color Change Direction // Submenu: Stylize // Desc: Show the direction of the maximum color change as a color. // Keywords: color change direction #region UICode double Amount1 = 10; //[0, 25]Color Scale (Coarse) double Amount2 = 0; //[-1, 1]Color Scale (Fine) double Amount3 = 1.0; //[0, 2]Color Range double Amount4 = 0.0; //[0, 1]Color Shift double Amount5 = 0.0; //[0, 1]Color Phase bool Amount6 = false; //Reverse Color Order bool Amount7 = true; //Full Circle bool Amount8 = false; //Reflected Color Range bool Amount9 = false; //Transparent Background #endregion Surface Src, Dst; int maxX, maxY; double colorScale; bool maxScale; double colorShift; double colorPhase; double colorRange; double colorOrder, colorOrderAdj; bool fullCircle; bool reflectColors; bool transparentBackground; const int middleWeight = 2; const double angleScale = 1.0 / Math.PI; void Render(Surface dst, Surface src, Rectangle rect) { colorScale = 0.002 * (Amount1 + Amount2); if (colorScale < 0) colorScale = 0; maxScale = (colorScale >= 25.0); // If scale is max., display all colors at full range. colorScale *= 4.0 / (2.0 + (double)middleWeight); colorShift = Amount4; colorPhase = Amount5; colorRange = Amount3; if (Amount6) // Sign of scaling chosen to match color menu wheel. { colorOrder = -angleScale; colorOrderAdj = 1.0; } else { colorOrder = angleScale; colorOrderAdj = 0.0; } fullCircle = Amount7; reflectColors = Amount8; transparentBackground = Amount9; Src = src; Dst = dst; Rectangle selection = this.EnvironmentParameters.GetSelection(src.Bounds).GetBoundsInt(); int left = rect.Left; int right = rect.Right; int top = rect.Top; int bottom = rect.Bottom; maxX = src.Width - 1; maxY = src.Height - 1; for (int y = top; y < bottom; y++) for (int x = left; x < right; x++) dst[x, y] = FindGradientColor(x, y); } protected ColorBgra FindGradientColor(int x, int y) { ColorBgra MM, UM, UR, MR, LR, LM, LL, ML, UL; ColorBgra gradColor = ColorBgra.Black; int lX, rX, uY, lY; lX = (x == 0) ? x : x - 1; rX = (x == maxX) ? x : x + 1; uY = (y == 0) ? y : y - 1; lY = (y == maxY) ? y : y + 1; MM = Src.GetPointUnchecked(x, y); UM = Src.GetPointUnchecked(x, uY); UR = Src.GetPointUnchecked(rX, uY); MR = Src.GetPointUnchecked(rX, y); LR = Src.GetPointUnchecked(rX, lY); LM = Src.GetPointUnchecked(x, lY); LL = Src.GetPointUnchecked(lX, lY); ML = Src.GetPointUnchecked(lX, y); UL = Src.GetPointUnchecked(lX, uY); int xR = (UL.R - UR.R) + middleWeight * (ML.R - MR.R) + (LL.R - LR.R); int xG = (UL.G - UR.G) + middleWeight * (ML.G - MR.G) + (LL.G - LR.G); int xB = (UL.B - UR. + middleWeight * (ML.B - MR. + (LL.B - LR.; int yR = (UL.R - LL.R) + middleWeight * (UM.R - LM.R) + (UR.R - LR.R); int yG = (UL.G - LL.G) + middleWeight * (UM.G - LM.G) + (UR.G - LR.G); int yB = (UL.B - LL. + middleWeight * (UM.B - LM. + (UR.B - LR.; int xDelta, yDelta, mag2; // The straight-forward implementation. // The change in each color component can either be consdered positive or negative. // Since changing all the signs won't change the magnitude of the change, red is // fixed and blue and green can have either sign. // Compute all four versions and choose the on that gives the largest magnitude. int xDeltaA, yDeltaA, xDeltaB, yDeltaB, xDeltaC, yDeltaC; int mag2A, mag2B, mag2C; xDelta = xR + xG + xB; yDelta = yR + yG + yB; xDeltaA = xR + xG - xB; yDeltaA = yR + yG - yB; xDeltaB = xR - xG + xB; yDeltaB = yR - yG + yB; xDeltaC = xR - xG - xB; yDeltaC = yR - yG - yB; mag2 = xDelta * xDelta + yDelta * yDelta; mag2A = xDeltaA * xDeltaA + yDeltaA * yDeltaA; mag2B = xDeltaB * xDeltaB + yDeltaB * yDeltaB; mag2C = xDeltaC * xDeltaC + yDeltaC * yDeltaC; // Use the one with the largest magnitude. if (mag2A > mag2) { xDelta = xDeltaA; yDelta = yDeltaA; mag2 = mag2A; } if (mag2C > mag2B) { xDeltaB = xDeltaC; yDeltaB = yDeltaC; mag2B = mag2C; } if (mag2B > mag2) { xDelta = xDeltaB; yDelta = yDeltaB; mag2 = mag2B; } if (mag2 == 0) { return transparentBackground ? ColorBgra.Transparent : ColorBgra.Black; } else { // Adjust sign of deltas so yDelta >= 0. This will produce an ATan between 0 and PI. if (yDelta < 0) { xDelta = -xDelta; yDelta = -yDelta; } double magnitude = Math.Sqrt((double)mag2); double xComponent = xDelta / magnitude; double yComponent = yDelta / magnitude; double value = maxScale ? 1.0 : Math.Min(1.0, colorScale * magnitude); // 0 <= hue <= 1.0 double hue = colorOrder * Math.Atan2(yComponent, xComponent) + colorOrderAdj; // If full circle, use the intensity to determine the direction. if (fullCircle) { hue *= 0.5; double intensity = xComponent * (xR + xG + xB) + yComponent * (yR + yG + yB); if (intensity > 0.0) hue += 0.5; } // Adjust the phase before restricting the range. hue += colorPhase; if (hue >= 1.0) hue -= 1.0; // Reflected colors match at the endpoints for better restricted range colors. if (reflectColors) { hue *= 2.0; if (hue > 1.0) hue = 2.0 - hue; } hue = colorRange * hue + colorShift; gradColor = transparentBackground ? HSVtoRGBA(hue, 1.0, 1.0, value) : HSVtoRGB(hue, 1.0, value); return gradColor; } } public ColorBgra HSVtoRGBA(double H, double S, double V, double A) { byte r, g, b; HSVtoRGB(H, S, V, out r, out g, out ; return ColorBgra.FromBgra(b, g, r, (byte)(255 * A + 0.5)); } public ColorBgra HSVtoRGB(double H, double S, double V) { byte r, g, b; HSVtoRGB(H, S, V, out r, out g, out ; return ColorBgra.FromBgr(b, g, r); } public void HSVtoRGB(double H, double S, double V, out byte bR, out byte bG, out byte bB) { // Parameters must satisfy the following ranges: // 0.0 <= H < 1.0 // 0.0 <= S <= 1.0 // 0.0 <= V <= 1.0 // Handle special case of gray (so no Hue) first if ((S == 0.0) || (V == 0.0)) { byte x = (byte)(int)(V * 255.0); bR = x; bG = x; bB = x; return; } H = HueConstrain(H); double R = V, G = V, B = V; double Hi = Math.Floor(6.0 * H); double f = 6.0 * H - Hi; double p = V * (1.0 - S); double q = V * (1.0 - f * S); double t = V * (1.0 - (1.0 - f) * S); if (Hi == 0.0) { R = V; G = t; B = p; } else if (Hi == 1.0) { R = q; G = V; B = p; } else if (Hi == 2.0) { R = p; G = V; B = t; } else if (Hi == 3.0) { R = p; G = q; B = V; } else if (Hi == 4.0) { R = t; G = p; B = V; } else // if (Hi == 5.0) { R = V; G = p; B = q; } int iR = (int)(R * 255.0 + 0.5); int iG = (int)(G * 255.0 + 0.5); int iB = (int)(B * 255.0 + 0.5); bR = (byte)iR; bG = (byte)iG; bB = (byte)iB; } public double HueConstrain(double MyHue) { // Makes sure that 0.0 <= MyAngle < 1.0 // Wraps around the value if its outside this range while (MyHue >= 1.0) { MyHue -= 1.0; } while (MyHue < 0.0) { MyHue += 1.0; } return MyHue; } Here's the (not especially attractive!) icon: Here is the plugin: DisplayColorChangeDirection.zip EDIT: Fixed spelling of "Coarse" (H/T, Djisves). Changed version to 1.1. EDIT: Restored icon, which I forgot in the previous version (sorry about that). Changed version to 1.2. EDIT: Added Color Range control. Changed version to 1.3. EDIT: Added Color Phase control. Changed version to 1.4. EDIT: Removed mostly unnecessary Middle Weight and Original Image controls. Replaced (at Eli's suggestion) White Background with Transparent Background. Added Reflected Color Range for improved colors when using restricted ranges. Changed version to 2.0. Edited February 9, 2018 by toe_head2001 Fixed broken Photobucket images 7 Quote Link to comment Share on other sites More sharing options...
nitenurse79 Posted May 20, 2015 Share Posted May 20, 2015 <snip> Quote Link to comment Share on other sites More sharing options...
Maximilian Posted May 20, 2015 Share Posted May 20, 2015 This one I have managed to successfully compile and use on PdN 3.5.11 I'll give it a better try later on but in the meantime I like the preliminary results I've obtained. Thanks for sharing, MJW! 1 Quote Link to comment Share on other sites More sharing options...
Djisves Posted May 21, 2015 Share Posted May 21, 2015 Interesing plugin MJW, thank you for sharing. Of course, you meant "coarse". Quote Link to comment Share on other sites More sharing options...
MJW Posted May 21, 2015 Author Share Posted May 21, 2015 Thanks, Djisves. The spelling is now corrected. Quote Link to comment Share on other sites More sharing options...
Seerose Posted May 21, 2015 Share Posted May 21, 2015 MJW! Thank you very much for plugin, and for your effort. Quote Live as if you were to die tomorrow. Learn as if you were to live forever. Gandhi Link to comment Share on other sites More sharing options...
MJW Posted May 21, 2015 Author Share Posted May 21, 2015 1 Quote Link to comment Share on other sites More sharing options...
Red ochre Posted May 21, 2015 Share Posted May 21, 2015 I think you need a snappier name though! (Used TR'sContour Filler on the text object first - background from clouds zoomed in) 3 Quote Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings Link to comment Share on other sites More sharing options...
MJW Posted May 21, 2015 Author Share Posted May 21, 2015 The name is pretty lame. I originally called it "Display Color Gradient," which is slightly better, but not much snappier. For the released version, I thought if I kept the original name, people might think it rendered a color gradient. For reasons I won't go into here, I was in a hurry to release it, and went with the first semi-sensible name that came to mind. Quote Link to comment Share on other sites More sharing options...
Ego Eram Reputo Posted May 21, 2015 Share Posted May 21, 2015 If a descriptive name doesn't pop into your thoughts try an offbeat one. "Rainbow Eye Bleed" - because it makes my eyes whimper.... 1 Quote ebook: Mastering Paint.NET | resources: Plugin Index | Stereogram Tut | proud supporter of Codelab plugins: EER's Plugin Pack | Planetoid | StickMan | WhichSymbol+ | Dr Scott's Markup Renderer | CSV Filetype | dwarf horde plugins: Plugin Browser | ShapeMaker Link to comment Share on other sites More sharing options...
Red ochre Posted May 21, 2015 Share Posted May 21, 2015 "Bacillus" ? - should put it close to the top the Stylize Submenu too! Quote Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings Link to comment Share on other sites More sharing options...
MJW Posted May 22, 2015 Author Share Posted May 22, 2015 (edited) "Rainbow Eye Bleed" - because it makes my eyes whimper.... For those who want a bit more subtlety in their images, I added a Color Range feature. Here is an example of plugin applied with a restricted range to Clouds: Here It's applied to Clouds processed with Dents: There's sometimes somewhat of a problem with color-direction angle wrap-around producing stray pixels that contrast with the surrounding region, because unlike the full color wheel, the boundary colors don't connect continuously. This can result in two pixels with nearly that same color gradient being colored with colors at the opposite ends of the color range. I thought about some options, such as reflecting the color range on either side of the range of direction angles, but decided to leave it as it was. I think it's still a useful feature. I'm not so sure that the ability to expand the range is useful or makes sense, but I left it in, in case it is and does. Edited May 22, 2015 by MJW Quote Link to comment Share on other sites More sharing options...
Lloyd Posted May 22, 2015 Share Posted May 22, 2015 So exactly how does this plugin work ? I have tried it on after running clouds using yellow and red for my colours and I don't get anything like the images posted here. 1 Quote Link to comment Share on other sites More sharing options...
sashwilko Posted May 22, 2015 Share Posted May 22, 2015 I can't get any result out of it either except a faded blob of two or three colours and I would like to think I am fairly good using pdn. I have even tried it on photo's with no decent result. Quote Link to comment Share on other sites More sharing options...
nitenurse79 Posted May 22, 2015 Share Posted May 22, 2015 Same here Lloyd and Sasha. I get zero results too, so i just deleted it. Quote Link to comment Share on other sites More sharing options...
MJW Posted May 22, 2015 Author Share Posted May 22, 2015 I added a Color Phase control to give more control when using restricted color ranges. Quote Link to comment Share on other sites More sharing options...
MJW Posted May 22, 2015 Author Share Posted May 22, 2015 (edited) Assuming I didn't somehow zip up and upload the wrong DLL (and I don't think I did), I can't imagine what those not getting results are doing wrong. If you run Clouds with the default settings, then run my Display Color Change Direction plugin with its default settings, you should get a bright pattern of colors. The plugin obviously worked for Seerose and Red ochre. EDIT: I just downloaded and installed the plugin attached in my lead post (Version 1.4), and it worked perfectly (or at least as perfectly as it works). Edited May 24, 2015 by MJW Quote Link to comment Share on other sites More sharing options...
Seerose Posted May 22, 2015 Share Posted May 22, 2015 Very good plugin. Thanks again MJW. Quote Live as if you were to die tomorrow. Learn as if you were to live forever. Gandhi Link to comment Share on other sites More sharing options...
MJW Posted May 22, 2015 Author Share Posted May 22, 2015 Very nice, Seerose!. See all you doubters, it works! Quote Link to comment Share on other sites More sharing options...
MJW Posted May 22, 2015 Author Share Posted May 22, 2015 Here's an image produced using (as I recall) Clouds, Ripples, and Dents: Quote Link to comment Share on other sites More sharing options...
Eli Posted May 22, 2015 Share Posted May 22, 2015 Thanks MJW It works for me too. I wonder if a transparent (alpha) background option could be added (just like white background) 2 Quote Link to comment Share on other sites More sharing options...
MJW Posted May 22, 2015 Author Share Posted May 22, 2015 (edited) So exactly how does this plugin work ? I have tried it on after running clouds using yellow and red for my colours and I don't get anything like the images posted here. Though you can run it on colored Clouds and it will still work, you can run it on black-and-white Clouds, also. The colors it generates don't directly depend on the colors of image. The colors are chosen based on the direction which the image color most rapidly changes; for black and white images, that's the direction the intensity most rapidly changes. The color-change direction is determined by looking at the pixel's eight neighbors. Edited May 22, 2015 by MJW Quote Link to comment Share on other sites More sharing options...
MJW Posted May 22, 2015 Author Share Posted May 22, 2015 (edited) I wonder if a transparent (alpha) background option could be added (just like white background) That sounds like a good idea. I'll probably do that. EDIT: I wonder if it would be better to just replace the White Background option with the Transparent Background option. I'm not sure the white background is so generally useful that it needs a special option. If the user wants a white background, it might be better to just add a white background layer and use the transparent option. If there are any opinions on this, I'd appreciate hearing them. If there are no opinions otherwise, I'll probably remove White Background when I add Transparent Background. Edited May 22, 2015 by MJW Quote Link to comment Share on other sites More sharing options...
Eli Posted May 23, 2015 Share Posted May 23, 2015 Removing White Background and replacing it for Transparent Background would work for me. Quote Link to comment Share on other sites More sharing options...
Djisves Posted May 23, 2015 Share Posted May 23, 2015 ... EDIT: I wonder if it would be better to just replace the White Background option with the Transparent Background option.... This. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.