<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>

<channel>
	<title>Paint.NET</title>
	<atom:link href="http://blog.getpaint.net/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.getpaint.net</link>
	<description>The best free image and photo editor. By Rick Brewster.</description>
	<pubDate>Mon, 15 Jun 2009 23:16:49 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
	<language>en</language>
			<item>
		<title>Paint.NET v3.5 – Better font handling, and performance. Again.</title>
		<link>http://blog.getpaint.net/2009/06/15/paintnet-v35-%e2%80%93-better-font-handling-and-performance-again/</link>
		<comments>http://blog.getpaint.net/2009/06/15/paintnet-v35-%e2%80%93-better-font-handling-and-performance-again/#comments</comments>
		<pubDate>Mon, 15 Jun 2009 23:16:49 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=334</guid>
		<description><![CDATA[Last Thursday I release a new alpha of Paint.NET v3.5, build 3450. I have rewritten the way that fonts are handled for and by the Text tool. Even if you don’t use the Text tool much, you will still notice some improvements! (see the bulleted list below)
In previous versions of Paint.NET, there are two forms [...]]]></description>
			<content:encoded><![CDATA[<p>Last Thursday I release a new alpha of Paint.NET v3.5, <a href="http://paintdotnet.forumer.com/viewtopic.php?f=46&amp;t=30398" target="_blank">build 3450</a>. I have rewritten the way that fonts are handled for and by the Text tool. Even if you don’t use the Text tool much, you will still notice some improvements! (see the bulleted list below)</p>
<p>In previous versions of Paint.NET, there are two forms of text rendering supported. The first and the default is called “Smooth”, which utilizes <a href="http://en.wikipedia.org/wiki/GDI%2B#GDI.2B" target="_blank">GDI+</a>* to render text. The second is called “Sharp”, and uses <a href="http://en.wikipedia.org/wiki/Graphics_Device_Interface" target="_blank">GDI</a>. For both, GDI+ is used for font enumeration through the classes in the System.Drawing namespace. Over time, GDI+ has proven to be a poor system for font handling. It has been the cause of many crashes, as GDI+ has a tendency to crash or trample on memory when it encounters fonts that are “bad” (although <em>bad</em> is relative – the font itself may be perfectly fine!). This has led to some people being completely unable to use Paint.NET through no fault of their own.</p>
<p>As a result, I have banished GDI+ from the Text tool. The new builds of Paint.NET are using GDI exclusively for font discovery and text rendering, a change that was substantial in the amount of code that was required and the amount of research that had to be done to make sense of it all. If you’d like to get an appreciation of the depth of the subject, you should check out chapters 14, “Fonts”, and 15, “Text”, of the book, <a href="http://www.amazon.com/gp/product/0130869856?ie=UTF8&amp;tag=httpbloggetpa-20&amp;linkCode=as2&amp;camp=1789&amp;creative=9325&amp;creativeASIN=0130869856">Windows Graphics Programming: Win32 GDI and DirectDraw (Hewlett-Packard Professional Books)</a><img style="border-bottom-style: none !important; border-right-style: none !important; margin: 0px; border-top-style: none !important; border-left-style: none !important" border="0" alt="" src="http://www.assoc-amazon.com/e/ir?t=httpbloggetpa-20&amp;l=as2&amp;o=1&amp;a=0130869856" width="1" height="1">. </p>
<p>The new <em>typography system</em> in Paint.NET has been designed so that I can plug new text rendering technologies into it. Right now it only supports GDI. For the meantime this means that the choice between “Sharp” and “Smooth” is not available. My next step is to add support for two more text rendering systems, <a href="http://www.freetype.org/" target="_blank">FreeType</a> and <a href="http://blogs.msdn.com/text/archive/2009/04/15/introducing-the-directwrite-font-system.aspx" target="_blank">DirectWrite</a> (for Windows 7 users**). The former will step in to provide the “Smooth” renderer, and the latter will be added under the name “Enhanced” (or some appropriate name). </p>
<p>In the meantime, you’ll still realize the following benefits in the latest alpha:</p>
<ul>
<li><strong>No more “missing” fonts</strong>. GDI+ doesn’t support some fonts, notably bitmap, vector, and certain OpenType fonts. I don’t know why. You’ll notice that the new versions of Paint.NET now has a “complete” font list.</li>
<li><strong>Improved startup performance.</strong> It’s ironic that I was telling my manager at work the other day, “Paint.NET v1.0 had poor startup performance – in fact, it was enumerating all the system fonts at system startup, <em>but it no longer does.</em>” Well, because of a bug in my layout code for the toolbar, Paint.NET v3.36 was still doing this! I fixed the bug, and Paint.NET v3.5 now properly defers this to later. I’ve measured the improvement in startup performance at about 15%*** on my systems, and if you have a “lot” of fonts you will no doubt see an even bigger improvement. This is in addition to the already improved startup performance of v3.5 versus v3.36! </li>
<li><strong>Improved stability.</strong> Like I mentioned earlier, GDI+ often crashes when it runs into “bad” fonts <em>(subject to GDI+’s definition of “bad”)</em>. Or, it has bugs that lead it to trample on memory it does not own, resulting in crashes which get attributed to the wrong code. GDI does not have this problem. Or, at the very least, if it runs into “bad” fonts, I now control the code that deals with this. I can then make it do something other than crash.</li>
<li><strong>Installing new fonts. </strong>Previously, Paint.NET needed to be restarted for it to recognize any new (or deleted) fonts. I now place a <a href="http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx" target="_blank">FileSystemWatcher</a> object on the system fonts directory and refresh the toolbar’s font list when changes are detected. There is also a shortcut in the Utilities menu to open the Fonts directory, which will be very useful for helping answer the question that is asked with surprising frequency on the forum: “How do I add fonts?”</li>
</ul>
<p><em>* The Wikipedia article states that in the Windows XP timeframe, GDI was deprecated in favor of GDI+. This is not true, although it may have been the altruistic intent at the time.</em></p>
<p><em>** <a href="http://blogs.msdn.com/text/archive/2009/04/13/directwrite-questions-and-answers.aspx" target="_blank">This will eventually be supported on Windows Vista as well.</a>&nbsp;</em></p>
<p><em>*** On my personal system, the difference is 0.577 seconds versus 0.405 seconds, as reported by Process Explorer. This is not a formal or exhaustive performance analysis. The precision and accuracy of Process Explorer is not at the millisecond level, hence me rounding all the way down to 15%. The system is an Intel Core i7 920 overclocked to 3.6GHz running Windows 7 RC build 7100. Another system, a Core 2 Quad Q6600 2.4GHz system running Windows 7, reported values of 1.0 second versus about 0.8 seconds, respectively.</em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2009/06/15/paintnet-v35-%e2%80%93-better-font-handling-and-performance-again/feed/</wfw:commentRss>
		</item>
		<item>
		<title>First alpha build of Paint.NET v3.5 is now available</title>
		<link>http://blog.getpaint.net/2009/05/17/first-alpha-build-of-paintnet-v35-is-now-available/</link>
		<comments>http://blog.getpaint.net/2009/05/17/first-alpha-build-of-paintnet-v35-is-now-available/#comments</comments>
		<pubDate>Mon, 18 May 2009 03:49:58 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=333</guid>
		<description><![CDATA[Here’s where you can check it out: http://paintdotnet.forumer.com/viewtopic.php?f=46&#38;t=30113
This will not be made available on the website. I don’t even recommend that any download websites host it yet. We’ll wait for the beta for that!
In the meantime, please download, install, and post your comments on the forum.
]]></description>
			<content:encoded><![CDATA[<p>Here’s where you can check it out: <a title="http://paintdotnet.forumer.com/viewtopic.php?f=46&amp;t=30113" href="http://paintdotnet.forumer.com/viewtopic.php?f=46&amp;t=30113">http://paintdotnet.forumer.com/viewtopic.php?f=46&amp;t=30113</a></p>
<p>This will not be made available on the website. I don’t even recommend that any download websites host it yet. We’ll wait for the beta for that!</p>
<p>In the meantime, please download, install, and post your comments on the forum.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2009/05/17/first-alpha-build-of-paintnet-v35-is-now-available/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Random April Thoughts</title>
		<link>http://blog.getpaint.net/2009/04/07/random-april-thoughts/</link>
		<comments>http://blog.getpaint.net/2009/04/07/random-april-thoughts/#comments</comments>
		<pubDate>Tue, 07 Apr 2009 18:29:12 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=332</guid>
		<description><![CDATA[It&#8217;s April and we finally have some sun in Seattle and I haven&#8217;t posted in awhile.
Paint.NET runs pretty well with Parallels on my MacBook Pro, although there&#8217;s a few quirks to squash. Hmm &#8230; they have an affiliate program. I smell a revision to the System Requirements coming soon. Do you know how many requests [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s April and we finally have some sun in Seattle and I haven&#8217;t posted in awhile.</p>
<p>Paint.NET runs pretty well with <a href="http://www.parallels.com/">Parallels</a> on my MacBook Pro, although there&#8217;s a few quirks to squash. Hmm &#8230; they have an affiliate program. I smell a revision to the <a href="http://www.getpaint.net/download.html#sysreq">System Requirements</a> coming soon. Do you know how many requests I get for a Mac version of Paint.NET? <img src='http://getpaint.setupmyblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://www.codinghorror.com/blog/archives/001249.html">&#8220;Should Competent Programms be &#8220;Mathematically Inclined&#8221;?&#8221;</a> &#8212; Absolutely, Jeff. I can&#8217;t believe anyone would question this. <em>&#8220;Math is hard, let&#8217;s go shopping!&#8221;</em> *faceplant*</p>
<p>Paint.NET v3.5 is coming along, but slowly. I haven&#8217;t had as much time or motivation, and it&#8217;s difficult when you don&#8217;t have a build that works because of ancillary code you broke in areas that you don&#8217;t really like (the Recolor tool comes to mind).</p>
<p>Blackjack is fun, especially when you&#8217;re winning.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2009/04/07/random-april-thoughts/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Thank you, Akimset spam detector</title>
		<link>http://blog.getpaint.net/2009/03/02/thank-you-akimset-spam-detector/</link>
		<comments>http://blog.getpaint.net/2009/03/02/thank-you-akimset-spam-detector/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 20:47:56 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Silly]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=331</guid>
		<description><![CDATA[One of the most popular plugins for WordPress blogs is the Akimset spam detector. Mine says it has found and squashed 93,860 spam posts since it was installed. I&#8217;m always amazed at what type of spam the robots try and sneak through every day.
Here&#8217;s a recent spam post:
&#8220;poonnnbvhifiytfyudyufydyddyufytfyufyutfyfyfyutfyfyutfyufytfytfyfyufytftyftftftftftftftttttttttttttttttttttttttttttfffffffffffffffffffffffffttttttttttttttttttttttffffffffffffffffffffffffffffffffffffffffffbut&#8221;
Thanks for the comment! I&#8217;ll be sure to [...]]]></description>
			<content:encoded><![CDATA[<p>One of the most popular plugins for WordPress blogs is the Akimset spam detector. Mine says it has found and squashed <b>93,860</b> spam posts since it was installed. I&#8217;m always amazed at what type of spam the robots try and sneak through every day.</p>
<p>Here&#8217;s a recent spam post:</p>
<blockquote><p><em>&#8220;poonnnbvhifiytfyudyufydyddyufytfyufyutfyfyfyutfyfyutfyufytfytfyfyufytftyftftftftftftftttttttttttttttttttttttttttttfffffffffffffffffffffffffttttttttttttttttttttttffffffffffffffffffffffffffffffffffffffffffbut&#8221;</em></p></blockquote>
<p>Thanks for the comment! I&#8217;ll be sure to raise that issue with <a href="http://en.wikipedia.org/wiki/Internet">management</a> the next time I see them.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2009/03/02/thank-you-akimset-spam-detector/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Russian is coming to Paint.NET</title>
		<link>http://blog.getpaint.net/2009/02/26/russian-is-coming-to-paintnet/</link>
		<comments>http://blog.getpaint.net/2009/02/26/russian-is-coming-to-paintnet/#comments</comments>
		<pubDate>Fri, 27 Feb 2009 04:19:43 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=330</guid>
		<description><![CDATA[Another great feature for the upcoming version 3.5 release: an official Russian translation! I think this should make 4.16% of the userbase very happy  

 

]]></description>
			<content:encoded><![CDATA[<p>Another great feature for the upcoming version 3.5 release: an official Russian translation! I think this should make <a href="http://blog.getpaint.net/2008/11/05/october-2008-usage-statistics/" target="_blank">4.16% of the userbase</a> very happy <img src='http://getpaint.setupmyblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<blockquote>
<p><img src="http://www.getpaint.net/users/rick/blog/20090226_pdn35rus.png"> </p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2009/02/26/russian-is-coming-to-paintnet/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Introducing Paint.NET v3.5’s new selection renderer</title>
		<link>http://blog.getpaint.net/2009/02/25/introducing-paintnet-v35%e2%80%99s-new-selection-renderer/</link>
		<comments>http://blog.getpaint.net/2009/02/25/introducing-paintnet-v35%e2%80%99s-new-selection-renderer/#comments</comments>
		<pubDate>Thu, 26 Feb 2009 06:56:33 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=329</guid>
		<description><![CDATA[In my previous post, I mentioned that I had rewritten the selection renderer in Paint.NET v3.5. As a pseudo-warning, this post is pretty technical.
The selection renderer in Paint.NET v3.36 uses GDI+. It draws the outline twice: once as a dashed black line, and the second as a dashed white line. A timer fires every 50 [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://blog.getpaint.net/2009/02/05/the-theme-of-paintnet-v35-is-%E2%80%A6-performance/" target="_blank">previous post</a>, I mentioned that I had rewritten the selection renderer in Paint.NET v3.5. As a pseudo-warning, this post is pretty technical.</p>
<p>The selection renderer in Paint.NET v3.36 uses GDI+. It draws the outline twice: once as a dashed black line, and the second as a dashed white line. A timer fires every 50 milliseconds or so and redraws the outline with a slightly increased “dash offset.” This gives the “dancing ants” animation. Our pal <a href="http://www.imdb.com/name/nm0731075/" target="_blank">Emma Roberts</a> will demonstrate:</p>
<blockquote>
<p>&nbsp;<img src="http://www.getpaint.net/users/rick/blog/20090204_336selEmma.png"> <br /><em>“Pretend I’m animated!” &#8212; Ants</em></p>
</blockquote>
<p>There are a few major problems with this implementation. The first is that while you are drawing or modifying a selection, it is only drawn with a black outline <em>(once you are done, it will transition to the “dancing ants” mode)</em>. This makes it wickedly difficult to figure out what kind of selection you’re drawing if the underlying area is black. Try it with a solid black image and you’ll understand immediately. I had to do a solid outline instead of a dashed one because there were some horrible artifacts and performance problems if I didn’t.</p>
<p>Next up, the new render cache <em>(hopefully I’ll discuss it in an upcoming post)</em> splits up rendering into more tiles than it did before (for several good reasons!). GDI+ does <em><u>not</u></em> do multithreading. At all. In fact, it actively prevents you from making GDI+ calls on more than one thread even if you are clever and “trick” it. This was resulting in selection rendering performance falling off a cliff as all sorts of “setup” work (creating brushes, clipping, etc.) was being over-executed by up to a factor of 10 <em>(that’s an estimate)</em>. Not to mention it was a non-starter for multithreaded performance scaling anyway.</p>
<p>Another problem is that the “dancing ants” animation consumes a <em>lot</em> of CPU power. This in turn slows down the rest of the system, and drains battery power <em>(I’m a desktop/workstation guy, but the market has been majority-owned by laptops for awhile now)</em>. There are a few optimizations in there to throttle CPU usage if it gets “too high” but it’s never really been profiled or quantitatively proven to work well. My criteria at the time was “fewer people are complaining,” and then I went and drank beer (woohoo!).</p>
<p>Ahem. Anyway. The animation is really there for two reasons: not only does it look cool, but it guarantees contrast between the selection outline and the underlying image. The image you’re working on can’t animate, but the selection outline does, so there you go: it will never be confused for being part of the image.</p>
<p>The solution? <strong>I wrote my own polygon rasterizer renderer. From scratch. </strong>There’s a good reason people use libraries like <a href="http://en.wikipedia.org/wiki/GDI%2B#GDI.2B" target="_blank">GDI+</a> and <a href="http://en.wikipedia.org/wiki/Cairo_(graphics)" target="_blank">Cairo</a> to render graphics for them: it’s tricky! Get someone else to do it for you! Simple implementations aren’t difficult, but the complexity skyrockets once you add things like antialiasing, clipping, blending, various types of caching, serialization (critical for undo/redo), and safe multithreading.</p>
<p>However, I felt it was worth it to implement just enough of a pixel-pushing geometry rasterization “library” in order to render the selection since it is so crucial for Paint.NET. It’s taken “only” 2 months to get right, and it still isn’t quite finished. <em>(but hey, if something is a core business of yours, </em><a href="http://www.joelonsoftware.com/articles/fog0000000007.html" target="_blank"><em>do it yourself!</em></a><em>)</em>. I’m now taking polygon lists and doing my own clipping, scanline rasterization, clipping, blending, etc. It’s fun, confusing, educational, and horrifying. I should probably have a cigarette once I’m all done and calmed down<em>.</em></p>
<p><a href="http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm" target="_blank">Bresenham invented the classic aliased line rasterization algorithm</a>, and a kid named <a href="http://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm" target="_blank">Xiaolin Wu later invented a smart antialiased rasterization algorithm</a>. Both are in wide use today because of their inherent and wonderful <em>simplicity. </em>I implemented the latter, because antialiasing is important. The selection outline now uses “XOR” blending, so contrast is guaranteed except for a few less-common scenarios (prevalent 50% grey).</p>
<p>Notice how in this new screenshot, the selection outline effectively changes color as it goes through parts of the image which are varying colors. Where her hair is dark, the selection is bright, and where it crosses her lighter skin tone it becomes darker:</p>
<blockquote>
<p><img src="http://www.getpaint.net/users/rick/blog/20090204_350selEmma.png"></p>
</blockquote>
<p>Normally you can’t use both XOR <em>and</em> antialiasing. XOR is meant to be “undoable” and so applying it a 2nd time simply gives you back the original data. It’s generally fast, cheap, and simple. With a naive antialiasing implementation you end up with seams and dots all over your polygon, as endpoints of lines give you pixels that are rendered twice, and very small lines (0 to 2 pixels long) don’t really know what to do. </p>
<p>My solution was to do the rendering in two passes. In the first pass I accumulate coverage values into the alpha channel. I accumulate towards zero, and use the inverse of that later as my real alpha value. I can do this because I know that the pixel is fully opaque at this stage in the rendering pipeline; this is because the “checkerboard” has already been applied. Thus, the alpha channel can be used for whatever I want.</p>
<p>In the second pass I apply the XOR operator to every pixel along the path at full strength (yar!), and then use alpha blending between the original pixel’s color value and the XOR’d color value with respect to the accumulated alpha. Yes, I’m doing stencil buffer accumulation in software. Video games use these a lot, especially for things like shadows and dancing teddy bears <em>(ok maybe not the second one so much)</em>.</p>
<p>Oh, also, the selection is no longer animated because contrast is achievable without it, and because the performance benefit is profound. It would also be much more difficult to get an animated or dotted outline with the new code. I’d need 4x the lines of code, or I’d have to employ code generators or some other form of voodoo <em>(if this were C++, a “policy-based template something-or-other”</em> would be employed). As it is I still have a few higher-order functions and closures in there I need to get rid of. But the performance is still great, so I have deferred those optimizations until later (alpha or beta). </p>
<p>Because the selection renderer is now implemented in code that is completely owned by me, all opportunities for optimization are available. This includes changing the underlying storage model that defines the selection’s polygons – I now use a List of Point arrays (<strong>List&lt;System.Windows.Point[]&gt;</strong>), which makes interoperating with <a href="http://en.wikipedia.org/wiki/GPC_General_Polygon_Clipper_Library" target="_blank">GPC</a> and <a href="http://en.wikipedia.org/wiki/Windows_Presentation_Foundation" target="_blank">WPF</a> easier and faster. I can optimize my clipping and do work ahead of time to ensure that rendering is fast. </p>
<p>I can split work like vector/matrix multiplication across multiple threads. I can even <em>prefetch</em> work ahead of time using “spare” CPU cycles. For instance, whenever the selection changes (moves, rotates, or is edited using add/subtract/union/intersection), I have to recompute the <em>scans</em> of the selection. This is a list of rectangles that I use to fill the interior of the selection with a blue tint. Well, in between the notification of a changed selection, and actually painting it (other stuff happens in the middle), I compute these scans in a background thread. This is a <em><a href="http://en.wikipedia.org/wiki/Future_(programming)" target="_blank">future</a></em> at work for you! </p>
<p>Also, I can make sure that these “scans” are computed and stored in sorted order with respect to their top Y coordinate. Then, when clipping the rendering of the highlighted selection interior, I can use a nicely fast <a href="http://en.wikipedia.org/wiki/Binary_search" target="_blank">binary search</a> to figure out which “scan” to start rendering from. Later on I’ll put in logic so that the computation itself can be clipped <em>(I never render the highlight outside of the image bounds, so why calculate that part?).</em> Oh, and did I mention that along the way I found some code on the critical path for the Magic Wand that was using <a href="http://en.wikipedia.org/wiki/Insertion_sort" target="_blank">insertion sort</a>? I didn’t? Well, it’s fixed. That was embarrassing.</p>
<p>Other opportunities for optimization include being smarter about which areas of the canvas are redrawn when things change. With GDI+, it was difficult to do the boolean path algebra correctly <em>(because of bugs in GDI+) </em>to find a minimal invalidation region, and so several heuristics were put into place. Now that I control all of the code for both rendering and computational geometry, I’ve been able to implement this better. This improves performance, and fixes some visual glitches whereby little bits and pieces of the selection outline remained when moving/rotating a selection <em>(the heuristic to fix this was, “every 1 second, redraw everything”)</em>.</p>
<p>This has all also served to help reacquaint myself with the Paint.NET codebase in areas that haven’t really seen much change in at least 2 years. Therefore, I’m better prepared for more refactoring after v3.5’s release. I’m changing gears for my work on v3.5: I’m going to stop fixing/refactoring things, and move to bugfixing mode. I’ve done a lot of optimizations, and there are still many more possible ones, but I also need to release something so that you all can use it! More optimizations can be trickled out over v3.5.1 or v3.6 releases, etc.</p>
<p>Anyway, that’s all for now. I hope you all will like it. One of my private beta testers sure does:</p>
<blockquote>
<p><em>“…the speed improvements in comparison to my memory of v3.36 are greatly improved on any Windows machine I throw it at. Really well done! I think that this alone will be enough to make people excited.”</em></p>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2009/02/25/introducing-paintnet-v35%e2%80%99s-new-selection-renderer/feed/</wfw:commentRss>
		</item>
		<item>
		<title>The theme of Paint.NET v3.5 is … performance</title>
		<link>http://blog.getpaint.net/2009/02/05/the-theme-of-paintnet-v35-is-%e2%80%a6-performance/</link>
		<comments>http://blog.getpaint.net/2009/02/05/the-theme-of-paintnet-v35-is-%e2%80%a6-performance/#comments</comments>
		<pubDate>Thu, 05 Feb 2009 08:01:02 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=328</guid>
		<description><![CDATA[I sat down to write some notes before starting this blog entry, and I wound up with two full pages in OneNote on the 1920&#215;1200 monitor it was sitting in. The more I’ve been working on it the more I’m excited about the Paint.NET v3.5 release. It isn’t one that introduces a lot of really [...]]]></description>
			<content:encoded><![CDATA[<p>I sat down to write some notes before starting this blog entry, and I wound up with two full pages in OneNote on the 1920&#215;1200 monitor it was sitting in. The more I’ve been working on it the more I’m excited about the Paint.NET v3.5 release. It isn’t one that introduces a lot of really cool or big-ticket features, but the list of small improvements is really adding up. I’ve been able to do a lot of research and prototyping in esoteric areas of multithreading and concurrency, and have gained both more mastery and more fear for these topics.</p>
<p>Performance work in Paint.NET v3.5 has wound up focusing on 3 areas:</p>
<ol>
<li><strong>Scaling up</strong>. As everyone’s been saying for years, the future is increasingly multithreaded. My newest CPU upgrade leaves me with 8 threads in Task Manager <em>(Intel Core i7 overclocked to 3.8GHz). </em>A lot of research and work has gone into making sure that Paint.NET continues to scale with more threads, and that I have better tools for safely and correctly implementing this across more of the application.
<p><em>”A high-end 64-bit Intel Core i7 desktop should run Paint.NET <u>very</u> fast.”</em></p>
<p><img src="http://www.getpaint.net/users/rick/blog/20090204_alienware.jpg">&nbsp;</p>
<li><strong>Scaling down.</strong> Those $300 netbooks that are taking everyone by storm only run about as fast as what I was using 7 years ago <em>(Pentium 4 at 2.0 – 2.5ghz)</em>. Clearly, classic optimization strategies are important as well: trimming cycles, removing or deferring code execution, and optimizing repainting.
<p><em>“A brand-new netbook with an Atom processor should run Paint.NET comfortably.”</em></p>
<p><img src="http://www.getpaint.net/users/rick/blog/20090204_dellmini9.jpg"></p>
<li><strong>Reducing memory usage.</strong> I guess this goes with scaling down. I made a bet a long time ago that 64-bit would slowly take care of the way I was allocating memory, which simplified development work but has had the consequence of consuming vast amounts of virtual address space . <strong>I was wrong: </strong>32-bit will be here for a <em>long</em> time, especially since most of those hot-like-pancakes $300 netbooks are <em><a href="http://processorfinder.intel.com/details.aspx?sSpec=SLB73" target="_blank">not 64-bit capable</a></em>. This is currently my top reliability issue, as running out of memory causes Paint.NET to crash.
<p><em>”It&#8217;s not <em>all</em> yours.”</em></p>
<p><img src="http://www.getpaint.net/users/rick/blog/20090204_ram.jpg"> </li>
</ol>
<p>I’ve had to split this discussion over several blog entries because otherwise it was too long and even I would have fallen asleep reading it. I’ll summarize the results here though:</p>
<ul>
<li>Images open much faster, especially on single-core/single-thread systems. <a href="http://blog.getpaint.net/2008/09/11/paintnet-and-performance-thumbnails/" target="_blank">Actually, I already wrote about this, so go read that first <img src='http://getpaint.setupmyblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </a>
<li>I <a href="http://blog.getpaint.net/2008/12/09/goodbye-pentium-4-hello-atom/" target="_blank">ordered</a> and <a href="http://blog.getpaint.net/2008/12/13/installing-net-35-sp1-please-wait-forever/" target="_blank">assembled</a> my own Atom-based mini-desktop (“nettop”), in order to keep myself honest as I was working on my Core 2 Quad QX6700 2.67 GHz monster and subsequently as I upgraded to a Core i7 920 2.66GHz overclocked to 3.8 GHz.
<li>The selection renderer has been completely rewritten. No more dancing ants and no more GDI+ means much lower CPU usage and better performance with multiple CPU cores.
<li>Much better CPU scaling for the image composition rendering pipeline using LINQ-esque functional programming and deferred execution techniques.
<li>A rewritten “render cache” has resulted in an average of 30-50% less memory usage when opening multiple images, especially those with just a single layer (PNG, JPEG). This means fewer out of memory <em>crashes</em>, and the ability to open more images without out-of-memory <em>errors</em>.</li>
</ul>
<p>Paint.NET v3.5 is a stepping stone towards a hopefully epic v4.0. I’m slowly rebuilding the application from the inside out, and it takes a lot of time to do the necessary research <em>and</em> development. About 2 years ago, right around the time I was preparing to release Paint.NET v3.0, I had this nagging feeling in the back of my head that said basically “<a href="http://icanhascheezburger.com/2008/02/23/funny-pictures-bird-watchin-yer-doin-it-wrong/" target="_blank">ur doin’ it wrong</a>”. My document model was wrong, my application model was brittle, and I just couldn’t implement really cool features without using up a <em>ton</em> of memory. I also couldn’t provide features like scripting or a better extensibility model (plugins) in a manner that was both safe and powerful.</p>
<p>However, I didn’t really know how to solve all of this at a scale lower than the 50,000-foot view. Since then I’ve been slowly piecing together the tools and knowledge that I’ll need to create the best version of Paint.NET ever – one that’s great both outside (for users) <em>and</em> inside (for developers).</p>
<p>Now, if you’ll excuse me, I’ve got to stop breaking things and start fixing them so that I can push out an alpha release.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2009/02/05/the-theme-of-paintnet-v35-is-%e2%80%a6-performance/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Mid-January Progress Update on Paint.NET v3.5</title>
		<link>http://blog.getpaint.net/2009/01/16/mid-january-progress-update-on-paintnet-v35/</link>
		<comments>http://blog.getpaint.net/2009/01/16/mid-january-progress-update-on-paintnet-v35/#comments</comments>
		<pubDate>Fri, 16 Jan 2009 09:06:06 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=326</guid>
		<description><![CDATA[I think it’s best to quote a private-message between myself and Ed Harvey on the forums:

I&#8217;ve got to stop breaking things before I start fixing them &#8230; 

Paint.NET v3.5 is turning out to be more work than I originally anticipated! What started out as a “simple” rewrite of the selection rendering system has turned into [...]]]></description>
			<content:encoded><![CDATA[<p>I think it’s best to quote a private-message between myself and Ed Harvey on the forums:</p>
<blockquote>
<p><em>I&#8217;ve got to stop breaking things before I start fixing them &#8230; </em></p>
</blockquote>
<p>Paint.NET v3.5 is turning out to be more work than I originally anticipated! What started out as a “simple” rewrite of the selection rendering system has turned into a major refactor of large portions of the code base. I’m done a wholesale adoption of WPF’s mathematics primitives such as Point, Rect, Int32Rect, Vector, Size, and Matrix. These classes do a better job and are more consistent than GDI+’s Point, PointF, Rectangle, RectangleF, Matrix, etc. (I’m still befuddled as to why <strong>System.Drawing.Drawing2D.Matrix</strong>, which is six floats and 24 bytes, needs a Dispose() method. Give me a struct please.)</p>
<p>The goal is to make sure that the entire data flow from the selection tools to the selection renderer is as performant as possible. Right now rendering performance is not favorable compared to Paint.NET v3.36, but it’s steadily improving and there’s a lot of tricks left up my sleeve.</p>
<p>Speaking of WPF, I’m <em>not</em> using it for the UI, although I’ve been learning a lot more about it. I’m starting to come up with devious and evil plans for how I can use it a lot more in the future. I’m also realizing that a lot of the current codebase is doing things “the very hard way”, and that certain ideas implemented across multiple files and tens of lines of code can often be expressed in just 1 or 2 lines of XAML.</p>
<p>Oh, but I am using WPF for the About dialog. It was a good exercise and learning experience <img src='http://getpaint.setupmyblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>I fixed the <a href="http://paintdotnet.forumer.com/viewtopic.php?f=10&amp;t=26787" target="_blank">“can’t move a small selection” bug</a>. The mouse input system for tools now uses double-precision floating point throughout, instead of integers. The problem here was that the tools were getting truncated mouse coordinates and even if you were zoomed in, and your 2&#215;2 pixel selection was filling your whole monitor, you still couldn’t move the selection around in an intuitive way because the Move tool only got integers describing the mouse position in terms of image coordinates.</p>
<p>Tablet PC “ink” and “pressure” support is out. It was implemented in a very bizarre way and was seriously preventing further progress and bug fixes. I haven’t had any hardware to test this for at least 3 years, so it has always been a best-faith feature. Hopefully it will make a comeback.</p>
<p>I’m itching to release <em>something</em> to the public. Maybe I should start putting up daily/weekly builds on the forum, even if just to get more testing done on the install and update code path. I’ve got a small private crowd of testers on the forum, and they’re a big help, but some fresh eyes would be useful.</p>
<p>I’ve also finished what I hope are my last round of “edits” or “drafts” on Paint.NET’s <em>functional</em> and <em>asynchronous</em> programming models. They both revolve around a base type called <strong>Result&lt;T&gt;</strong>, which is an implementation of the “either” monad specialized for values and errors. Here’s a simplified version:</p>
<blockquote>
<p><font face="consolas">public class Result&lt;T&gt;<br />{<br />&nbsp;&nbsp;&nbsp; public T Value { get; }<br />&nbsp;&nbsp;&nbsp; public bool IsValue { get; }<br />&nbsp;&nbsp;&nbsp; public Exception Error { get; }<br />&nbsp;&nbsp;&nbsp; public bool IsError { get; }<br />&nbsp;&nbsp;&nbsp; public bool NeedsObservation { get; }<br />&nbsp;&nbsp;&nbsp; public void Observe();<br />}</font></p>
</blockquote>
<p>You see, it’s always bugged me (more so recently) that in C# every method signature implicitely has a “I might throw an exception” tag on it. To borrow some C++ syntax:</p>
<blockquote>
<p>public delegate TRet Func&lt;T1, TRet&gt;(T1 arg1) <strong><u>throw(…)</u></strong>; // jee golly, I might throw! or not!</p>
</blockquote>
<p>There’s no way to specify “nothrow” and have the compiler statically enforce it. Because of this, every asynchronous programming model I’ve seen has its own special way of communicating things like success, aborted, canceled, or that an exception was thrown. The documentation never seems to be clear what happens if your callback throws an exception in its guest environment. It’s such a shame. Instead, let’s start with <strong>Func.Eval</strong> which helps us to normalize the situation:</p>
<blockquote>
<p><font face="consolas">public static class Func<br />{<br />&nbsp;&nbsp;&nbsp; public static Result&lt;TRet&gt; Eval(Func&lt;TRet&gt; f)<br />&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TRet value;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; value = f();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (Exception ex)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Result.NewError&lt;TRet&gt;(ex);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return Result.New&lt;TRet&gt;(value);<br />&nbsp;&nbsp;&nbsp; }<br />}</font></p>
</blockquote>
<p>In order to support “Eval” for Action delegates, Result&lt;T&gt; actually derives from a base Result class, which omits the Value and IsValue properties.</p>
<p>If a Result contains an error, then it must be <em>observed</em>. Put simply, you must either call Observe() or access the property getter for the Error property. Otherwise, once the Result instance is finalized by the garbage collector it will throw an exception, crash, and then burn. This ensures that no exceptions get lost or eaten. Also, when creating a Result that contains an error, the current stack trace is captured. This has already helped me a lot in debugging!</p>
<p>This whole system snakes through a few namespaces and DLL’s, and has undergone several waves of refactoring. I’m actually using all of it, so any clumsiness or impedance mismatch with the method overload resolution in the compiler is quickly caught and dealt with.</p>
<p>Oh, I mentioned that this ties into asynchronous programming as well. I’ll go into that in more detail later, but I’ve now got a very natural programming model for continuation-passing style which 1) makes it trivial to write sequences of code that “hops” between threads (think loading/computing in background and updating UI in foreground), and 2) doesn’t require any locks or mutexes to use (the implementation uses them), and 3) is almost as natural to use as synchronous code ala Func.Eval(). </p>
<p>It’s also served as the basis for what is now a trivial implementation of <em>iterative tasks. </em>I mentioned these briefly in an older blog post. It’s a clever hack that many people have developed independently whereby you “yield” instructions to a dispatcher to perform things like switching to another thread or doing efficient waits on other objects. Combine this with a data / task parallel library like what’s coming in .NET 4.0, and we’ve finally graduated to the toddler stage of concurrent programming.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2009/01/16/mid-january-progress-update-on-paintnet-v35/feed/</wfw:commentRss>
		</item>
		<item>
		<title>How to fix: Paint.NET &#8220;breaks&#8221; with Vista SP2 Beta</title>
		<link>http://blog.getpaint.net/2008/12/20/how-to-fix-paintnet-breaks-with-vista-sp2-beta/</link>
		<comments>http://blog.getpaint.net/2008/12/20/how-to-fix-paintnet-breaks-with-vista-sp2-beta/#comments</comments>
		<pubDate>Sat, 20 Dec 2008 22:31:42 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=325</guid>
		<description><![CDATA[I&#8217;ve had some reports that installing the Windows Vista SP2 beta (or &#8220;CPP&#8221;) breaks Paint.NET v3.36.
You&#8217;ll get an error message like so:

 

Contrary to the error, Paint.NET v3.36 does not require .NET Framework 3.5 SP1.
There are two ways to fix this:
1. Install .NET Framework 3.5 SP1. I recommend doing this anyway, because it has numerous [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve had some reports that installing the Windows Vista SP2 beta (or &#8220;CPP&#8221;) breaks Paint.NET v3.36.</p>
<p>You&#8217;ll get an error message like so:</p>
<blockquote>
<p><img src="http://www.getpaint.net/users/rick/blog/20081220_fx351req.png"> </p>
</blockquote>
<p>Contrary to the error, Paint.NET v3.36 does <em>not</em> require .NET Framework 3.5 SP1.</p>
<p>There are two ways to fix this:</p>
<p>1. <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=ab99342f-5d1a-413d-8319-81da479ab0d7" target="_blank">Install .NET Framework 3.5 SP1</a>. I recommend doing this anyway, because it has numerous fixes and performance improvements that make Paint.NET happy.</p>
<p>2. Go to the directory you installed Paint.NET, and remove all the files with the &#8220;.exe.config&#8221; extension. This will un-confuse the .NET loader stuff.</p>
<p>This seems to be something related to the .NET Client Profile, although I&#8217;m not sure what the root cause is. I&#8217;ll be reporting this bug to the right people, so that it can be fixed.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2008/12/20/how-to-fix-paintnet-breaks-with-vista-sp2-beta/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Installing .NET 3.5 SP1: Please wait &#8230; Forever!</title>
		<link>http://blog.getpaint.net/2008/12/13/installing-net-35-sp1-please-wait-forever/</link>
		<comments>http://blog.getpaint.net/2008/12/13/installing-net-35-sp1-please-wait-forever/#comments</comments>
		<pubDate>Sat, 13 Dec 2008 09:54:56 +0000</pubDate>
		<dc:creator>Rick Brewster</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blog.getpaint.net/?p=324</guid>
		<description><![CDATA[The very cool thing about Paint.NET v3.5 is that it installs quite fast on a fresh Windows XP SP2 machine. And that includes the installation of prerequisites like Windows Installer 3.1 and the Client Profile version of the .NET Framework 3.5 SP1. Even on my new little Atom 330 box* it is kind of pleasantly [...]]]></description>
			<content:encoded><![CDATA[<p>The very cool thing about Paint.NET v3.5 is that it installs quite fast on a fresh Windows XP SP2 machine. And that includes the installation of prerequisites like Windows Installer 3.1 <em>and</em> the Client Profile version of the .NET Framework 3.5 SP1. Even on <a href="http://blog.getpaint.net/2008/12/09/goodbye-pentium-4-hello-atom/" target="_blank">my new little Atom 330 box</a>* it is kind of pleasantly fast. I&#8217;d even say it&#8217;s fun. <em>(The unfortunate thing is that Paint.NET v3.5 is not yet out of &#8220;pre-alpha&#8221; &#8230;)</em></p>
<form action="http://www.jdoqocy.com/interactive" method="get" target="_blank">
<table cellspacing="0" cellpadding="5" width="600" border="0">
<tbody>
<tr>
<td valign="top" width="10%"><img alt="Intel BOXD945GCLF2 Atom 330 Mini ITX Motherboard/CPU Combo" src="http://images10.newegg.com/ProductImageCompressAll200/13-121-359-02.jpg" border="0"></td>
<td valign="top">
<p><b><font size="4">Intel BOXD945GCLF2 Atom 330 Mini ITX Motherboard/CPU Combo</font></b></p>
<p><font size="2">Intel BOXD945GCLF2 Atom 330 Intel 945GC Mini ITX Motherboard/CPU Combo</font></p>
<hr />
<input type="hidden" value="3274622" name="pid">
<input type="hidden" value="10440897" name="aid">
<input type="hidden" value="N82E16813121359" name="cjsku">
<input type="hidden" value="http://www.newegg.com/Product/Product.aspx?Item=N82E16813121359&amp;nm_mc=AFC-C8Junction&amp;cm_mmc=AFC-C8Junction-_-Motherboard / CPU / VGA Sets-_-Intel-_-13121359" name="url">
<input type="submit" value="Buy"> </td>
</tr>
</tbody>
</table>
</form>
<p><img height="1" src="http://www.ftjcfx.com/image-3274622-10440897" width="1" border="0">
<p>Once you jump over to Windows Vista, the story becomes very very very <em>very</em> dire. <strong>It took a full hour to install .NET 3.5 SP1.</strong> The hard drive was thrashing and yelling the entire time, and CPU usage was quite high. In the middle of this, a Windows Update dialog popped up in the corner telling me I needed to restart. That sounds like a bad idea since I&#8217;m still in the middle of installing a new system component! This paints a <em>very </em>bleak picture for getting .NET 3.5 SP1 and Paint.NET v3.5 successfully deployed to the large userbase that I have currently sitting on .NET 2.0 and Paint.NET v3.36. I&#8217;m afraid that most users will see the .NET installer &#8220;hanging&#8221; at 40% and just restart their computer, or cancel it, or kill it using Task Manager. How fun will it be for users to click on &#8220;Install Update&#8221; only to have to wait an hour before they can use their computer again, let alone Paint.NET?</p>
<p>I honestly don&#8217;t think it&#8217;s worth 1 hour to install a 2 MB program. Even <a href="http://www.adobe.com/products/photoshop/family/" target="_blank">Adobe Photoshop</a> and <a href="http://wolfram.com/products/mathematica/index.html" target="_blank">Mathematica 7.0</a> install in minutes, and they are hundreds of megabytes.</p>
<p>This isn&#8217;t a random or one-off occurrence &#8212; this is not the first time I&#8217;ve seen this. Almost every time I&#8217;ve installed .NET 3.5 SP1 on to any system, whether it&#8217;s mine or someone else&#8217;s, the same thing happens. <strong>It doesn&#8217;t matter if it&#8217;s an Atom or a brand new 3.0GHz Core 2 Duo, it still takes one full hour.</strong> Sometimes you can actually get the installation to complete quickly <em>if</em> you go and make sure that Windows Update is <em>completely</em> caught up. Even then, you can never be completely sure. Any system that isn&#8217;t used 8+ hours/day by a computer-industry professional like myself is likely to be at least 1 update behind. <em>(I&#8217;ll bet a <a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16819115200" target="_blank">Core i7 965</a> could do it in 45 minutes though :))</em></p>
<p>This is <strong>very</strong> frustrating, to say the least. On the positive side I know some of the people who work on this stuff, and they&#8217;re all great people who want things to be awesome. You can be sure I&#8217;ll be e-mailing them soon <img src='http://getpaint.setupmyblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> And with any luck, the &#8220;GDR&#8221; update that&#8217;s coming (soon?) will have already fixed this. Cross your fingers.</p>
<p>Performance of the Atom 330 is actually surprisingly good. The results of 32-bit PdnBench are almost exactly the same as a <a href="http://www.newegg.com/Product/Product.aspx?Item=N82E16819116027" target="_blank">Pentium 4 3.0 GHz &#8220;E&#8221; Prescott</a> chip &#8212; about 180 seconds for completion &#8212; which is impressive to say the least. Back in the day (2004) that P4 chip consumed so much power that some reviewers melted their motherboards, whereas this Atom barely even needs a heatsink. In 64-bit mode, the Atom 330 pulls ahead to 155 seconds. Those results use 2 threads on the P4 (single core w/ HyperThreading), and 4 on the Atom (dual core w/ HyperThreading).</p>
<p><em>* Actually it&#8217;s not really a box. It&#8217;s small, and not inside of a case. Maybe &#8220;kit&#8221; would be a better term?</em></p>
<p><em>** Yes, I&#8217;m testing out some newegg.com affiliate stuff. If you&#8217;re interested in the Atom 330 board listed above, then please click on the &#8220;Buy&#8221; button above. Just like Amazon affiliate links, if you buy it via that link then I get a tiny amount of the purchase price. It doesn&#8217;t cost you anything extra. It&#8217;s another way to support Paint.NET <img src='http://getpaint.setupmyblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </em></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.getpaint.net/2008/12/13/installing-net-35-sp1-please-wait-forever/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
