/// <summary>
        /// Reads image data.
        /// </summary>
        private bool ReadImageData()
        {
            // Exit if this image already read
            if (ImgRecord.Data != null)
            {
                return(true);
            }

            // Setup frame to hold extracted image
            ImgRecord.Width  = Header.Width;
            ImgRecord.Height = Header.Height;
            ImgRecord.Stride = Header.Width;
            ImgRecord.Format = DFBitmap.Formats.Indexed;
            ImgRecord.Data   = new byte[Header.Width * Header.Height];

            // Create reader
            BinaryReader Reader = ManagedFile.GetReader(ImageDataPosition);

            // Read image data
            ReadImage(ref Reader);

            // Read palette data
            ReadPalette(ref Reader);

            return(true);
        }
 /// <summary>
 /// Read palette for specified record.
 /// </summary>
 /// <param name="Index">Index of palette.</param>
 private void ReadPalette(int Index)
 {
     // Read palette data if not already stored
     if (null == Palettes[Index])
     {
         BinaryReader Reader = ManagedFile.GetReader(PaletteDataPosition + (776 * Index) + 8);
         Palettes[Index] = new DFPalette();
         Palettes[Index].Read(ref Reader);
     }
 }
        /// <summary>
        /// Reads image data.
        /// </summary>
        /// <param name="Index">Index of image.</param>
        private bool ReadImageData(int Index)
        {
            // Read image if not already stored
            if (null == Bitmaps[Index].Data)
            {
                BinaryReader Reader = ManagedFile.GetReader(ImageDataPosition + (FrameDataLength * Index));
                Bitmaps[Index].Width  = FrameWidth;
                Bitmaps[Index].Height = FrameHeight;
                Bitmaps[Index].Stride = FrameWidth;
                Bitmaps[Index].Format = DFBitmap.Formats.Indexed;
                Bitmaps[Index].Data   = Reader.ReadBytes(FrameDataLength);
            }

            return(true);
        }
        /// <summary>
        /// Read file.
        /// </summary>
        /// <returns>True if succeeded, otherwise false.</returns>
        private bool Read()
        {
            try
            {
                // Step through file
                BinaryReader reader = ManagedFile.GetReader();
                ReadRecords(ref reader);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return(false);
            }

            return(true);
        }
        /// <summary>
        /// Read uncompressed record.
        /// </summary>
        /// <param name="Record">Record index.</param>
        /// <param name="Frame">Frame index.</param>
        /// <returns>True if succeeded, otherwise false.</returns>
        private bool ReadImage(int Record, int Frame)
        {
            // Setup frame to hold extracted image
            Records[Record].Frames[Frame].Width  = Records[Record].Header.Width;
            Records[Record].Frames[Frame].Height = Records[Record].Header.Height;
            Records[Record].Frames[Frame].Stride = Records[Record].Header.Width;
            Records[Record].Frames[Frame].Format = DFBitmap.Formats.Indexed;
            Records[Record].Frames[Frame].Data   = new byte[Records[Record].Header.PixelDataLength];

            // Read image bytes
            long         position = Records[Record].Header.DataPosition;
            BinaryReader reader   = ManagedFile.GetReader(position);
            BinaryWriter writer   = new BinaryWriter(new MemoryStream(Records[Record].Frames[Frame].Data));

            writer.Write(reader.ReadBytes(Records[Record].Header.PixelDataLength));

            return(true);
        }
        /// <summary>
        /// Read a RLE record.
        /// </summary>
        /// <param name="Record">Record index.</param>
        /// <param name="Frame">Frame index.</param>
        /// <returns>True if succeeded, otherwise false.</returns>
        private bool ReadRleImage(int Record, int Frame)
        {
            // Setup frame to hold extracted image
            int length = Records[Record].Header.Width * Records[Record].Header.Height;

            Records[Record].Frames[Frame].Width  = Records[Record].Header.Width;
            Records[Record].Frames[Frame].Height = Records[Record].Header.Height;
            Records[Record].Frames[Frame].Stride = Records[Record].Header.Width;
            Records[Record].Frames[Frame].Format = DFBitmap.Formats.Indexed;
            Records[Record].Frames[Frame].Data   = new byte[length];

            // Extract image data from RLE
            long         position = Records[Record].Header.DataPosition;
            BinaryReader reader   = ManagedFile.GetReader(position);
            BinaryWriter writer   = new BinaryWriter(new MemoryStream(Records[Record].Frames[Frame].Data));

            ReadRleData(ref reader, length, ref writer);

            return(true);
        }
        /// <summary>
        /// Read a RecordRle record.
        /// </summary>
        /// <param name="Record">Record index.</param>
        /// <param name="Frame">Frame index.</param>
        /// <returns>True if succeeded, otherwise false.</returns>
        private bool ReadRle(int Record, int Frame)
        {
            // Create buffer to hold extracted image
            Records[Record].Frames[Frame].Width  = Records[Record].Width;
            Records[Record].Frames[Frame].Height = Records[Record].Height;
            Records[Record].Frames[Frame].Stride = Records[Record].Width;
            Records[Record].Frames[Frame].Format = DFBitmap.Formats.Indexed;
            Records[Record].Frames[Frame].Data   = new byte[Records[Record].Width * Records[Record].Height];

            // Find offset to special row headers for this frame
            long position = Records[Record].Position + Records[Record].DataOffset;

            position += (Records[Record].Height * Frame) * 4;
            BinaryReader Reader = ManagedFile.GetReader(position);

            // Read special row headers for this frame
            SpecialRowHeader[] SpecialRowHeaders = new SpecialRowHeader[Records[Record].Height];
            for (int i = 0; i < Records[Record].Height; i++)
            {
                SpecialRowHeaders[i].RowOffset   = Reader.ReadInt16();
                SpecialRowHeaders[i].RowEncoding = (RowEncoding)Reader.ReadUInt16();
            }

            // Create row memory writer
            BinaryWriter writer = new BinaryWriter(new MemoryStream(Records[Record].Frames[Frame].Data));

            // Extract all rows of image
            foreach (SpecialRowHeader header in SpecialRowHeaders)
            {
                // Get offset to row relative to record data offset
                position = Records[Record].Position + header.RowOffset;
                Reader.BaseStream.Position = position;

                // Handle row data based on compression
                if (RowEncoding.IsRleEncoded == header.RowEncoding)
                {
                    // Extract RLE row
                    byte pixel    = 0;
                    int  probe    = 0;
                    int  rowPos   = 0;
                    int  rowWidth = Reader.ReadUInt16();
                    do
                    {
                        probe = Reader.ReadInt16();
                        if (probe < 0)
                        {
                            probe = -probe;
                            pixel = Reader.ReadByte();
                            for (int i = 0; i < probe; i++)
                            {
                                writer.Write(pixel);
                                rowPos++;
                            }
                        }
                        else if (0 < probe)
                        {
                            writer.Write(Reader.ReadBytes(probe));
                            rowPos += probe;
                        }
                    } while (rowPos < rowWidth);
                }
                else
                {
                    // Just copy bytes
                    writer.Write(Reader.ReadBytes(Records[Record].Width));
                }
            }

            return(true);
        }
        /// <summary>
        /// Read uncompressed record.
        /// </summary>
        /// <param name="Record">Record index.</param>
        /// <param name="Frame">Frame index.</param>
        /// <returns>True if succeeded, otherwise false.</returns>
        private bool ReadImage(int Record, int Frame)
        {
            // Create buffer to hold extracted image
            Records[Record].Frames[Frame].Width  = Records[Record].Width;
            Records[Record].Frames[Frame].Height = Records[Record].Height;
            Records[Record].Frames[Frame].Stride = Records[Record].Width;
            Records[Record].Frames[Frame].Format = DFBitmap.Formats.Indexed;
            Records[Record].Frames[Frame].Data   = new byte[Records[Record].Width * Records[Record].Height];

            if (Records[Record].FrameCount == 1)
            {
                // Extract image bytes
                long         position = Records[Record].Position + Records[Record].DataOffset;
                BinaryReader reader   = ManagedFile.GetReader(position);
                BinaryWriter writer   = new BinaryWriter(new MemoryStream(Records[Record].Frames[Frame].Data));
                for (int y = 0; y < Records[Record].Height; y++)
                {
                    writer.Write(reader.ReadBytes(Records[Record].Width));
                    reader.BaseStream.Position += (256 - Records[Record].Width);
                }
            }
            else if (Records[Record].FrameCount > 1)
            {
                // Get frame offset list
                Int32[]      offsets  = new Int32[Records[Record].FrameCount];
                long         position = Records[Record].Position + Records[Record].DataOffset;
                BinaryReader reader   = ManagedFile.GetReader(position);
                for (int offset = 0; offset < Records[Record].FrameCount; offset++)
                {
                    offsets[offset] = reader.ReadInt32();
                }

                // Offset to desired frame
                reader.BaseStream.Position = position + offsets[Frame];
                int cx = reader.ReadInt16();
                int cy = reader.ReadInt16();

                // Extract image bytes
                BinaryWriter writer = new BinaryWriter(new MemoryStream(Records[Record].Frames[Frame].Data));
                for (int y = 0; y < cy; y++)
                {
                    int x = 0;
                    while (x < cx)
                    {
                        // Write transparant bytes
                        byte pixel = reader.ReadByte();
                        int  run   = x + pixel;
                        for (; x < run; x++)
                        {
                            writer.Write((byte)0);
                        }

                        // Write image bytes
                        pixel = reader.ReadByte();
                        run   = x + pixel;
                        for (; x < run; x++)
                        {
                            pixel = reader.ReadByte();
                            writer.Write(pixel);
                        }
                    }
                }
            }
            else
            {
                // No frames
                return(false);
            }

            return(true);
        }