Quick and Dirty Output of WriteableBitmap as TGA Image
Jan 21, 2010
If you ever needed to save a WriteableBitmap to an image file without too much hassle (e.g. for debugging purposes), you could use this simple source code to save it as TGA and then open with Paint.NET:
From Wikipedia: "TGA files are in widespread use due to their simplicity and ease of implementation and lack of encumbering patents."
[code:c#]
public static class TgaWriter {
public static void Write(WriteableBitmap bitmap, Stream output) {
int width = bitmap.PixelWidth;
int height = bitmap.PixelHeight;
int[] pixels = bitmap.Pixels;
byte[] pixelsArr = new byte[pixels.Length * 4];
int offsetSource = 0;
int width4 = width * 4;
int width8 = width * 8;
int offsetDest = (height - 1) * width4;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int value = pixels[offsetSource];
pixelsArr[offsetDest] = (byte)(value & 255); // b
pixelsArr[offsetDest + 1] = (byte)((value >> 8) & 255); // g
pixelsArr[offsetDest + 2] = (byte)((value >> 16) & 255); // r
pixelsArr[offsetDest + 3] = (byte)(value >> 24); // a
offsetSource++;
offsetDest += 4;
}
offsetDest -= width8;
}
byte[] header = new byte[] {
0, // ID length
0, // no color map
2, // uncompressed, true color
0, 0, 0, 0,
0,
0, 0, 0, 0, // x and y origin
(byte)(width & 0x00FF),
(byte)((width & 0xFF00) >> 8),
(byte)(height & 0x00FF),
(byte)((height & 0xFF00) >> 8),
32, // 32 bit bitmap
0 };
using (BinaryWriter writer = new BinaryWriter(output)) {
writer.Write(header);
writer.Write(pixelsArr);
}
}
}
[/code]
Here's a sample usage of the above class:
Important Edit: if you want to support transparency, you'd have to call CompensateForRender() from this post: http://nokola.com/blog/post/2010/01/27/The-Most-Important-Silverlight-WriteableBitmap-Gotcha-Does-It-LoseChange-Colors.aspx
[code:c#]
private void btnSave_Click(object sender, RoutedEventArgs e) {
WriteableBitmap _screen;
// ... do something with the WriteableBitmap here...
SaveFileDialog dialog = new SaveFileDialog();
dialog.DefaultExt = ".tga";
dialog.Filter = "TGA Image (*.tga)|*.tga";
dialog.FilterIndex = 1;
if (dialog.ShowDialog() != true) return;
using (Stream fileStream = dialog.OpenFile()) {
TgaWriter.Write(_screen, fileStream);
fileStream.Close();
}
}
[/code]
The benefit of the above code is that you don't have to worry about image libraries, external binary dependencies and such - just paste & go :)
The TGA file format: http://en.wikipedia.org/wiki/Truevision_TGA