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 Winamp.com 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: http://www.dotpdn.com/files/Epica210.zip . 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).

 

August

September

Aug. -> Sept.

Total Hits

1,182,822

1,227,592

3.79%

Hits Per Day

38,156

39,600

 
       

32-bit

98.75%

98.76%

0.01%

64-bit

1.25%

1.24%

-0.78%

       

Windows XP

84.29%

84.04%

-0.30%

Windows 2003

0.66%

0.63%

-4.17%

Windows Vista

15.05%

15.33%

1.88%

       

English

46.66%

46.36%

-0.64%

German

18.02%

17.48%

-2.95%

French

7.62%

8.51%

11.55%

Portuguese

5.92%

5.87%

-0.86%

Spanish

4.58%

4.54%

-0.92%

Japanese

2.20%

2.21%

0.65%

Italian

1.67%

2.10%

25.73%

Netherlands

1.9
3%

1.77%

-8.30%

Russian

1.66%

1.67%

0.41%

Chinese (Simplified)

1.51%

1.16%

-23.13%

Polish

1.87%

1.96%

4.80%

Chinese (Traditional)

0.92%

0.80%

-13.32%

Turkey

0.74%

0.73%

-0.94%

Korean

0.63%

0.57%

-9.02%

The rest

4.08%

4.28%

4.79%

Have translations

87.13%

86.70%

-0.50%

Don’t have translation

12.87%

13.30%

3.37%

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(
PropertyNames.Offset,
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).

Dealing With Legacy, or The Story of Paint.NET’s Bug Database

As a computer scientist and software developer, I have been conditioned to live in fear, or at least gross distaste, of legacy. That is to say, legacy code, legacy systems, legacy process/procedures, etc. As a self-proclaimed cowboy rock star egotastic developer, anytime I see code that wasn’t written by myself (or a select group of those whom I deem as “peers”), my first instinct is to proclaim that it’s horribly written and that I should redo it. Likewise, the same goes for legacy systems and process/procedures. “Oh gosh, we’d be so much more efficient without all this process in place!” … “Oh gosh, our server is running on an OS that’s 4 years old, we need to upgrade it!” … “Oh gosh, oh gosh!”

Sound familiar? It should if you’re a software developer on a project with more people assigned to it than you can count on two fingers. I’ve found that one important part of career and professional growth in software development is learning how to deal with legacy, and to reign back the instincts to immediately and bombastically proclaim it all as a bunch of crap. Sometimes dealing with legacy means refactoring utility code while you’re fixing a bug that is dependent on it (“I’m in this part of the code anyway, why not?”). Other times that means checking out half the source code tree to make a tiny change in every single file that has positive consequences in areas of performance, stability, maintainability, or whatever. On rare occasions it really does mean rewriting all the code, or redefining the process by which you’re doing development.

Oftentimes, however, I’ve learned that you should just leave it alone.

If you have something in place that works, and you don’t have plans to change it, then guess what … it’s probably ok to leave it alone! Even if the code is nasty, or the implementation uses 5 year old design patterns, or if there’s a new intern who really really wants to prove him or herself. For example, I would argue that Notepad works. It does its job, it does it well, and there’s really no need to rewrite it to use C# or WPF or sock puppets or anything. It’s a stable legacy system. (That’s not to say there isn’t a need or a market for something more, such as Notepad++ or Notepad2.)

Now, you might wonder what in the world this has to do with Paint.NET’s bug database. Well, before I start, you should first answer the following question: What do you think I’m using for Paint.NET defect/bug tracking?

Ok, seriously, ask yourself that question. Give yourself at least 10 seconds to come up with a few different possibilities, both low- and high-tech. Pieces of paper stapled to the wall? Sourceforge? A custom WinForms or ASP.NET app? Notepad? Excel? The back of my hand and a marker?

Here’s the answer and the story:

Paint.NET’s bug database is Bugzilla 2.16.3 running on Apache in Redhat Linux 8.0. It was originally hosted on a Pentium II named “elbonian3” in some dark corner of the EECS department of Washington State University. It was set up by (I think) Chris Crosetto during Fall semester of 2003 (~August) for the Computer Science 422 class (“Software Testing”) that Jack Hagemeister was running. The purpose was to inspect the source code of some client software that Gene Apperson (Microsoft alumni, Diligent founder) was developing, and to then file bugs on it. I was in this class and filed many bugs on the code, although I don’t know if Gene ever fixed the bugs or if his project was ever finished. Paint.NET started the following semester, and version 1.0 was written from start to finish in 15 weeks without any official bug tracking system. I think Brandon had an Excel file but nobody else really had access. I do not recommend doing that, by the way, that’s just the way things went down.

For the Fall 2004 semester, I talked with Jack and we set up a senior design project to ramp Paint.NET up to version 2.0. We got three students to work on it: Tom Jackson, Michael Kelsey, and Craig Taylor. The first thing we did was to have me finish up my work on version 1.1, and have the three students do bug filing and write updated documentation (haha, suckers!). As part of this, they managed to get the new semester’s CS422 students to do a lot of testing. To do this they picked up and ran with the “elbonian3” server that had been set up the year before. It worked great: students would file bugs, I would get e-mails from the server, and we could respond to each bug appropriately. The three students learned a lot about bug triaging, as well as release and defect management. Next up, they did their development work to push Paint.NET up to version 2.0 which was released right before Christmas. Then Paint.NET was Slashdotted. It was amazing, and comedic: the attention caused enough network traffic to bring down the entire EECS network for 2 days.

