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 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); } }
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; } }
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; }
// 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); _idLength = 0; _colorMapType = isIndexed ? (byte)1 : (byte)0; _dataType = enc; if (isIndexed) { _paletteStartIndex = 0; _paletteLength = (short)(1 << bpp); _paletteDepth = (byte)palDepth; } _xOrigin = 0; _yOrigin = 0; _width = (short)w; _height = (short)h; _bpp = (byte)bpp; _imageDescriptor = 0; }
// encoding type 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 type: {type} is not implemented."); default: throw new ArgumentException($"Data type: {type} is not encoded."); } }
internal void InternalRead(BinaryReader reader) { _idLength = reader.ReadByte(); _colorMapType = reader.ReadByte(); _dataType = (TGAEncoding)reader.ReadByte(); _paletteStartIndex = reader.ReadInt16(); _paletteLength = reader.ReadInt16(); _paletteDepth = reader.ReadByte(); _xOrigin = reader.ReadInt16(); _yOrigin = reader.ReadInt16(); _width = reader.ReadInt16(); _height = reader.ReadInt16(); _bpp = reader.ReadByte(); _imageDescriptor = reader.ReadByte(); // format check if (EncodingUsesRLEOrCmp(_dataType) || _dataType == TGAEncoding.Grayscale) { throw new NotImplementedException($"Data type not supported: {_dataType}"); } else if (_dataType == TGAEncoding.None) { return; } // skip user data reader.Seek(_idLength, SeekOrigin.Current); if (IsIndexed) { // read palette and indices _palette = ReadPalette(reader, _paletteLength, _bpp, _paletteDepth); _paletteIndices = ReadIndices(reader, _dataType, _bpp, _width, _height); } else { // read pixels _pixels = ReadPixels(reader, _dataType, _bpp, _width, _height); } }
/// <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 type 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 type 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 _paletteIndices, out _palette); } else { // set palette and pixel data _palette = palette; _paletteIndices = pixelIndices; } } else { _pixels = BitmapHelper.GetColors(BitmapHelper.Create(palette, pixelIndices, width, height)); } }
/// <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 type 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 type is set to none if (encodingType == TGAEncoding.None) return; // set bitmap data if (IsIndexed) { BitmapHelper.QuantizeBitmap(bitmap, 1 << bitsPerPixel, out _paletteIndices, out _palette); } else { _pixels = BitmapHelper.GetColors(bitmap); } }
/// <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 type 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) { }