Paint.NET finally gets error handling for plugins

For the longest time, any unhandled exception in Paint.NET caused a generic “Oops sorry, go check the crash log on your desktop” error dialog. It’s not really that helpful, and it always points the blame in my direction even when it’s a plugin’s fault.

So, for v3.20 there is a real error dialog for this! If you’re running an effect or adjustment plugin and it doesn’t handle an exception, you’ll get the following dialog instead.

(quick digression: yes, command link buttons in v3.20 now look more like “real” command link buttons in Vista)

Clicking on the Error Details button will show the user details such as the file name of the plugin, its name, and the exception text. If the author implements a [PluginSupportInfo] attribute tag on the effect type and/or assembly, then additional information will be displayed such as author, copyright, and website URL.

If a plugin fails to load, you’ll get this:

Clicking on it reveals the reason why, although this text is really meant to serve as diagnostic information for the plugin author. I don’t expect non-developers to care about most of this except for maybe the file name.

In this case, Ed’s Surface Blur effect was deriving from a class in PaintDotNet.Effects.dll that was really only supposed to be used internally, and that is now using a different base class in v3.20. So his code is all confused and he will need to release an update. The other 10+ effects in his DLL’s still work fine though 🙂

Anyway, hopefully this will relieve my inbox a little and I won’t receive crash reports for plugins anymore.


Lots of small donations = Suspicious?

Over the last several weeks I’ve been receiving a barrage of very small donations from a single person. They range in size from $0.01 USD to $0.05 USD, and the PayPal transaction fee results in a net of $0.00 for me. It’s obviously very suspicious, and my bet is that this individual is trying to artificially inflate their PayPal or eBay reputation. What better way to get a very high reputation than to have a lot of successful payments? Or, maybe they’re trying to inflate my reputation? I don’t get it.

Has anyone else seen similar activity?

Fixed Ratio and Fixed Size selections

You asked for it, and now you’re going to get it. This is currently the most passionately requested feature for Paint.NET, and I’ve just finished writing it for the v3.20 release.

This will make it easy, for instance, to select a 4 inch X 6 inch area. Or to do 16×9 ratio cropping to create wallpapers for that awesome widescreen TV you just bought. I have also added a toolbar split-button for selecting the selection combine mode. This does not add new functionality to Paint.NET but does increase the discoverability of this feature, and also ensures some consistency.

The Magic Wand and Paint Bucket tools also get a toolbar button for choosing Contiguous vs. Global flood. Again, this isn’t adding new functionality but falls into the area of making an existing feature more discoverable. I haven’t found a pair of icons that I really like for this yet, so the lightning bolt and globe are currently just stand-ins:

Epica – A Winamp Visualization Plugin from 2001, by Me

This post is completely unrelated to Paint.NET. Well, sort of.

Back in college I spent a lot of time working on a graphics library in C++, which I used to write a visualization plugin for Winamp. It was known by the name “Quasar” until I released it publicly and renamed it to “Epica” and bumped the version tag to 2.0. The second and last release was version 2.10 and it accumulated about 250,000 downloads on before I took it down in 2002.

Well, the other day I tracked down the Epica installer from my old college-hosted website. I installed the latest version of Winamp, which I think is 5.6789 or something weird, and to my surprise, my plugin still worked! It looks great on the media center PC at 1920 x 1080 on my new Samsung LN-T4671F TV (46″ LCD, absolutely beautiful thing).

The official requirements are Winamp 2.xx or newer, a few extra megabytes of memory, and a Pentium with MMX. I recommend you have at least a Pentium III, which these days shouldn’t really be a problem. By default it will probably try to run at 800×600 so I recommend going into the configuration settings and cranking up the resolution! I’ve posted a download link at the bottom of this blog post.

One of the cool things about Epica is that it gives you a lot of interactive control over the visuals. Press F1 while the thing is running and you’ll get a full page listing of all the keyboard controls. Oh, and you can even use a joystick for some of the stuff which I believe is documented in the README.TXT file. The idea is that it will try to do a good job automatically reacting to the music, but if you really want to put on a show then you can call the shots in real-time.

I actually used this for visuals at a student-body sponsored rave at WSU, called “Fusion II”, in 2001. This thing was projected up on a huge wall powered by my 800 MHz Pentium III and the awesome live music being performed by the likes of DJ Dan and Donald Glaude. There were a lot of people in the CUB Ballroom that night, and the plugin, as well as the other visuals I was doing, was a hit. They asked me to do the visuals the next year at Fusion 3 but I had to decline so I would have time to finish my junior-year Computer Science 360 project (“File Systems”). So that means I finished up Epica when I was a sophomore at WSU.