For about the next year and a half, I continued to use this server remotely from 300 miles away to do Paint.NET’s defect tracking. However, in early- to mid-2006 it was clear that it was no longer appropriate to house this software at EECS. The network administrator was overworked (as they always are!) and the server was often down (for whatever reason), and Paint.NET was not really a “WSU project” anymore. The admin wanted to retire the server, and said he could send me the contents of the hard drive as a VMWare virtual hard drive file. I said that would be great, and the next day I started downloading a 2 GB tarball over HTTP.

Once I had downloaded and extracted the file, my next job was to install the free Windows version of VMWare Player on my server box in a dark corner of my house. This was no problem; it booted right up and spat out a login screen. But, you see, there was a major problem: the server still thought it was in Pullman on the eecs.wsu.edu domain. I managed to figure out what IP address the server had obtained, but whenever I tried to access it Apache would respond with headers pointing my browser back to the old eecs.wsu.edu address. Argh! Try as I might, I couldn’t figure out how to reconfigure Apache not to do this.

I’m sure some magical combination of grep and sed and other 3-to-4 letter combinations could fix it quick, but I found a faster-for-me solution: I cheated. I edited my hosts file in Windows so that it would map elbonian3’s network name to the local IP address of the virtual machine. Then, when I typed in the IP address in to my browser, it would get redirected to elbonian3 which would then get redirected right back to the IP address in a way that was completely transparent to the browser. Success! I had a working bug server again!

On a quick side note, about a month after I set this up I found that my IP range was being blacklisted by spamhaus or something. The reason was that sendmail was still active on my virtual server. Bugzilla kept trying to blast e-mail notifications about bug changes through an EECS mail server, which for obvious reasons rejected them. I’m a dumb clumsy oaf when it comes to Linux administration so I had to find a clever way to disable sendmail … I think in the end I may have just removed execute permissions on the appropriate binary. Bugzilla still claims to be sending out e-mails in its UI, but none of them actually get sent.

Anyway. A few weeks ago I decided to retire that server, as it wasn’t really doing much other than hosting this virtual machine and a CVSNT server. Why pay for that electricity if I can get it to run on my main workstation anyway? These were two things I figured could be done much faster if I just ran them locally (CVSNT is slow for Paint.NET’s repository on a 100mbit connection). There was another problem though: I use VirtualPC so that I can host copies of Windows XP and Vista in various configurations (high DPI, weird visual themes, etc.) in order to do testing for Paint.NET. I had VMWare up and running successfully, but the moment I tried to run VirtualPC the whole system hung and my awesome techno music started skipping. Bleh!

I managed to find a utility to convert the VMWare “VMDK” hard drive file to a Virtual PC “VHD” file. It’s called, appropriately, Vmdk2Vhd. And now I have my Bugzilla running in Virtual PC on my desktop system.

So there you have it. I use an old version Bugzilla in a virtualized Linux installation which still thinks it’s sitting in a dusty corner of my old university that’s over 300 miles away.

And it works.

And past that, who cares? Right now, I sure don’t. Legacy isn’t all bad, as long as it works and you don’t have to maintain or reconfigure it all that often. I’m basically the sole developer on Paint.NET right now so my requirements are pretty slim for things like bug tracking and source code control (Linus thinks I’m “ugly and stupid” for using CVS … but hey, you gotta admire his passion).

By the way, the quote in the Bugzilla screenshot above reads: “Using exceptions for bounds checking is like driving a car … it’s cheaper to just do a little extra work and stay in-bounds than it is to crash off the side of the freeway and say, ‘Oh the insurance can pay for that.'”

Successful Freeware Tip #3: Release Often to Keep People Interested

Prior to Paint.NET v2.6, I was releasing at a pace that covered several months. 2.0 to 2.1 was about 5 months, and forward to 2.5 was another 6 months. V2.6 was done in 3 months, and 3.0 took about 11 months. However, between 2.6 and 3.0 I release 2.61, 2.62, 2.63, 2.64, 2.70, and 2.72 – at a pace of roughly one every 4-6 weeks. Once 3.0 came out, I released 3.01, 3.05, 3.07, and 3.08 at a similarly fast pace, followed by v3.10 just shy of 3 months later.

There were several reasons for all the small “.01” releases from the 2.6 codebase. One was that I needed to put out some important bug fixes to decrease support costs (“costs” meaning “my time” and “user happiness”). If you can just fix common bugs, or work around common user mistakes, then they are no longer bugs or mistakes: it just works! Less e-mails for you, more working software for the masses. It’s a win-win.

The second reason was that I wanted to see what would happen if I released more often. I knew that 3.0 was going to take awhile to develop, and I wanted to keep online attention devoted towards Paint.NET. People forget about things quickly, and I wanted to avoid seeing any comments like, “Whatever happened to Paint.NET?”

