BoltBait Posted January 29, 2015 Posted January 29, 2015 As requested here... https://forums.getpaint.net/topic/31461-plugin-request-inner-drop-shadow/ Object Inner Shadow Plugin Download here for latest version: https://forums.getpaint.net/BoltBaitPluginPack Download here for Paint.NET 3.5.11: InnerShadow3511.zip I'll edit in a nice description of this later when I'm not so tired. You all know what to do. For the curious... (This does NOT work in CodeLab, sorry): Spoiler using System; using System.Linq; using System.Text; using System.Windows; using System.Drawing; using Microsoft.Win32; using System.Reflection; using System.Drawing.Text; using System.Windows.Forms; using System.Collections.Generic; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; using PaintDotNet; using PaintDotNet.Effects; using PaintDotNet.AppModel; using PaintDotNet.IndirectUI; using PaintDotNet.Collections; using PaintDotNet.PropertySystem; [assembly: AssemblyTitle("Inner Shadow Plugin for Paint.NET")] [assembly: AssemblyDescription("Apply inner shadow to objects.")] [assembly: AssemblyConfiguration("inner|shadow|bevel")] [assembly: AssemblyCompany("BoltBait")] [assembly: AssemblyProduct("Inner Shadow")] [assembly: AssemblyCopyright("Copyright © BoltBait")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] [assembly: AssemblyVersion("3.0.*")] namespace InnerShadowEffect { public class PluginSupportInfo : IPluginSupportInfo { public string Author { get { return ((AssemblyCopyrightAttribute)base.GetType().Assembly.GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false)[0]).Copyright; } } public string Copyright { get { return ((AssemblyDescriptionAttribute)base.GetType().Assembly.GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false)[0]).Description; } } public string DisplayName { get { return ((AssemblyProductAttribute)base.GetType().Assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false)[0]).Product; } } public Version Version { get { return base.GetType().Assembly.GetName().Version; } } public Uri WebsiteUri { get { return new Uri("http://www.BoltBait.com/pdn"); } } } [PluginSupportInfo(typeof(PluginSupportInfo), DisplayName = "Inner Shadow")] public class InnerShadowEffectPlugin : PropertyBasedEffect { public static string StaticName { get { return "Inner Shadow"; } } public static Image StaticIcon { get { return new Bitmap(typeof(InnerShadowEffectPlugin), "InnerShadow.png"); } } public static string SubmenuName { get { return "Object"; } } public InnerShadowEffectPlugin() : base(StaticName, StaticIcon, SubmenuName, EffectFlags.Configurable) { } public enum PropertyNames { Amount1, Amount2, Amount3, Amount4, Amount5, Amount6 } protected override PropertyCollection OnCreatePropertyCollection() { List<Property> props = new List<Property>(); props.Add(new DoubleProperty(PropertyNames.Amount1, -45, -180, +180)); props.Add(new Int32Property(PropertyNames.Amount2, 10, 1, 100)); props.Add(new Int32Property(PropertyNames.Amount3, 2, 0, 50)); props.Add(new DoubleProperty(PropertyNames.Amount4, 0.8, 0, 1)); props.Add(new Int32Property(PropertyNames.Amount5, ColorBgra.ToOpaqueInt32(ColorBgra.Black), 0, 0xffffff)); props.Add(new BooleanProperty(PropertyNames.Amount6, true)); return new PropertyCollection(props); } protected override ControlInfo OnCreateConfigUI(PropertyCollection props) { ControlInfo configUI = CreateDefaultConfigUI(props); configUI.SetPropertyControlValue(PropertyNames.Amount1, ControlInfoPropertyNames.DisplayName, "Light Angle"); configUI.SetPropertyControlType(PropertyNames.Amount1, PropertyControlType.AngleChooser); configUI.SetPropertyControlValue(PropertyNames.Amount2, ControlInfoPropertyNames.DisplayName, "Shadow Length"); configUI.SetPropertyControlValue(PropertyNames.Amount3, ControlInfoPropertyNames.DisplayName, "Blur Radius"); configUI.SetPropertyControlValue(PropertyNames.Amount4, ControlInfoPropertyNames.DisplayName, "Shadow Strength"); configUI.SetPropertyControlValue(PropertyNames.Amount4, ControlInfoPropertyNames.SliderLargeChange, 0.25); configUI.SetPropertyControlValue(PropertyNames.Amount4, ControlInfoPropertyNames.SliderSmallChange, 0.05); configUI.SetPropertyControlValue(PropertyNames.Amount4, ControlInfoPropertyNames.UpDownIncrement, 0.01); configUI.SetPropertyControlValue(PropertyNames.Amount4, ControlInfoPropertyNames.ControlColors, new ColorBgra[] { ColorBgra.White, ColorBgra.Black }); configUI.SetPropertyControlValue(PropertyNames.Amount5, ControlInfoPropertyNames.DisplayName, "Shadow Color"); configUI.SetPropertyControlType(PropertyNames.Amount5, PropertyControlType.ColorWheel); configUI.SetPropertyControlValue(PropertyNames.Amount6, ControlInfoPropertyNames.DisplayName, string.Empty); configUI.SetPropertyControlValue(PropertyNames.Amount6, ControlInfoPropertyNames.Description, "Keep original image"); return configUI; } protected override void OnSetRenderInfo(PropertyBasedEffectConfigToken newToken, RenderArgs dstArgs, RenderArgs srcArgs) { this.Amount1 = newToken.GetProperty<DoubleProperty>(PropertyNames.Amount1).Value; this.Amount2 = newToken.GetProperty<Int32Property>(PropertyNames.Amount2).Value; this.Amount3 = newToken.GetProperty<Int32Property>(PropertyNames.Amount3).Value; this.Amount4 = newToken.GetProperty<DoubleProperty>(PropertyNames.Amount4).Value; this.Amount5 = ColorBgra.FromOpaqueInt32(newToken.GetProperty<Int32Property>(PropertyNames.Amount5).Value); this.Amount6 = newToken.GetProperty<BooleanProperty>(PropertyNames.Amount6).Value; // Save time by only calculating this stuff when necessary. // This makes the UI much more responsive. if (scratch1 == null) { scratch1 = new Surface(dstArgs.Size); scratch1.Clear(ColorBgra.Black); for (int y = 0; y < srcArgs.Height; y++) { for (int x = 0; x < srcArgs.Width; x++) { if (srcArgs.Surface[x, y].A != 0) { scratch1[x, y] = ColorBgra.Transparent; } } } } if (scratch2 == null) { scratch2 = new Surface(dstArgs.Size); PreviousDistance = 0; PreviousAngle = -999; } if ((PreviousAngle != Amount1) || (PreviousDistance != Amount2)) { // Setup for calling the Motion Blur effect MotionBlurEffect mblurEffect = new MotionBlurEffect(); PropertyCollection mblurProps = mblurEffect.CreatePropertyCollection(); PropertyBasedEffectConfigToken mBlurParameters = new PropertyBasedEffectConfigToken(mblurProps); mBlurParameters.SetPropertyValue(MotionBlurEffect.PropertyNames.Angle, Amount1); mBlurParameters.SetPropertyValue(MotionBlurEffect.PropertyNames.Centered, false); mBlurParameters.SetPropertyValue(MotionBlurEffect.PropertyNames.Distance, Amount2); mblurEffect.SetRenderInfo(mBlurParameters, new RenderArgs(scratch2), new RenderArgs(scratch1)); // Call the Motion Blur function mblurEffect.Render(new Rectangle[1] { scratch1.Bounds }, 0, 1); PreviousAngle = Amount1; PreviousDistance = Amount2; } base.OnSetRenderInfo(newToken, dstArgs, srcArgs); } protected override void OnCustomizeConfigUIWindowProperties(PropertyCollection props) { // Change the effect's window title props[ControlInfoPropertyNames.WindowTitle].Value = "BoltBait's Object Inner Shadow v3.0"; base.OnCustomizeConfigUIWindowProperties(props); } protected override unsafe void OnRender(Rectangle[] rois, int startIndex, int length) { if (length == 0) return; for (int i = startIndex; i < startIndex + length; ++i) { Render(DstArgs.Surface, SrcArgs.Surface, rois[i]); } } #region User Entered Code // Title: BoltBait's Object Inner Shadow v3.0 // Author: BoltBait // Submenu: Object // Name: Inner Shadow // URL: http://www.BoltBait.com/pdn // Desc: Apply inner shadow to objects // Keywords: Inner|Shadow #region UICode double Amount1 = -45; // [-180,180] Angle int Amount2 = 10; // [1,100] Distance int Amount3 = 2; // [0,25] Blur Radius double Amount4 = 0.8; // [0,1] Density ColorBgra Amount5 = ColorBgra.FromBgr(0, 0, 0); // Shadow Color bool Amount6 = true; // [0,1] Keep original image #endregion // Let's speed up the rendering by only calculating what changes int PreviousDistance = 0; double PreviousAngle = -999; // Setup 2 scratch surfaces private Surface scratch1 = null; private Surface scratch2 = null; // Setup for using Normal blend op private BinaryPixelOp normalOp = LayerBlendModeUtil.CreateCompositionOp(LayerBlendMode.Normal); //private BinaryPixelOp normalOp = new UserBlendOps.NormalBlendOp(); // Here is the main render loop function unsafe void Render(Surface dst, Surface src, Rectangle rect) { byte A; byte BA; // Setup for calling the Blur effect GaussianBlurEffect blurEffect = new GaussianBlurEffect(); PropertyCollection blurProps = blurEffect.CreatePropertyCollection(); PropertyBasedEffectConfigToken BlurParameters = new PropertyBasedEffectConfigToken(blurProps); BlurParameters.SetPropertyValue(GaussianBlurEffect.PropertyNames.Radius, Amount3); blurEffect.SetRenderInfo(BlurParameters, new RenderArgs(dst), new RenderArgs(scratch2)); // Call the Gaussian Blur function blurEffect.Render(new Rectangle[1] { rect }, 0, 1); for (int y = rect.Top; y < rect.Bottom; y++) { if (IsCancelRequested) return; ColorBgra* srcPtr = src.GetPointAddressUnchecked(rect.Left, y); ColorBgra* dstPtr = dst.GetPointAddressUnchecked(rect.Left, y); for (int x = rect.Left; x < rect.Right; x++) { ColorBgra CurrentPixel = *srcPtr; A = CurrentPixel.A; ColorBgra BlackPixel = *dstPtr; BA = (byte)(BlackPixel.A * Amount4); BlackPixel = Amount5; BlackPixel.A = BA; if (Amount6) { CurrentPixel = normalOp.Apply(CurrentPixel, BlackPixel); CurrentPixel.A = A; } else { CurrentPixel = BlackPixel; CurrentPixel.A = Math.Min(A, BlackPixel.A); } *dstPtr = CurrentPixel; srcPtr++; dstPtr++; } } } #endregion } } History: v1.0 - Initial Release v2.0 - Speed up rendering for all but the first two controls v3.0 - Corrected "keep only shadow" alpha calculation 9 Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
Cc4FuzzyHuggles Posted January 29, 2015 Posted January 29, 2015 Beautiful! Thank you so much! Quote *~ Cc4FuzzyHuggles Gallery ~*
Red ochre Posted January 29, 2015 Posted January 29, 2015 U.I. looks good, results look good and thanks for the source code too. (I'll try and compile it to run on 3.5.11 ) 1 Quote Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings
TechnoRobbo Posted January 29, 2015 Posted January 29, 2015 Nice compact code!! Excellent job! Works to perfection!! 1 Quote Go out there and be amazing. Have Fun, TRSome Pretty Pictures Some Cool Plugins
Seerose Posted January 29, 2015 Posted January 29, 2015 (edited) @BoltBait! Thanks and respect for hard work. Edited January 29, 2015 by Seerose 1 Quote Live as if you were to die tomorrow. Learn as if you were to live forever. Gandhi
sashwilko Posted January 29, 2015 Posted January 29, 2015 Fun plugin BoltBait. Thank you from me too. Here is a quick play. 3 Quote
BoltBait Posted January 29, 2015 Author Posted January 29, 2015 Nice compact code!! Coming from the Plugin of the Year Author, you're making me blush. Thanks. Nice pics everyone! Glad you like it. I'm going to try to speed it up before I put it into my plugin pack. Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
Ego Eram Reputo Posted January 30, 2015 Posted January 30, 2015 Brilliant plugin. Easy to use and so obvious when you think about it. Drop Shadow's twin 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
BoltBait Posted January 30, 2015 Author Posted January 30, 2015 OK, so all 32 people that downloaded the first version, time to upgrade! Updates: -The first 2 controls in the UI take some time to calculate, same as before. -The other controls in the UI are MUCH faster. Please test the hell out of it. If it looks good, I'll add it to my plugin pack. Wut? Well, if you change either Angle or Distance the calculations are done in a single thread... so it is slow. If you change the other controls the calculations are done in multiple threads... so the calculations are faster. This is a change from the first version where ALL the calculations were done in a single thread. Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
Cc4FuzzyHuggles Posted January 30, 2015 Posted January 30, 2015 Hello. I really like the faster speeds for some of the settings, the plugin is looking better and better. Here is some more feedback though...Most of the plugin is looking pretty good, I love all of the available settings and features it has to offer. But I do want to point out that the option to keep only the shadow (uncheck "keep original image") gives the shadow rough outer edges. Quote *~ Cc4FuzzyHuggles Gallery ~*
BoltBait Posted January 30, 2015 Author Posted January 30, 2015 I do want to point out that the option to keep only the shadow (uncheck "keep original image") gives the shadow rough outer edges. If only there was a plugin to... uh... feather those edges. I'm afraid that this is just something you'll have to learn to live with. There is no easy way to calculate a proper edge alpha. Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
Cc4FuzzyHuggles Posted January 30, 2015 Posted January 30, 2015 (edited) Since the shadow has a blur to it, when you apply feather it takes away the hard outer edge, which then lessens the “inner shadow" appearance and gives the shadow an overall blurry appearance. Other edge smoothing plugins don't seem to smooth just the hard outer edge either, they smooth everything, which effects the "inner shadow" area.Here is a sample image of trying to use feather. I really like the feature to have the shadow only, as it allows me to place objects under the shadow layer and make cool layering effects. Edited January 30, 2015 by Cc4FuzzyHuggles Quote *~ Cc4FuzzyHuggles Gallery ~*
skullbonz Posted January 30, 2015 Posted January 30, 2015 I see it only works on the latest version of pdn. Quote http://forums.getpaint.net/index.php?/topic/21233-skullbonz-art-gallery
BoltBait Posted January 30, 2015 Author Posted January 30, 2015 I see it only works on the latest version of pdn. I compiled it against 4.0. So it should work on 4.0+. It contains certain features that are only supported on 4.0, so that's the reason. I posted the source, so you can try to change it to work on 3.5.11 if you like. 1 Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
Cc4FuzzyHuggles Posted January 30, 2015 Posted January 30, 2015 (edited) I'm afraid that this is just something you'll have to learn to live with. There is no easy way to calculate a proper edge alpha. It's a shame to hear that. I was hoping for an all in one plugin. I thought some kind of anti-aliasing might be possible or some kind of one-sided AA's assistant thing. I wasn't thinking to add more settings, just a behind the scenes edge smoothing processes. But alright, I guess the Alpha Mask plugin is still going to be my best friend for cutting off ugly edges. Edited January 30, 2015 by Cc4FuzzyHuggles Quote *~ Cc4FuzzyHuggles Gallery ~*
BoltBait Posted January 30, 2015 Author Posted January 30, 2015 I do want to point out that the option to keep only the shadow (uncheck "keep original image") gives the shadow rough outer edges. There is no easy way to calculate a proper edge alpha. Turns out that was a lie. I have a solution to that problem. I'll post a fix tonight. I see it only works on the latest version of pdn. I'll post a version for 3.5.11 tonight. Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
BoltBait Posted January 31, 2015 Author Posted January 31, 2015 Turns out that was a lie. I have a solution to that problem. I'll post a fix tonight. Posted. I'll post a version for 3.5.11 tonight. Posted. Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
Seerose Posted January 31, 2015 Posted January 31, 2015 Thank you for these (new) wonderful plugins, and for the effort. Quote Live as if you were to die tomorrow. Learn as if you were to live forever. Gandhi
Red ochre Posted January 31, 2015 Posted January 31, 2015 Many thanks, especially for the 3.5.11 version. Quote Red ochre Plugin pack.............. Diabolical Drawings ................Real Paintings
Eli Posted January 31, 2015 Posted January 31, 2015 Thanks! It is going to be a favorite for its flexibility. Thanks for includding the requested options. The last version renders very fast. Quote
Cc4FuzzyHuggles Posted January 31, 2015 Posted January 31, 2015 Using the shadow only is MUCH better, very nice! Thank you very much for making this plugin and continuing to improve it. Quote *~ Cc4FuzzyHuggles Gallery ~*
BoltBait Posted January 31, 2015 Author Posted January 31, 2015 I just added a similar plugin to my plugin pack. Only this one bases the shadow on the selection outline (Marching Ants). The only place to get it is in my plugin pack. Enjoy. 1 Quote Download: BoltBait's Plugin Pack | CodeLab | and a Free Computer Dominos Game
barbieq25 Posted February 5, 2015 Posted February 5, 2015 Oooh! See what I missed when I was out in the wilderness! Thanks heaps 1 Quote Knowledge is no burden to carry. April Jones, 2012 Gallery My DA Gallery
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.