コード例 #1
0
        IarImage CombineImage(IarImage overlay, IarArchive iarc)
        {
            using (var input = new BinMemoryStream(overlay.Data))
            {
                var dir        = (List <Entry>)iarc.Dir;
                int base_index = input.ReadInt32();
                if (base_index >= dir.Count)
                {
                    throw new InvalidFormatException("Invalid base image index");
                }
                int diff_y     = input.ReadInt32();
                int diff_count = input.ReadInt32();

                var    overlay_info = overlay.Info;
                int    pixel_size   = overlay_info.BPP / 8;
                var    base_image   = new IarImage(iarc, dir[base_index]);
                byte[] output       = base_image.Data;
                if (overlay_info.Height != base_image.Info.Height || overlay_info.Stride != base_image.Info.Stride)
                {
                    int    src_height = (int)Math.Min(overlay_info.Height, base_image.Info.Height);
                    int    src_stride = Math.Min(overlay_info.Stride, base_image.Info.Stride);
                    byte[] src        = base_image.Data;
                    output = new byte[overlay_info.Height * overlay_info.Stride];
                    int dst_pos = 0;
                    if (base_image.Info.OffsetY < overlay_info.OffsetY)
                    {
                        dst_pos += (-base_image.Info.OffsetY + overlay_info.OffsetY) * overlay_info.Stride;
                    }
                    if (base_image.Info.OffsetX < overlay_info.OffsetX)
                    {
                        dst_pos += (-base_image.Info.OffsetX + overlay_info.OffsetX) * pixel_size;
                    }
                    for (int y = 0; y < src_height; ++y)
                    {
                        Buffer.BlockCopy(src, y * base_image.Info.Stride, output, dst_pos, src_stride);
                        dst_pos += overlay_info.Stride;
                    }
                }
                int dst = diff_y * overlay_info.Stride;
                for (int i = 0; i < diff_count; ++i)
                {
                    int chunk_count = input.ReadUInt16();
                    int x           = 0;
                    for (int j = 0; j < chunk_count; ++j)
                    {
                        int skip_count = pixel_size * input.ReadUInt16();
                        int copy_count = pixel_size * input.ReadUInt16();

                        x += skip_count;
                        input.Read(output, dst + x, copy_count);
                        x += copy_count;
                    }
                    dst += overlay_info.Stride;
                }
                return(new IarImage(overlay_info, output, overlay.Palette));
            }
        }
コード例 #2
0
ファイル: ImageG00.cs プロジェクト: zxc120/GARbro
        void UnpackV2()
        {
            Format = PixelFormats.Bgra32;
            int tile_count = m_input.ReadInt32();
            var tiles      = new List <Tile> (tile_count);

            for (int i = 0; i < tile_count; ++i)
            {
                var tile = new Tile();
                tile.X = m_input.ReadInt32();
                tile.Y = m_input.ReadInt32();
                tiles.Add(tile);
                m_input.Seek(0x10, SeekOrigin.Current);
            }
            using (var input = new BinMemoryStream(LzDecompress(m_input, 2, 1)))
            {
                if (input.ReadInt32() != tile_count)
                {
                    throw new InvalidFormatException();
                }
                int dst_stride = m_width * 4;
                m_output = new byte[m_height * dst_stride];
                for (int i = 0; i < tile_count; ++i)
                {
                    tiles[i].Offset = input.ReadUInt32();
                    tiles[i].Length = input.ReadInt32();
                }
                var tile = tiles.First(t => t.Length != 0);

                input.Position = tile.Offset;
                int tile_type = input.ReadUInt16();
                int count     = input.ReadUInt16();
                if (tile_type != 1)
                {
                    throw new InvalidFormatException();
                }
                input.Seek(0x70, SeekOrigin.Current);
                for (int i = 0; i < count; ++i)
                {
                    int tile_x = input.ReadUInt16();
                    int tile_y = input.ReadUInt16();
                    input.ReadInt16();
                    int tile_width  = input.ReadUInt16();
                    int tile_height = input.ReadUInt16();
                    input.Seek(0x52, SeekOrigin.Current);

                    tile_x += tile.X;
                    tile_y += tile.Y;
                    if (tile_x + tile_width > m_width || tile_y + tile_height > m_height)
                    {
                        throw new InvalidFormatException();
                    }
                    int dst         = tile_y * dst_stride + tile_x * 4;
                    int tile_stride = tile_width * 4;
                    for (int row = 0; row < tile_height; ++row)
                    {
                        input.Read(m_output, dst, tile_stride);
                        dst += dst_stride;
                    }
                }
            }
        }
コード例 #3
0
        public byte[] Unpack()
        {
            m_input.Position = 0x20;
            if (m_info.HasPalette)
            {
                Palette = ImageFormat.ReadPalette(m_input.AsStream, 0x100, PaletteFormat.Bgr);
            }

            var buffer = ReadChunks();

            using (var input = new BinMemoryStream(buffer))
            {
                int g_pos         = m_info.iWidth;
                int b_pos         = m_info.iWidth * 2;
                int a_pos         = m_info.iWidth * 3;
                var scanline      = new byte[m_info.ScanLineSize * 2];
                var unpack_buffer = new byte[scanline.Length];
                int dst           = 0;
                for (int y = 0; y < m_info.iHeight; ++y)
                {
                    int  packed_size = Binary.BigEndian(input.ReadInt24() << 8);
                    byte flags       = input.ReadUInt8();
                    if (packed_size > scanline.Length)
                    {
                        break;
                    }
                    input.Read(scanline, 0, packed_size);
                    if ((flags & 4) != 0) // LZSS compression
                    {
                        packed_size = PckOpener.LzssUnpack(scanline, packed_size, unpack_buffer);
                        var swap = scanline;
                        scanline      = unpack_buffer;
                        unpack_buffer = swap;
                    }
                    if ((flags & 2) != 0) // RLE compression
                    {
                        packed_size = RleUnpack(scanline, packed_size, unpack_buffer);
                        var swap = scanline;
                        scanline      = unpack_buffer;
                        unpack_buffer = swap;
                    }
                    if ((flags & 1) != 0)
                    {
                        RestoreScanline(scanline, packed_size);
                    }
                    switch (m_info.BPP)
                    {
                    case 24:
                    {
                        int src_r = 0;
                        int src_g = g_pos;
                        int src_b = b_pos;
                        int src_a = a_pos;
                        for (int x = 0; x < m_info.iWidth; ++x)
                        {
                            m_output[dst++] = scanline[src_b++];
                            m_output[dst++] = scanline[src_g++];
                            m_output[dst++] = scanline[src_r++];
                            if (m_info.HasAlpha)
                            {
                                m_output[dst++] = scanline[src_a++];
                            }
                        }
                        break;
                    }

                    default:
                        throw new NotImplementedException("Not supported LAG color depth.");
                    }
                }
            }
            return(m_output);
        }