Пример #1
0
 public override void Dispose()
 {
     if (m_memory != null)
     {
         m_memory.Free(Buffer.Length);
     }
     else
     {
         m_parent.Dispose();
     }
 }
Пример #2
0
 public override void Dispose()
 {
     if (m_memory != null)
     {
         m_memory.Free(Image.Width * Image.Height);
     }
     else
     {
         m_parent.Dispose();
     }
 }
Пример #3
0
 public override void Dispose()
 {
     m_memory.Free(Palette.Size * 3);
 }
Пример #4
0
        public static Image Decode(Stream stream, MemoryTracker memory, out Palette o_palette)
        {
            var reader = new BinaryReader(stream);

            // Read the header
            int imageIDLength        = reader.ReadByte();
            int colorMapType         = reader.ReadByte();
            int imageType            = reader.ReadByte();
            int colorMapStart        = reader.ReadUInt16();
            int colorMapLength       = reader.ReadUInt16();
            int colorMapBitsPerPixel = reader.ReadByte();

            reader.ReadUInt16(); // xOffset
            reader.ReadUInt16(); // yOffset
            int width           = reader.ReadUInt16();
            int height          = reader.ReadUInt16();
            int bitsPerPixel    = reader.ReadByte();
            int imageDescriptor = reader.ReadByte();

            if (bitsPerPixel != 8 ||
                width == 0 || height == 0 ||
                colorMapType != 1 ||
                (colorMapStart + colorMapLength) == 0 ||
                (colorMapStart + colorMapLength) > 256 ||
                (colorMapBitsPerPixel != 24 && colorMapBitsPerPixel != 32) ||
                (imageType != 1 && imageType != 9))
            {
                throw new IOException("Unsupported TGA file");
            }

            // Read the ID
            if (imageIDLength > 0)
            {
                reader.ReadBytes(imageIDLength);
            }

            // Read the color map
            int colorMapBytesPerPixel = colorMapBitsPerPixel / 8;
            var colorMap = reader.ReadBytes(colorMapLength * colorMapBytesPerPixel);
            var colors   = new uint[colorMapStart + colorMapLength];

            for (int i = 0; i < colors.Length; ++i)
            {
                if (i < colorMapStart)
                {
                    colors[i] = 0x000000ff;
                }
                else
                {
                    uint b = colorMap[(i - colorMapStart) * colorMapBytesPerPixel];
                    uint g = colorMap[(i - colorMapStart) * colorMapBytesPerPixel + 1];
                    uint r = colorMap[(i - colorMapStart) * colorMapBytesPerPixel + 2];
                    colors[i] = (r << 24) + (g << 16) + (b << 8) + 0xff;
                }
            }
            var palette = new Palette(colors);

            // Decode the image
            long size = width * height;

            if (palette != null)
            {
                size += 3 * palette.Size;
            }
            if (!memory.Alloc(size))
            {
                throw new OutOfMemoryException();
            }
            try
            {
                // Read the pixels
                byte[] buffer;
                bool   rle = (imageType >= 8);
                if (rle)
                {
                    // RLE
                    buffer = new byte[width * height];
                    int pos = 0;
                    while (pos < buffer.Length)
                    {
                        byte b = reader.ReadByte();
                        if (((int)b & 0x80) == 0x80)
                        {
                            // Run-length packet
                            int  count = ((int)b & 0x7f) + 1;
                            byte value = reader.ReadByte();
                            int  limit = Math.Min(pos + count, buffer.Length);
                            while (pos < limit)
                            {
                                buffer[pos++] = value;
                            }
                        }
                        else
                        {
                            // Non-run-length packet
                            int count = ((int)b & 0x7f) + 1;
                            int limit = Math.Min(pos + count, buffer.Length);
                            while (pos < limit)
                            {
                                buffer[pos++] = reader.ReadByte();
                            }
                        }
                    }
                }
                else
                {
                    // Non RLE
                    buffer = reader.ReadBytes(width * height);
                }

                // Create the image
                bool flipY = (imageDescriptor & 0x20) == 0;
                var  image = new Image(width, height);
                if (flipY)
                {
                    for (int y = 0; y < height; ++y)
                    {
                        int flippedY = height - 1 - y;
                        image.Write(buffer, y * width, width, 0, flippedY);
                    }
                }
                else
                {
                    image.Write(buffer, 0, width * height, 0, 0);
                }
                o_palette = palette;
                return(image);
            }
            catch
            {
                memory.Free(size);
                throw;
            }
        }