In total, the plugin comprised over 30,000 lines of C++ and inline assembly code. I learned a lot about computer graphics and performance programming, as well as software development and usability. I used assembly language so I could get at MMX and SSE where I was able to eek out 75% to 150% performance gains over regular C code. They don’t teach you this stuff in class, folks. I exercised a lot of my experience from Epica while writing Paint.NET. Nowadays I don’t do any assembly language but prefer instead to use multiple threads and parallelizable algorithms.

Oh yeah, you can download it here: . Remember, you must have Winamp installed. The latest version works, and the whole thing is Vista compatible as well. Have fun!

More Paint.NET v3.20 ramblings, and 3 pieces of news

I have some more ramblings about the property system, as well as three bits of news for the v3.20 release.

The more I keep using this new property system and UI generation code, the more I like it. I’ve been able to add a few features to some of the effects, such as the ability to move the center of rendering. This is important for things like radial and zoom blur, as well as many of the distortion effects.

In this screenshot, the “Center” property allows you to click and drag to move where the radial blur is centered on (it is centered on the cat’s right eye – well, your “left” but the cat’s “right”). Adding this to an effect takes as little as one line of code with the way I have set this up (I actually spread mine over 4 lines of code for readability’s sake). I’m really looking forward to extending this system to the Save Configuration dialog (would make it super fast to add 8-bit PNG support yes?), as well as other parts of Paint.NET. The “Layer Properties” dialog could be done very quickly using this code. The Resize dialog would also be a great application for this, and eventually I really want to redo the Colors floating window with all of this. I might redo the “About” dialog as a good starting exercise. See, a lot of UI development is really just an exercise in layout and data binding. And this takes care of it all.

The first news I have is a release date for Paint.NET v3.20: December 15th is the planned date. This means I am hoping to have a beta out by mid-November at the absolute latest. Which means I need to kick it in to high gear and wrap things up really soon!

The second news is that HD Photo support is being dropped from the v3.20 release. The reason is simply that the .NET Framework 3.0 is an enormous download and I’m not ready to require a 1.5 MB image editor to require an extra 50 MB download on 32-bit Windows XP just yet. I wanted to pull in .NET 3.5, but apparently it is 140 MB on 32-bit XP (at least that’s what Beta 2 says) which is just way too much. Maybe after the busy Christmas season I’ll be braver and make the next release require .NET 3.0.

Also, the plugin management that I talked about in previous posts will not
be making it into the v3.20 release. There just isn’t enough time to do it right now while also ensuring the highest quality for the aforementioned property system / UI generation.

Playing with Paint.NET v3.20’s new Property System

I’ve finally settled on the framework code for this new property system and automatic UI generator, at least with respect to Effect configuration dialogs. The beauty of this new system is that it literally only takes me about 5 minutes to convert an effect from the old system to this new system. And, from there, I can experiment with adding, removing, and tweaking properties at a very quick pace.

For example, tonight I went and upgraded many of the effects that come with Paint.NET. For most of them there won’t be much of a difference, such as Add Noise: it’s just two Int32-based sliders. But, for others …

Tile Reflection (v3.10 versus v3.20)

Zoom Blur (v3.10 versus v3.20)

The difference can be quite pronounced. I don’t have to write much code for any of this! Most of the work in these new dialogs is in making sure that the text resources are still loaded properly. I think this will be of great benefit for plugin authors, as it will allow them to use a much more versatile set and quantity of rendering properties, without having to resort to clumsy UI and data binding code.

September 2007 usage statistics

Overall usage is up only 3.8% for September, which isn’t too surprising nor is it bad. Vista share grew only a very small amount, and 64-bit is basically at the same level it was in August – it’s still disappointingly low. Overall there isn’t really much to say this month that hasn’t been said already for August, or June or July. My bet is that Vista’s share will jump right around Christmas time.

To grow Paint.NET’s userbase further, I think it will take the addition of some killer new features that people have been clamoring for. And maybe some others that they haven’t but will nonetheless be quite awesome.

Revenue was much higher than in August and is still going strong into September, although I have noticed the “new release afterglow” is now starting to wear off (version 3.10 was published on August 24th). Donations always spike very strongly after a new release for about 10 days (by the way, thanks to everyone who has donated! It really does make a difference!). AdSense also takes a healthy jump but doesn’t exhibit the same derivatives. It tends to show a much smaller short-term spike, after which it grows over the following few weeks and then cools off over about the same amount of time. My guess is that a freshly updated web page is simply more valued by AdSense (I could be completely wrong of course). It may be prudent to time a release in order to take advantage of the Q4 advertising spree, as John Chow puts it. By the way, he recently broke past $20,000 / month with just his blog. I would love to accomplish the same with Paint.NET, all while continuing to give it away for free.

