Пример #1
0
        //=========== READING ============
        #region Reading

        /** <summary> Reads the graphics data. </summary> */
        public void Read(BinaryReader reader, ImageDirectory directory, Palette colorPalette = null)
        {
            if (colorPalette == null)
            {
                colorPalette = Palette.DefaultPalette;
            }
            long startPosition = reader.BaseStream.Position;

            for (int i = 0; i < directory.Count; i++)
            {
                ImageEntry entry = directory.Entries[i];
                if (entry.Flags == ImageFlags.DirectBitmap)
                {
                    Bitmap       image        = new Bitmap(entry.Width, entry.Height);
                    PaletteImage paletteImage = new PaletteImage(entry.Width, entry.Height);
                    reader.BaseStream.Position = startPosition + entry.StartAddress;

                    // Read each row
                    for (int y = 0; y < entry.Height; y++)
                    {
                        for (int x = 0; x < entry.Width; x++)
                        {
                            byte b = reader.ReadByte();
                            image.SetPixel(x, y, colorPalette.Colors[b]);
                            paletteImage.Pixels[x, y] = b;
                        }
                    }

                    this.Images.Add(image);
                    this.PaletteImages.Add(paletteImage);
                }
                else if (entry.Flags == ImageFlags.CompactedBitmap)
                {
                    Bitmap       image        = new Bitmap(entry.Width, entry.Height);
                    PaletteImage paletteImage = new PaletteImage(entry.Width, entry.Height);
                    uint[]       rowOffsets   = new uint[entry.Height];
                    reader.BaseStream.Position = startPosition + entry.StartAddress;

                    // Read the row offsets
                    for (int j = 0; j < entry.Height; j++)
                    {
                        rowOffsets[j] = reader.ReadUInt16();
                    }

                    // Read the scan lines in each row
                    for (int j = 0; j < entry.Height; j++)
                    {
                        reader.BaseStream.Position = startPosition + entry.StartAddress + rowOffsets[j];
                        byte b1 = 0;
                        byte b2 = 0;

                        // A MSB of 1 means the last scan line in a row
                        while ((b1 & 0x80) == 0)
                        {
                            // Read the number of bytes of data
                            b1 = reader.ReadByte();
                            // Read the offset from the left edge of the image
                            b2 = reader.ReadByte();
                            for (int k = 0; k < (int)(b1 & 0x7F); k++)
                            {
                                byte b3 = reader.ReadByte();
                                try {
                                    image.SetPixel((int)b2 + k, j, colorPalette.Colors[b3]);
                                    paletteImage.Pixels[(int)b2 + k, j] = b3;
                                }
                                catch (Exception) {
                                    Console.WriteLine("Help");
                                }
                            }
                        }
                    }

                    this.Images.Add(image);
                    this.PaletteImages.Add(paletteImage);
                }
                else if (entry.Flags == ImageFlags.PaletteEntries)
                {
                    Palette palette = new Palette(entry.Width);
                    reader.BaseStream.Position = startPosition + entry.StartAddress;

                    // Read each color
                    for (int j = 0; j < entry.Width; j++)
                    {
                        // Yes the colors are in the order blue, green, red
                        byte blue  = reader.ReadByte();
                        byte green = reader.ReadByte();
                        byte red   = reader.ReadByte();

                        palette.Colors[j] = Color.FromArgb(red, green, blue);
                    }
                    this.Palettes.Add(palette);
                }
            }
        }
