Ejemplo n.º 1
0
        private static byte[] ReadColor(int pixelDepth, BinaryReader reader)
        {
            switch (pixelDepth)
            {
            case 16:
            {
                var color16 = reader.ReadInt16();

                return(Tga.FlipRgb(
                           new[]
                    {
                        (byte)(((color16 >> 0) & 0x1f) * 0xff / 0x1f), (byte)(((color16 >> 5) & 0x1f) * 0xff / 0x1f),
                        (byte)(((color16 >> 10) & 0x1f) * 0xff / 0x1f),

                        // It seems the alpha value is not used here...
                        //(byte) ((color16 >> 15) * 0xff)
                        (byte)0xff
                    }
                           ));
            }

            case 24:
                return(Tga.FlipRgb(new[] { reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), (byte)0xff }));

            case 32:
                return(Tga.FlipRgb(new[] { reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte() }));

            default:
                return(new byte[4]);
            }
        }
Ejemplo n.º 2
0
        public Tga(Stream stream)
        {
            using var reader = new BinaryReader(stream);

            if (reader.ReadByte() != 0x00)
            {
                throw new Exception("Unsupported IDLength");
            }

            var colorMapType = reader.ReadByte();

            if (colorMapType != 0x00 && colorMapType != 0x01)
            {
                throw new Exception("Unsupported ColorMapType");
            }

            var imageType = reader.ReadByte();

            if (imageType != 0x00 && imageType != 0x01 && imageType != 0x02 && imageType != 0x0a)
            {
                throw new Exception("Unsupported ImageType");
            }

            var firstIndexEntry   = 0;
            var colorMapLength    = 0;
            var colorMapEntrySize = 0;

            // This is a custom tga format, as this imageType means originally "no image".
            if (imageType == 0x00)
            {
                reader.ReadBytes(3);
            }
            else
            {
                firstIndexEntry   = reader.ReadUInt16();
                colorMapLength    = reader.ReadUInt16();
                colorMapEntrySize = reader.ReadByte();

                if (colorMapType == 0x01)
                {
                    if (firstIndexEntry + colorMapLength > 256 || colorMapLength == 0)
                    {
                        throw new Exception("Unsupported ColorMap");
                    }

                    if (colorMapEntrySize != 16 && colorMapEntrySize != 24 && colorMapEntrySize != 32)
                    {
                        throw new Exception("Unsupported ColorMap");
                    }
                }
                else if (firstIndexEntry != 0 || colorMapLength != 0 || colorMapEntrySize != 0)
                {
                    throw new Exception("Unsupported ColorMap");
                }

                if (reader.ReadUInt16() != 0x0000)
                {
                    throw new Exception("Unsupported XOrigin");
                }

                if (reader.ReadUInt16() != 0x0000)
                {
                    throw new Exception("Unsupported YOrigin");
                }
            }

            this.Width  = reader.ReadUInt16();
            this.Height = reader.ReadUInt16();

            var pixelDepth = reader.ReadByte();

            if (colorMapType == 0x01)
            {
                if (pixelDepth != 8)
                {
                    throw new Exception("Unsupported PixelDepth");
                }
            }
            else if (pixelDepth != 16 && pixelDepth != 24 && pixelDepth != 32)
            {
                throw new Exception("Unsupported PixelDepth");
            }

            // TODO implement alphaBits
            var alphaBits      = 0;
            var flipHorizontal = false;
            var flipVertical   = false;

            if (imageType != 0x00)
            {
                var imageDescriptor = reader.ReadByte();
                alphaBits      = imageDescriptor & 0x0f;
                flipHorizontal = (imageDescriptor & 0x10) != 0x00;
                flipVertical   = (imageDescriptor & 0x20) != 0x00;

                if (imageDescriptor >> 6 != 0x00)
                {
                    throw new Exception("Unsupported ImageDescriptor");
                }

                // TODO what does it mean when alphaBits are 8?
                if (pixelDepth == 8 && alphaBits != 0 && alphaBits != 8)
                {
                    throw new Exception("Unsupported AlphaBits");
                }

                // TODO what does it mean when alphaBits are 0?
                if (pixelDepth == 16 && alphaBits != 1 && alphaBits != 0)
                {
                    throw new Exception("Unsupported AlphaBits");
                }

                if (pixelDepth == 24 && alphaBits != 0)
                {
                    throw new Exception("Unsupported AlphaBits");
                }

                // TODO what does it mean when alphaBits are 0?
                if (pixelDepth == 32 && alphaBits != 8 && alphaBits != 0)
                {
                    throw new Exception("Unsupported AlphaBits");
                }
            }

            this.Pixels = new byte[this.Width * this.Height * 4];

            var colorMap = new byte[colorMapLength * 4];

            if (colorMapType == 0x01)
            {
                for (var i = 0; i < colorMapLength; i++)
                {
                    Array.Copy(Tga.ReadColor(colorMapEntrySize, reader), 0, colorMap, i * 4, 4);
                }
            }

            var pixelReader = reader;

            if (imageType == 0x0a)
            {
                var bytesPerPixel = pixelDepth / 8;
                var uncompressed  = new byte[this.Width * this.Height * bytesPerPixel];

                for (var i = 0; i < uncompressed.Length;)
                {
                    var info  = reader.ReadByte();
                    var mode  = info >> 7;
                    var count = (info & 0x7f) + 1;

                    if (mode == 1)
                    {
                        var pixel = Tga.ReadColor(pixelDepth, reader);

                        for (var j = 0; j < count; j++, i += bytesPerPixel)
                        {
                            Array.Copy(pixel, 0, uncompressed, i, bytesPerPixel);
                        }
                    }
                    else
                    {
                        var numBytes = bytesPerPixel * count;
                        Array.Copy(reader.ReadBytes(numBytes), 0, uncompressed, i, numBytes);
                        i += numBytes;
                    }
                }

                pixelReader = new BinaryReader(new MemoryStream(uncompressed));
            }

            for (var y = 0; y < this.Height; y++)
            {
                for (var x = 0; x < this.Width; x++)
                {
                    var rgba = new byte[4];

                    if (colorMapType == 0x01)
                    {
                        Array.Copy(colorMap, (pixelReader.ReadByte() - firstIndexEntry) * 4, rgba, 0, 4);
                    }
                    else
                    {
                        rgba = Tga.ReadColor(pixelDepth, pixelReader);
                    }

                    if (rgba[0] == 0xff && rgba[1] == 0x00 && rgba[2] == 0xff && rgba[3] == 0xff)
                    {
                        continue;
                    }

                    Array.Copy(rgba, 0, this.Pixels, ((flipVertical ? this.Height - 1 - y : y) * this.Width + (flipHorizontal ? this.Width - 1 - x : x)) * 4, 4);
                }
            }
        }