public IarImage(IarArchive iarc, Entry entry) { int flags = iarc.File.View.ReadUInt16(entry.Offset); int bpp; switch (flags & 0x3E) { case 0x02: bpp = 8; break; case 0x1C: bpp = 24; break; case 0x3C: bpp = 32; break; default: throw new NotSupportedException("Not supported IAR image format"); } var offset = entry.Offset; m_info = new IarImageInfo { Flags = flags, BPP = bpp, Compressed = iarc.File.View.ReadByte(offset + 3) != 0, Width = iarc.File.View.ReadUInt32(offset + 0x20), Height = iarc.File.View.ReadUInt32(offset + 0x24), Stride = iarc.File.View.ReadInt32(offset + 0x28), OffsetX = iarc.File.View.ReadInt32(offset + 0x18), OffsetY = iarc.File.View.ReadInt32(offset + 0x1C), UnpackedSize = iarc.File.View.ReadInt32(offset + 8), PaletteSize = iarc.File.View.ReadUInt32(offset + 0xC), PackedSize = iarc.File.View.ReadInt32(offset + 0x10), }; uint header_size = 1 == iarc.Version ? 0x30u : iarc.Version < 4 ? 0x40u : 0x48u; offset += header_size; uint input_size = entry.Size - header_size; if (m_info.PaletteSize > 0) { m_palette = new byte[m_info.PaletteSize]; iarc.File.View.Read(offset, m_palette, 0, m_info.PaletteSize); offset += m_info.PaletteSize; input_size -= m_info.PaletteSize; } m_output = new byte[m_info.UnpackedSize]; using (var input = iarc.File.CreateStream(offset, input_size)) { if (m_info.Compressed) { using (var reader = new IarDecompressor(input)) reader.Unpack(m_output); } else { input.Read(m_output, 0, m_output.Length); } } }
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)); } }
IarImage CombineLayers(IarImage layers, IarArchive iarc) { layers.Info.Stride = (int)layers.Info.Width * 4; layers.Info.BPP = 32; var pixels = new byte[layers.Info.Stride * (int)layers.Info.Height]; var output = new IarImage(layers.Info, pixels); using (var mem = new MemoryStream(layers.Data)) using (var input = new BinaryReader(mem)) { int offset_x = 0, offset_y = 0; var dir = (List <Entry>)iarc.Dir; while (input.BaseStream.Position < input.BaseStream.Length) { int cmd = input.ReadByte(); switch (cmd) { case 0x21: offset_x += input.ReadInt16(); offset_y += input.ReadInt16(); break; case 0x00: case 0x20: { int index = input.ReadInt32(); if (index < 0 || index >= dir.Count) { throw new InvalidFormatException("Invalid image layer index"); } var layer = new IarImage(iarc, dir[index]); layer.Info.OffsetX -= offset_x; layer.Info.OffsetY -= offset_y; if (0x20 == cmd) { output.ApplyMask(layer); } else { output.Blend(layer); } } break; default: Trace.WriteLine(string.Format("Unknown layer type 0x{0:X2}", cmd), "IAR"); break; } } return(output); } }
public IarImage(IarArchive iarc, Entry entry) { int flags = iarc.File.View.ReadUInt16 (entry.Offset); int bpp; switch (flags & 0x3E) { case 0x02: bpp = 8; break; case 0x1C: bpp = 24; break; case 0x3C: bpp = 32; break; default: throw new NotSupportedException ("Not supported IAR image format"); } var offset = entry.Offset; m_info = new IarImageInfo { Flags = flags, BPP = bpp, Compressed = iarc.File.View.ReadByte (offset+3) != 0, Width = iarc.File.View.ReadUInt32 (offset+0x20), Height = iarc.File.View.ReadUInt32 (offset+0x24), Stride = iarc.File.View.ReadInt32 (offset+0x28), OffsetX = iarc.File.View.ReadInt32 (offset+0x18), OffsetY = iarc.File.View.ReadInt32 (offset+0x1C), UnpackedSize = iarc.File.View.ReadInt32 (offset+8), PaletteSize = iarc.File.View.ReadUInt32 (offset+0xC), PackedSize = iarc.File.View.ReadInt32 (offset+0x10), }; uint header_size = 1 == iarc.Version ? 0x30u : iarc.Version < 4 ? 0x40u : 0x48u; offset += header_size; uint input_size = entry.Size - header_size; if (m_info.PaletteSize > 0) { m_palette = new byte[m_info.PaletteSize]; iarc.File.View.Read (offset, m_palette, 0, m_info.PaletteSize); offset += m_info.PaletteSize; input_size -= m_info.PaletteSize; } m_output = new byte[m_info.UnpackedSize]; using (var input = iarc.File.CreateStream (offset, input_size)) { if (m_info.Compressed) { using (var reader = new IarDecompressor (input)) reader.Unpack (m_output); } else input.Read (m_output, 0, m_output.Length); } }
IarImage CombineLayers(IarImage layers, IarArchive iarc) { layers.Info.Stride = (int)layers.Info.Width * 4; layers.Info.BPP = 32; var pixels = new byte[layers.Info.Stride * (int)layers.Info.Height]; var output = new IarImage (layers.Info, pixels); using (var mem = new MemoryStream (layers.Data)) using (var input = new BinaryReader (mem)) { int offset_x = 0, offset_y = 0; var dir = (List<Entry>)iarc.Dir; while (input.BaseStream.Position < input.BaseStream.Length) { int cmd = input.ReadByte(); switch (cmd) { case 0x21: offset_x += input.ReadInt16(); offset_y += input.ReadInt16(); break; case 0x00: case 0x20: { int index = input.ReadInt32(); if (index < 0 || index >= dir.Count) throw new InvalidFormatException ("Invalid image layer index"); var layer = new IarImage (iarc, dir[index]); layer.Info.OffsetX -= offset_x; layer.Info.OffsetY -= offset_y; if (0x20 == cmd) output.ApplyMask (layer); else output.Blend (layer); } break; default: Trace.WriteLine (string.Format ("Unknown layer type 0x{0:X2}", cmd), "IAR"); break; } } return output; } }
IarImage CombineImage(IarImage overlay, IarArchive iarc) { using (var mem = new MemoryStream (overlay.Data)) using (var input = new BinaryReader (mem)) { 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; 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; 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 pixel_size = overlay_info.BPP / 8; 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); } }