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."

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);
        }
    }
}

 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

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();
    }
}

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

 

  
blog comments powered by Disqus

nokola.com | Terms | Log in

Recent

About the author

Happy & enjoying life. Software enthusiast.
The opinions I express here and on nokola.com are mine and not my employeer's (Microsoft).
This is the official blog of nokola.com. You can find Silverlight samples, coding stuff, and hopefully other interesting things here.