As a reminder, these statistics represent hits to the auto-updater manifests, which means they approximately reveal the Paint.NET application’s usage. Unless the auto-updater is disabled, it will check for updates up to once every 5 days at application startup. This is done by downloading a text file whose filename is decorated with OS and language information. Having 1.2 million hits to the manifest does not mean that Paint.NET has 1.2 million installations, or 1.2 million active users. It is merely a tool for comparing usage trends amongst different time periods (month to month, in this case).




Aug. -> Sept.

Total Hits




Hits Per Day













Windows XP




Windows 2003




Windows Vista









































Chinese (Simplified)








Chinese (Traditional)












The rest




Have translations




Don’t have translation




What’s coming for Paint.NET v3.20: Plugin Development

In a previous blog posting I rambled on about how plugins need to be easier, both for users and developers. I haven’t had a lot of time lately to work on Paint.NET, but I have managed to get started on a new system for developing effect plugins that provide configuration UI for the user. These types of plugins are the most popular: you click on them in the Effects menu and it pops up a dialog with sliders and buttons and whatnot which lets you configure properties that determine how the effect is rendered.

The problem with developing these configuration dialogs is that they are extremely tiresome to write. You can write rendering code for a simple plugin very quickly using CodeLab, but you are limited to a “1, 2, or 3 amount sliders” configuration dialog. If you need 4 sliders, then you have to write a brand new dialog from scratch complete with layout and data binding. It’s easy to get the implementation wrong, or to at least skirt the line of what constitutes a “correct” implementation. My experience has been that if it’s possible to do things “the wrong way,” then your framework needs to be changed: it should only ever be possible to do things the right way, or at least make it extremely obvious when you’re breaking the rules. Right now that distinction isn’t really clear.

I have been working on a new system that will allow plugin developers to easily get intricate configuration dialogs from just a description of the properties that govern rendering. For example, adding this code in an Effect:

protected override PropertyCollection CreatePropertyCollection()
List<Property> props = new List<Property>();

props.Add(new Int32Property(PropertyNames.Factor, 1, 1, 10));
props.Add(new DoubleProperty(PropertyNames.Zoom, 10, 0, 100));
props.Add(new AngleProperty(PropertyNames.Angle));

props.Add(new DoubleVectorProperty(
Pair.MakePair(0.0, 0.0),
Pair.MakePair(-1.0, -1.0),
Pair.MakePair(1.0, 1.0)));

props.Add(new Int32Property(PropertyNames.Quality, 2, 1, 4));
props.Add(new BooleanProperty(PropertyNames.InvertColors));

return new PropertyCollection(props, new PropertyCollectionRule[0]);

… generates this type of dialog:

(click for full-size)

All of the layout and data binding is handled automatically, making the plugin author’s life much, much easier. The dialog is resizable, and if there are too many properties to fit on-screen it will automatically provide a scrollbar. The UI itself is still rough draft: the “offset” is still just two sliders right now, for instance, and needs something akin to what we have in the Rotate/Zoom dialog. This system and the UI generation should only improve with time. Eventually I want to have the Rotate/Zoom, Curves, and even Levels configuration dialogs written using this. So far I have an enhanced version of Frosted Glass using this, and have re-done the UI for Clouds up to feature parity with v3.10.

But the great thing about being able to easily get this UI is that it is also very easy to change it. What if you want to change the ordering? Add a property? Remove two properties? It’s easy. Just change the code in your CreatePropertyCollection() function.

Once this system is mostly finished for Effect development, I will also be extending it to the UI generation for file type plugins. This will allow me to provide rich configuration for things like HDPhoto, but without having to write a lot of the complicated logic that governs its data binding and property value dependencies (“property Z may only be configured if property M is enabled” … barf).

The other thing some of you may have picked up on is that the code above could easily be auto-generated from, for instance, an XML description of the same properties. This system is being designed to make code generation scenarios simple to implement, such as for CodeLab.

Lastly, once the system is well understood, I will rewrite the “Colors” floater window using the same UI generation and property system. That thing is about 5,000 lines of code and is very fragile. It has grown organically since 2004 and is in very sad shape. It works, but only because it has been thoroughly debugged. I much prefer code that works because it was meant to work (i.o.w. it works by design, not by accident).