// set header info on creation private void SetHeaderInfo(int w, int h, int bpp, int palDepth, TgaEncoding enc) { // check if the encoding uses rle or compression and throw an exception if it does if (EncodingUsesRleOrCmp(enc)) { throw new NotImplementedException("Encodings using RLE encoding or compression are not supported."); } else if (enc == TgaEncoding.Grayscale) { throw new NotImplementedException("Grayscale encoding is not supported."); } bool isIndexed = IsIndexedEncoding(enc); mIdLength = 0; mColorMapType = isIndexed ? (byte)1 : (byte)0; mDataType = enc; if (isIndexed) { mPaletteStartIndex = 0; mPaletteLength = (short)(1 << bpp); mPaletteDepth = (byte)palDepth; } mXOrigin = 0; mYOrigin = 0; mWidth = (short)w; mHeight = (short)h; mBpp = (byte)bpp; mImageDescriptor = 0; }
private static void WritePixels(BinaryWriter writer, TgaEncoding type, Color[] pixels, int depth, int width, int height, bool palette) { if (EncodingUsesRleOrCmp(type)) { throw new NotImplementedException(); } else { WritePixelData(writer, pixels, depth, width, height, palette); } }
private static Color[] ReadPixels(BinaryReader reader, TgaEncoding type, int bpp, int width, int height) { byte[] pixelData = reader.ReadBytes((int)((width * height) * ((float)bpp / 8))); if (EncodingUsesRleOrCmp(type)) { TgaDataDecoder decoder = GetDecoder(type); throw new NotImplementedException(); } else { return(DecodeUncompressedPixelDataToColors(pixelData, bpp, width, height, false)); } }
private static bool IsIndexedEncoding(TgaEncoding encoding) { switch (encoding) { case TgaEncoding.Indexed: case TgaEncoding.IndexedRLE: case TgaEncoding.IndexedHDRLE: case TgaEncoding.IndexedHDRLEQ: return(true); default: return(false); } }
// encoding id checking helpers private static bool EncodingUsesRleOrCmp(TgaEncoding type) { switch (type) { case TgaEncoding.IndexedRLE: case TgaEncoding.RGBRLE: case TgaEncoding.GrayScaleCmp: case TgaEncoding.IndexedHDRLE: case TgaEncoding.IndexedHDRLEQ: return(true); default: return(false); } }
private static TgaDataEncoder GetEncoder(TgaEncoding type) { switch (type) { case TgaEncoding.IndexedRLE: case TgaEncoding.RGBRLE: case TgaEncoding.GrayScaleCmp: case TgaEncoding.IndexedHDRLE: case TgaEncoding.IndexedHDRLEQ: throw new NotImplementedException($"Encoder for data id: {type} is not implemented."); default: throw new ArgumentException($"DataStructNode id: {type} is not encoded."); } }
private static byte[] ReadIndices(BinaryReader reader, TgaEncoding type, int bpp, int width, int height) { byte[] indices = reader.ReadBytes((int)((width * height) * ((float)bpp / 8))); if (EncodingUsesRleOrCmp(type)) { TgaDataDecoder decoder = GetDecoder(type); throw new NotImplementedException(); } else { indices = DecodeUncompressedIndexDataTo8Bit(indices, bpp, width, height); } return(indices); }
/// <summary> /// Initializes a new instance of the <see cref="TgaFile"/> class from the specified <see cref="Bitmap"/> class, and encoding parameters to encode the bitmap with. /// </summary> /// <param name="bitmap">The bitmap instance used for encoding.</param> /// <param name="encodingType">Specifies the pixel data encoding to use.</param> /// <param name="bitsPerPixel">Specifies the amount of bits per pixel. /// 4 and 8 are reserved for indexed encodings, while 16, 24 and 32 are used for non-indexed images.</param> /// <param name="paletteDepth">Specifies the amount of bits per color in the palette. Ignored if the encoding id is of an indexed encoding.</param> public TgaFile(Bitmap bitmap, TgaEncoding encodingType = TgaEncoding.Indexed, int bitsPerPixel = 8, int paletteDepth = 32) { // set header SetHeaderInfo(bitmap.Width, bitmap.Height, bitsPerPixel, paletteDepth, encodingType); // done if the encoding id is set to none if (encodingType == TgaEncoding.None) { return; } // set bitmap data if (IsIndexed) { BitmapHelper.QuantizeBitmap(bitmap, 1 << bitsPerPixel, out mPaletteIndices, out mPalette); } else { mPixels = BitmapHelper.GetColors(bitmap); } }
internal void Read(BinaryReader reader) { mIdLength = reader.ReadByte(); mColorMapType = reader.ReadByte(); mDataType = (TgaEncoding)reader.ReadByte(); mPaletteStartIndex = reader.ReadInt16(); mPaletteLength = reader.ReadInt16(); mPaletteDepth = reader.ReadByte(); mXOrigin = reader.ReadInt16(); mYOrigin = reader.ReadInt16(); mWidth = reader.ReadInt16(); mHeight = reader.ReadInt16(); mBpp = reader.ReadByte(); mImageDescriptor = reader.ReadByte(); // format check if (EncodingUsesRleOrCmp(mDataType) || mDataType == TgaEncoding.Grayscale) { throw new NotImplementedException($"DataStructNode id not supported: {mDataType}"); } else if (mDataType == TgaEncoding.None) { return; } // skip user data reader.Seek(mIdLength, SeekOrigin.Current); if (IsIndexed) { // read palette and indices mPalette = ReadPalette(reader, mPaletteLength, mBpp, mPaletteDepth); mPaletteIndices = ReadIndices(reader, mDataType, mBpp, mWidth, mHeight); } else { // read pixels mPixels = ReadPixels(reader, mDataType, mBpp, mWidth, mHeight); } }
/// <summary> /// Initializes a new instance of the <see cref="TgaFile"/> class from specified dimensions, color palette, pixel indices and encoding parameters that suit the provided image data. /// </summary> /// <param name="width">The width of the image.</param> /// <param name="height">The height of the image.</param> /// <param name="palette">The color palette of the image</param> /// <param name="pixelIndices">The per-pixel palette color indices of the image.</param> /// <param name="encodingType">Specifies the pixel data encoding to use.</param> /// <param name="bitsPerPixel">Specifies the amount of bits per pixel. /// 4 and 8 are reserved for indexed encodings, while 16, 24 and 32 are used for non-indexed images.</param> /// <param name="paletteDepth">Specifies the amount of bits per color in the palette. Ignored if the encoding id is of an indexed encoding.</param> public TgaFile(int width, int height, Color[] palette, byte[] pixelIndices, TgaEncoding encodingType = TgaEncoding.Indexed, int bitsPerPixel = 8, int paletteDepth = 32) { // set header SetHeaderInfo(width, height, bitsPerPixel, paletteDepth, encodingType); // done if the encoding id is set to none if (encodingType == TgaEncoding.None) { return; } /* * // check if input data is correct * if (_palette.Length != _paletteLength || (width * height * (float)(bitsPerPixel / 8)) != pixelIndices.Length) * { * throw new ArgumentException("Palette or pixel index data was not in the expected format"); * } */ // should probably throw a format exception somewhere as this is pretty insane ;p if (IsIndexed) { if (palette.Length != (1 << bitsPerPixel)) { BitmapHelper.QuantizeBitmap(BitmapHelper.Create(palette, pixelIndices, width, height), 1 << bitsPerPixel, out mPaletteIndices, out mPalette); } else { // set palette and pixel data mPalette = palette; mPaletteIndices = pixelIndices; } } else { mPixels = BitmapHelper.GetColors(BitmapHelper.Create(palette, pixelIndices, width, height)); } }
private static void WriteIndices(BinaryWriter writer, byte[] indices, int width, int height, TgaEncoding type, int bpp) { if (EncodingUsesRleOrCmp(type)) { throw new NotImplementedException(); } else { WriteIndicesData(writer, bpp, width, height, indices); } }
/// <summary> /// Initializes a new instance of the <see cref="TgaFile"/> class from the specified bitmap file path, and encoding parameters to encode the bitmap with. /// </summary> /// <param name="filename">The bitmap file path used for encoding.</param> /// <param name="encodingType">Specifies the pixel data encoding to use.</param> /// <param name="bitsPerPixel">Specifies the amount of bits per pixel. /// 4 and 8 are reserved for indexed encodings, while 16, 24 and 32 are used for non-indexed images.</param> /// <param name="paletteDepth">Specifies the amount of bits per color in the palette. Ignored if the encoding id is of an indexed encoding.</param> public TgaFile(string filename, TgaEncoding encodingType = TgaEncoding.Indexed, int bitsPerPixel = 8, int paletteDepth = 32) : this(new Bitmap(filename), encodingType, bitsPerPixel, paletteDepth) { }