public void UnpackAlpha(int offset) { using (var input = new BinMemoryStream(this.Input, offset, Input.Length - offset)) { if (1 != input.ReadInt32()) { return; } int dst = 3; int ctl = 1 << 1; while (dst < Output.Length) { ctl >>= 1; if (1 == ctl) { ctl = input.ReadUInt8() | 0x100; } if (0 != (ctl & 1)) { int v = input.ReadUInt16(); int x = v & 0x3F; if (x > 0x1F) { x |= -0x40; } int y = (v >> 6) & 7; if (y != 0) { y |= -8; } int count = ((v >> 9) & 0x7F) + 3; int src = dst + (x + y * Width) * 4; if (src < 0 || src >= dst) { return; } for (int i = 0; i < count; ++i) { Output[dst] = Output[src]; src += 4; dst += 4; } } else { Output[dst] = input.ReadUInt8(); dst += 4; } } HasAlpha = true; } }
void LoadBlob(AssetReader reader) { int count = reader.ReadInt32(); int buffer_bytes = reader.ReadInt32(); var node_data = reader.ReadBytes(24 * count); m_data = reader.ReadBytes(buffer_bytes); var parents = new Stack <TypeTree>(); parents.Push(this); using (var buf = new BinMemoryStream(node_data)) { for (int i = 0; i < count; ++i) { int version = buf.ReadInt16(); int depth = buf.ReadUInt8(); TypeTree current; if (0 == depth) { current = this; } else { while (parents.Count > depth) { parents.Pop(); } current = new TypeTree(m_format); parents.Peek().Children.Add(current); parents.Push(current); } current.Version = version; current.IsArray = buf.ReadUInt8() != 0; current.Type = GetString(buf.ReadInt32()); current.Name = GetString(buf.ReadInt32()); current.Size = buf.ReadInt32(); current.Index = buf.ReadUInt32(); current.Flags = buf.ReadInt32(); } } }
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 input = new BinMemoryStream(layers.Data)) { int offset_x = 0, offset_y = 0; var dir = (List <Entry>)iarc.Dir; while (input.Position < input.Length) { int cmd = input.ReadUInt8(); 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 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); }