So I forked the code and continued to release off the 2.6 tree. My theory was that if I didn’t release every so often, the media and online community would slowly forget about Paint.NET. I don’t really do any marketing or advertising to fill that niche (it wouldn’t be profitable). My theory continued such that if I did release often (4-6 weeks is about right), even with just a +.01 bugfix-only release, that the media and online community would be consistently reminded about Paint.NET. Users would hear more about it, which breeds familiarity, which coaxes more and more people to download and try it out. This means more users sticking with the program, more people donating, more traffic to my website, and generally just more awesomeness all around. Oh, and quick releases means users get bug fixes and features quicker too 😉

Here’s the great thing: this theory is proving itself to be correct. Here are some facts that back it up:

  • Nearly 80% of the 3-year old forum‘s activity is from this calendar year. Part of this I believe can also be attributed to having placed a link to the forum in the application’s Help menu. (Comparing # of posts from December 31st, 2006 to today’s count.)
  • Almost 60% of the all Paint.NET downloads have occurred during this calendar year. (Comparing download counts for December 31st, 2006 versus today at BetaNews, historically the primary download mirror.)
  • Revenue via donations is about 2x what it was before 3.0 was released. (This is comparing February 2007 through August 2007, with August 2006 through December 2006).
  • Revenue via AdSense is about 10x what it used to be. (This is comparing May 2007 through September 2007, with August 2006 through December 2006, but excluding November 2006 because there was some glitch that nuked my earnings for a week or so).

After the v3.0 release things really started picking up in the donations and AdSense departments. This is of course partly due to the fact that v3.0 simply rocked compared to previous versions and reached a critical mass of features and press coverage, and I started getting more traffic.

The 3 months gap between 3.08 and 3.10 confirmed my theory that frequent releases create a positive feedback cycle for earnings and avoids media forgetfulness. Before the 3.10 release, it was quite apparent that donations and AdSense were losing their steam from the 3.07 and 3.08 releases. Check out this graph showing my relative daily AdSense earnings:

The amount of traffic coming to the site is mostly constant, but it appears like AdSense was just, I don’t know, getting bored with the site or something. Now that 3.10 is out the door, AdSense is continuing on a slow upward trend, even a full month after the release. Maybe AdSense has a bias against stale sites? I even saw a very happy spike on Sunday which set an all-time 1-day record. AdSense is definitely a strange, strange beast.

The graph for donations is very different and always shows huge spikes for about 10 days following a release. I do not have a graph prepared because of the difference in how PayPal provides its data: I have to do some crazy Excel programming to get it to work L

The base theory is that every time I release, I get a short-term spike in traffic after which it settles down to a level that is slightly higher than what the average was before.

Considering Direct Ad Sales

One thing that John Chow has given advice on is selling ads directly. I’ve been thinking about this a bit the last few days and I think it may be time for me to try it out. I certainly have the traffic for it! The getpaint.net website gets over 1 million “page impressions” per month as reported by Google Analytics. The index page does around 400,000, and the download page sits at just under 500,000. Right now I’m using Google AdSense and it is doing very well for itself, at least in absolute terms (never say “no” to free money, right?).

John Chow’s advice says to take the amount you’re earning with AdSense and double it for when you try selling ads directly. The hypothesis is that Google is sharing revenue at a rate of about 50%. His other general advice to diversify your income is one that I’ve implemented as well – albeit by implementing Search that is still provided by Google, and by moving the Help content online and adding AdSense to it (together they added enough to my Paint.NET earnings to buy a Bluray player!).

This could help to significantly diversify my income sources and reduce my reliance on AdSense, which in August accounted for 80% of Paint.NET revenue. It’s not that I dislike AdSense, and I bet the feeling is mutual. I also don’t think I will be banned, but it’s still a significant risk factor — just ask Henry and Wilson about the time they lost out on $200,000 (although they seem to have broken some of the AdSense TOS, such as not having more than 1 account).

I also have advertising space available in the Paint.NET installer. You know when you install the program and it says “Please wait, optimizing…” and there’s a little banner that says “Please donate!” along with one for the download mirror (“This update brought to you by BetaNews”) or for searchpaint.net? I bet I could sell that as advertising space as well. It reaches hundreds of thousands of users per month and is on screen for a good chunk of time.

The only thing I’m wary of is that John Chow also suggests that you create an Advertisers page that list your rates directly instead of saying, “please e-mail us for a quote.” But hey, if I have to disclose revenue to get a huge increase in it, it might just be worth it. John Chow does it every month and when he posts earnings just shy of $18,000 for August, people are stunned and inspired (or, shocked and awed?).

I would probably sweeten the deal by allowing the advertiser (or advertisers, I don’t know how I’ll do things) access to the site’s Google Analytics reports. That way they could see what types of visitors they are reaching, and retarget their ad appropriately if they wanted.

So … comments?

Anyway I’m off to Bumbershoot in the morning*. I’ve never been but it’s supposed to be awesome, and it’s a friend’s birthday too.

* Yeah yeah I posted at 4:30am …