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

 

  

Comments

1/22/2010 12:32:48 PM #

Rene Schulte

Nice and useful. Thanks for sharing.
I think this could also be a good addition for the WriteableBitmapEx library. What do you think?

Rene Schulte | Reply

1/27/2010 4:52:02 PM #

nokola

Thanks! Yes, it would be nice to add it there...Unfortunately I have to wrap up something else first - please feel free to put it in if you'd like  - I may not get to it for long time Smile Note you may have to do premultiplication conversion before saving too (nokola.com/.../...-Does-It-LoseChange-Colors.aspx)

nokola | Reply

1/28/2010 1:09:51 PM #

Rene Schulte

I've put it into the WriteableBitmapEx library as WriteTga method. Thanks for sharing it!
BTW, the alpha channel was saved fine without the pre multiplication.

Rene Schulte | Reply

1/29/2010 5:44:59 AM #

nokola

Thanks for putting it in the library! btw, I'm pretty sure the TGA output should not work without premultiplication...interesting
If you'd like I'll send you my test .png to try with - is that OK?
If the alpha is 255 or 0 (or close to one of these 2 values), the difference is probably not noticeable, but if it's something like 128, it gets pretty weird Smile

nokola | Reply

1/27/2010 7:17:15 AM #

trackback

The Most Important Silverlight WriteableBitmap Gotcha - Does It Lose/Change Colors?

The Most Important Silverlight WriteableBitmap Gotcha - Does It Lose/Change Colors?

You Had Me At 'Hello World!' | Reply

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading



nokola.com | Terms | Log in