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)); } }
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; } } } }
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); }