private void LoadTGAImage(BinaryReader binReader)
{
//************** NOTE *******************
// The memory allocated for Microsoft Bitmaps must be aligned on a 32bit boundary.
// The stride refers to the number of bytes allocated for one scanline of the bitmap.
// In your loop, you copy the pixels one scanline at a time and take into
// consideration the amount of padding that occurs due to memory alignment.
// calculate the stride, in bytes, of the image (32bit aligned width of each image row)
this.intStride = (((int)this.objTargaHeader.Width * (int)this.objTargaHeader.PixelDepth + 31) & ~31) >> 3; // width in bytes
// calculate the padding, in bytes, of the image
// number of bytes to add to make each row a 32bit aligned row
// padding in bytes
this.intPadding = this.intStride - ((((int)this.objTargaHeader.Width * (int)this.objTargaHeader.PixelDepth) + 7) / 8);
// get the image data bytes
byte[] bimagedata = this.LoadImageBytes(binReader);
// since the Bitmap constructor requires a poiter to an array of image bytes
// we have to pin down the memory used by the byte array and use the pointer
// of this pinned memory to create the Bitmap.
// This tells the Garbage Collector to leave the memory alone and DO NOT touch it.
this.ImageByteHandle = GCHandle.Alloc(bimagedata, GCHandleType.Pinned);
// make sure we don't have a phantom Bitmap
if (this.bmpTargaImage != null) {
this.bmpTargaImage.Dispose();
}
// make sure we don't have a phantom Thumbnail
if (this.bmpImageThumbnail != null) {
this.bmpImageThumbnail.Dispose();
}
// get the Pixel format to use with the Bitmap object
PixelFormat pf = this.GetPixelFormat();
// create a Bitmap object using the image Width, Height,
// Stride, PixelFormat and the pointer to the pinned byte array.
this.bmpTargaImage = new Bitmap((int)this.objTargaHeader.Width,
(int)this.objTargaHeader.Height,
this.intStride,
pf,
this.ImageByteHandle.AddrOfPinnedObject());
this.LoadThumbnail(binReader, pf);
// load the color map into the Bitmap, if it exists
if (this.objTargaHeader.ColorMap.Count > 0) {
// get the Bitmap's current palette
ColorPalette pal = this.bmpTargaImage.Palette;
// loop trough each color in the loaded file's color map
for (int i = 0; i < this.objTargaHeader.ColorMap.Count; i++) {
// is the AttributesType 0 or 1 bit
if (this.objTargaExtensionArea.AttributesType == 0 ||
this.objTargaExtensionArea.AttributesType == 1)
// use 255 for alpha ( 255 = opaque/visible ) so we can see the image
pal.Entries[i] = Color.FromArgb(255, this.objTargaHeader.ColorMap[i].R, this.objTargaHeader.ColorMap[i].G, this.objTargaHeader.ColorMap[i].B);
else
// use whatever value is there
pal.Entries[i] = this.objTargaHeader.ColorMap[i];
}
// set the new palette back to the Bitmap object
this.bmpTargaImage.Palette = pal;
// set the palette to the thumbnail also, if there is one
if (this.bmpImageThumbnail != null) {
this.bmpImageThumbnail.Palette = pal;
}
} else { // no color map
// check to see if this is a Black and White (Greyscale)
if (this.objTargaHeader.PixelDepth == 8 && (this.objTargaHeader.ImageType == ImageType.UNCOMPRESSED_BLACK_AND_WHITE ||
this.objTargaHeader.ImageType == ImageType.RUN_LENGTH_ENCODED_BLACK_AND_WHITE)) {
// get the current palette
ColorPalette pal = this.bmpTargaImage.Palette;
// create the Greyscale palette
for (int i = 0; i < 256; i++) {
pal.Entries[i] = Color.FromArgb(i, i, i);
}
// set the new palette back to the Bitmap object
this.bmpTargaImage.Palette = pal;
// set the palette to the thumbnail also, if there is one
if (this.bmpImageThumbnail != null) {
this.bmpImageThumbnail.Palette = pal;
}
}
}
}