/// <summary> /// Reads the image data bytes from the file and loads them into the Image Bitmap object. /// Also loads the color map, if any, into the Image Bitmap. /// </summary> /// <param name="binReader">A BinaryReader that points the loaded file byte stream.</param> 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); // get the Pixel format to use with the Bitmap object TGAPixelFormat 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 RawTGABitmap((int)this.objTargaHeader.Width, (int)this.objTargaHeader.Height, bimagedata, pf); 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; } } */ // 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)) }
/// <summary> /// Loads the thumbnail of the loaded image file, if any. /// </summary> /// <param name="binReader">A BinaryReader that points the loaded file byte stream.</param> /// <param name="pfPixelFormat">A PixelFormat value indicating what pixel format to use when loading the thumbnail.</param> private void LoadThumbnail(BinaryReader binReader, TGAPixelFormat pfPixelFormat) { // read the Thumbnail image data into a byte array // take into account stride has to be a multiple of 4 // use padding to make sure multiple of 4 byte[] data = null; if (binReader != null && binReader.BaseStream != null && binReader.BaseStream.Length > 0 && binReader.BaseStream.CanSeek == true) { if (this.ExtensionArea.PostageStampOffset > 0) { // seek to the beginning of the image data using the ImageDataOffset value binReader.BaseStream.Seek(this.ExtensionArea.PostageStampOffset, SeekOrigin.Begin); int iWidth = (int)binReader.ReadByte(); int iHeight = (int)binReader.ReadByte(); int iStride = ((iWidth * (int)this.objTargaHeader.PixelDepth + 31) & ~31) >> 3; // width in bytes int iPadding = iStride - (((iWidth * (int)this.objTargaHeader.PixelDepth) + 7) / 8); System.Collections.Generic.List<System.Collections.Generic.List<byte>> objRows = new System.Collections.Generic.List<System.Collections.Generic.List<byte>>(); System.Collections.Generic.List<byte> objRow = new System.Collections.Generic.List<byte>(); byte[] padding = new byte[iPadding]; MemoryStream msData = null; bool blnEachRowReverse = false; bool blnRowsReverse = false; using (msData = new MemoryStream()) { // get the size in bytes of each row in the image int intImageRowByteSize = iWidth * ((int)this.objTargaHeader.PixelDepth / 8); // get the size in bytes of the whole image int intImageByteSize = intImageRowByteSize * iHeight; // thumbnails are never compressed for (int i = 0; i < iHeight; i++) { for (int j = 0; j < intImageRowByteSize; j++) { objRow.Add(binReader.ReadByte()); } objRows.Add(objRow); objRow = new System.Collections.Generic.List<byte>(); } switch (this.objTargaHeader.FirstPixelDestination) { case FirstPixelDestination.TOP_LEFT: break; case FirstPixelDestination.TOP_RIGHT: blnRowsReverse = false; blnEachRowReverse = false; break; case FirstPixelDestination.BOTTOM_LEFT: break; case FirstPixelDestination.BOTTOM_RIGHT: case FirstPixelDestination.UNKNOWN: blnRowsReverse = true; blnEachRowReverse = false; break; } if (blnRowsReverse == true) objRows.Reverse(); for (int i = 0; i < objRows.Count; i++) { if (blnEachRowReverse == true) objRows[i].Reverse(); byte[] brow = objRows[i].ToArray(); msData.Write(brow, 0, brow.Length); msData.Write(padding, 0, padding.Length); } data = msData.ToArray(); } if (data != null && data.Length > 0) { this.bmpImageThumbnail = new RawTGABitmap(iWidth, iHeight, data, pfPixelFormat); } } } }
/// <summary> /// Creates a new instance of the TargaImage object. /// </summary> public TargaImage() { this.objTargaFooter = new TargaFooter(); this.objTargaHeader = new TargaHeader(); this.objTargaExtensionArea = new TargaExtensionArea(); this.bmpTargaImage = null; this.bmpImageThumbnail = null; }