Initialize Git repository
Initial import of version 1.0.4 into Codeplex
Get code to compile cleanly

1. Updated solution to Visual Studio 2010.
2. Set target framework to .NET Framework 3.5 to match Paint.NET.
3. Updated DLL references for Paint.NET 3.5.2.
4. Revised code to match Paint.NET interfaces.
5. Deleted post-build copy action.
Preserve layer blend mode on save
Reduce filesizes by saving partial layers

Cliff Cawley originally made this change and distributed it separately.
Now that an authoritative source code repository has been established on
Codeplex, the change can be brought back into trunk.

Internally, Paint.NET layers have the same dimensions as the canvas.
However, this change allows our PSD files to load more efficiently into
Photoshop, which uses less memory for partial layers.
Release version 1.0.5
Convert Channels into an array

Profiling showed that over half (!) of the time is spent doing
SortedList key lookups on SortedChannels.  In contrast, array indexing
can be optimized into pointer arithmetic, so it is much more efficient.

This results in a 2x performance improvement for both loading and
saving.  The remaining hotspots are in color-conversion and MemoryBlock
accesses.
Reduce abstraction overhead in color conversion

Previously, ImageDecoderPdn had been:
  1. Converting the PSD channel-separated format to System.Drawing.Color
  2. Converting the Color to a PaintDotNet.ColorBgra
  3. Copying the ColorBgra into the PaintDotNet.MemoryBlock, one byte
     at a time.

This change collapses the three copies into one, by changing the
GetColor functions into SetColor functions that operate directly on the
MemoryBlock.

This results in a 2x performance improvement for PSD loading.  Most of
the time is now spent in MemoryBlock, which is Paint.NET code.
Release version 1.0.6
Use pointers for faster color-conversion

Profiling showed that the MemoryBlock accesses were also spending about
80% of their time on non-productive tasks:
  1. Checking that the object has not been disposed.
  2. Bounds-checking.

It is not necessary to do these checks on every single pixel.  The
plugin already does its own bounds-checking:
  1. Surface.GetRow will throw if the y coordinate is out of bounds.
  2. The x-coordinate is clamped at Surface.Width for each row.

Moving to unsafe pointer operations increases PSD loading speed by about
5x.  The bounds-checking calculations are moved outside of the loop for
greater speed.
Use Paint.NET API for more robust pointers

Color-conversion code has been modified to work with ColorBgra* pointers
and call Surface.GetRowAddressUnchecked.  This is less fragile than
using MemoryBlock.Pointer directly as a byte*, as it avoids hard-
coding the byte layout of the ColorBgra structure.
Use pointers for faster saving of PSD files

When saving, most of the time is now spent in Document.Render, which
renders the flattened preview image in the PSD file.  Document.Render is
wholly Paint.NET code, and does not call into the plugin.
Release version 1.0.7
More performance optimizations

At Rick Brewster's suggestion:

  1. Called the safer GetRowAddress instead of GetRowAddressUnchecked.
     Performance impact is minimal, as it is called from the outer loop.
  2. Rendered to the scratch surface that is passed into OnSave, rather
     than allocating another Surface.
  3. Used pointers instead of array indexing for greater speed.

Additional performance optimizations for specific color modes:

  1. CMYK loading was wasting 1/2 of its runtime recalculating
     Math.Pow(2, 8) for every single pixel.  This is now hardcoded.
  2. Lab loading was wasting 2/3 of its time using Math.Pow to raise
     values to the third power.  Multiplication is much faster.

In both cases, the range has also been reset to 255 instead of 256.
RLE compression for layer image data

RLE compression had already been implemented, but SavePixelData was
always writing the uncompressed data.  Changing this one line allows RLE
to work properly.  As expected, this reduces file sizes by an order of
magnitude.

Performance of RLE compression is also improved by having it write RLE
packets directly from the image data, rather than copying into a buffer
first.  A number of misspelled identifiers have also been fixed.
Process layers/channels in parallel

The last change caused a doubling of PSD saving time, as RLE compression
is a processor-intensive operation.  To counteract this performance
drop, I have used the Paint.NET private threadpool to parallelize most
of the loading and saving operations at the granularity of layers or
channels.  On a system with lots of cores, the plugin now performs quite
well indeed.

There is still some sequentiality remaining (notably in masks).  Also,
single-layer images will only benefit from the parallelization that was
done at a channel granularity.  However, it's mostly the images with
high layer counts that tend to slow down anyway.
Release version 1.5.0

Major bump in version number because RLE is a big deal.

I've also convinced myself that PSD files written by Photoshop really
are violating the specification by not padding RLE-compressed rows to
even lengths.  Thus, the current implementation is correct.
Apply patch from K9998 for Unicode font error
Fix bugs reported by Karl Barger

Bugs fixed:
  1. RLE decompression was working off signed int's, resulting in
     negative row lengths.
  2. User mask was not being read in, causing the reader position to be
     offset.
Work item 6191: Load bitmap-mode images

Bitmap images are fairly straightforward.  However, note that rows are
byte-aligned in the file.