Welcome to MSDN Blogs Sign in | Join | Help

You had me at "Hello World!"

XAML, WPF, Silverlight, .NET, Office 2007, Windows code samples and other interesting things

Syndication

Silverlight: Super-fast Dymanic Image Generation Code (Revisited)

I decided to give a third spin of Joe Stegman's dynamic image generation code. This time, it's many times faster (about 10x) than the original implementation and the png is generated in-place (no recoding necessary).

I used some hacky optimizations :) For example, replacing the big CRC loop with a constant (0), definitely improves speed a lot! :)

There are no more intermediate memory streams or buffers: whenever SetPixel() is called, the value is written directly into PNG. Also all the header and size information is created just once. That also helped performance quite a bit.

With the new code my raindrops sample runs 20% faster (90% of the time used in calculating the drops): www.nokola.com/raindrops

Download the source code containing the new PngEncoder class here: www.nokola.com/sources/water.zip

Here's how to use the new image generator class:

PngEncoder surface = new PngEncoder(640, 480); // image dimension

surface.SetPixelSlow(40, 30, 200, 135, 32, 255); // set pixel at (40,30) with color RGBA=(200,135,32,255)

           

// draw a white horizontal line fast

int rowStart = surface.GetRowStart(30);

for (int i = 0; i < 10; i++) {

// SetPixelAtRowStart() is good for blitting/copying existing images onto this one

surface.SetPixelAtRowStart(i + 40, rowStart, 255, 255, 255, 255);

}

 

// display the image

BitmapImage img = new BitmapImage();

img.SetSource(surface.GetImageStream());

imgWater.Source = img; // this is just a normal Silverlight Image

 

And, here's the GetImageStream() function for comparison with the previous implementation:

public Stream GetImageStream()

{

MemoryStream ms = new MemoryStream();

ms.Write(_buffer, 0, _buffer.Length);

ms.Seek(0, SeekOrigin.Begin);

return ms;

}

Compare this to the previous function, that had numerous for()-s, encoding logic, etc :)

hoho! I'm very happy for doing this!

Edit: here's the source code for the SetPixelXX functions - to prove they are actually not slow :)

public void SetPixelSlow(int col, int row, byte red, byte green, byte blue, byte alpha)

{

int start = _rowLength * row + col * 4 + 1;

      int blockNum = start / _blockSize;

      start += ((blockNum + 1) * 5);

      start += _dataStart;

 

      _buffer[start] = red;

      _buffer[start + 1] = green;

      _buffer[start + 2] = blue;

      _buffer[start + 3] = alpha;

}

 

public void SetPixelAtRowStart(int col, int rowStart, byte red, byte green, byte blue, byte alpha)

{

int start = rowStart + (col << 2);

 

      _buffer[start] = red;

      _buffer[start + 1] = green;

      _buffer[start + 2] = blue;

      _buffer[start + 3] = alpha;

}

 

public int GetRowStart(int row)

{

int start = _rowLength * row + 1;

      int blockNum = start / _blockSize;

      start += ((blockNum + 1) * 5);

      start += _dataStart;

      return start;

}

 

 

Published Wednesday, March 04, 2009 5:33 PM by nikola

Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Thursday, March 05, 2009 2:30 PM

VERY cool stuff.

This encoder is blasting away the old one!

Btw. line 74 in PngEncoder is unused.

SharpGIS

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Tuesday, May 26, 2009 4:36 PM

Thanks!

nikola

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Tuesday, June 23, 2009 2:42 AM

When I try to use the code above, I cannot read the generated png stream, all imaging programs say that it's not a valid png format (including .NET's libraries under WPF). Did anybody else have issues?

Christoph

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Saturday, June 27, 2009 10:05 AM

Hi,

Unfortunately the code strangely doesn't work with WPF, the produced image seems to be not a valid PNG image. Any ideas?

Christoph

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Wednesday, July 01, 2009 1:22 PM

Yes, the produced image is not a valid PNG (the CRC is set to 0). This is a trick that allows to generate the PNG much faster and it happens to work in SL 2. For WPF/other programs, check out my previous posts about PNG image generation. The generators there make valid PNGs according to the spec, but slower.

nikola

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Wednesday, July 01, 2009 4:05 PM

Ah, okay, perfect. And sorry for double posting, I though the blog ate my comment.

Thanks,

Christoph

Christoph

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Wednesday, July 01, 2009 4:57 PM

no problem :) I just came back from 3 weeks holiday and saw your comment that was left for review by the blog software.

nikola

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Tuesday, August 18, 2009 3:41 AM

Humm... interesting,

So it is truely faster!!

Thanks for bringing this up

geeks

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Tuesday, August 18, 2009 1:43 PM

yw :) Silverlight 3 has a new WritableBitmap class that makes the png code above (partially) obsolete.

http://www.wintellect.com/CS/blogs/jprosise/archive/2009/03/23/silverlight-3-s-new-writeablebitmap.aspx

I haven't perf-ed it but I bet it's faster than the previous method.

nikola

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Thursday, September 24, 2009 11:09 AM

Hi,

I have a problem with this approach when my canvas size is more than 3000...

If i write the resultant image and try to open it, i am not able to view anything.. the image is corrupted... But the approach works fine for smaller images(Canvas).

any idea on this??

Thanks,

Ravi

Ravi

# re: Silverlight: Super-fast Dymanic Image Generation Code (Revisited) @ Friday, September 25, 2009 1:33 AM

I'm not sure why the image gets corrupted over 3000 size...might be an issue with the algorithm I'm using.

Anyway, a better approach is to use WritableBitmap, which is now available in SL3. The approach above is for SL2, which does not have WritableBitmap.

Check this blog for more info:

http://www.wintellect.com/CS/blogs/jprosise/archive/2009/03/23/silverlight-3-s-new-writeablebitmap.aspx

hope this helps - please let me know!

nikola

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
Page view tracker