Пример #2
0
        /** <summary> Writes the graphics data. </summary> */
        public void Write(BinaryWriter writer, ImageDirectory directory)
        {
            long startPosition = writer.BaseStream.Position;

            for (int i = 0; i < directory.Count; i++)
            {
                ImageEntry entry = directory.Entries[i];
                entry.StartAddress = (uint)(writer.BaseStream.Position - startPosition);

                if (entry.Flags == ImageFlags.DirectBitmap)
                {
                    PaletteImage paletteImage = this.PaletteImages[i];            // new PaletteImage(entry.Width, entry.Height);

                    // Write each row
                    for (int y = 0; y < entry.Height; y++)
                    {
                        // Write each pixel in the row
                        for (int x = 0; x < entry.Width; x++)
                        {
                            writer.Write(paletteImage.Pixels[x, y]);
                        }
                    }
                }
                else if (entry.Flags == ImageFlags.CompactedBitmap)
                {
                    PaletteImage paletteImage = this.PaletteImages[i];            // new PaletteImage(entry.Width, entry.Height);

                    List <ScanLine> scanLines  = new List <ScanLine>();
                    ushort[]        rowOffsets = new ushort[entry.Height];
                    ushort          rowOffset  = (ushort)(entry.Height * 2);

                    // Write the scan lines in every row and figure out the scan line row offsets
                    for (int y = 0; y < (int)entry.Height; y++)
                    {
                        rowOffsets[y] = rowOffset;

                        ScanLine scanLine = new ScanLine();
                        scanLine.Row = (short)y;

                        // Continue until the next row
                        while ((scanLine.Count & 0x80) == 0x00)
                        {
                            // Reset the scan line count
                            scanLine.Count = 0;

                            // Find each scan line and then check if there's another one in the row
                            bool finishedScanLine = false;
                            bool lastScanLine     = true;
                            for (int x = 0; x + (int)scanLine.Offset < (int)entry.Width; x++)
                            {
                                if (!finishedScanLine)
                                {
                                    if (scanLine.Count == 0)
                                    {
                                        // If the scan line hasn't started yet, increment the offset
                                        if (paletteImage.Pixels[x + scanLine.Offset, y] == 0x00)
                                        {
                                            scanLine.Offset++;
                                            x--;
                                        }
                                        else
                                        {
                                            scanLine.Count = 1;
                                        }
                                    }
                                    else if (paletteImage.Pixels[x + scanLine.Offset, y] == 0x00 || x == 0x7F)
                                    {
                                        // If the next pixel is transparent or the scan line is as big as possible, finish the line
                                        finishedScanLine = true;
                                    }
                                    else
                                    {
                                        // Increment the scan line byte count
                                        scanLine.Count++;
                                    }
                                }
                                else if (paletteImage.Pixels[x + scanLine.Offset, y] != 0x00)
                                {
                                    // There is another scan line after this
                                    lastScanLine = false;
                                    break;
                                }
                            }
                            // Set the end flag if the scan line is the last in the row
                            if (lastScanLine)
                            {
                                scanLine.Count |= 0x80;
                            }
                            // If the row has all transparent pixels, set the offset to 0
                            if (scanLine.Count == 0)
                            {
                                scanLine.Offset = 0;
                                scanLine.Count  = 0;
                            }

                            rowOffset += (ushort)(2 + (scanLine.Count & 0x7F));
                            scanLines.Add(scanLine);

                            // Increment the scan line count
                            if (!lastScanLine)
                            {
                                scanLine.Offset += (byte)(scanLine.Count & 0x7F);
                            }
                        }
                    }

                    // Write the row offsets
                    for (int j = 0; j < entry.Height; j++)
                    {
                        writer.Write(rowOffsets[j]);
                    }

                    // Write the scan lines
                    for (int j = 0; j < scanLines.Count; j++)
                    {
                        writer.Write(scanLines[j].Count);
                        writer.Write(scanLines[j].Offset);
                        for (int k = 0; k < (int)(scanLines[j].Count & 0x7F); k++)
                        {
                            try {
                                writer.Write(paletteImage.Pixels[k + scanLines[j].Offset, scanLines[j].Row]);
                            }
                            catch (Exception) {
                                Console.WriteLine("Help");
                            }
                        }
                    }
                }
                else if (entry.Flags == ImageFlags.PaletteEntries)
                {
                    Palette palette = new Palette(entry.Width);

                    // Write each color
                    for (int j = 0; j < entry.Width; j++)
                    {
                        // Yes the colors are in the order blue, green, red
                        writer.Write(palette.Colors[j].B);
                        writer.Write(palette.Colors[j].G);
                        writer.Write(palette.Colors[j].R);
                    }
                }
            }
        }