diff --git a/ArcFormats/Pajamas/ImageEPA.cs b/ArcFormats/Pajamas/ImageEPA.cs index 2d40c496..e56c1374 100644 --- a/ArcFormats/Pajamas/ImageEPA.cs +++ b/ArcFormats/Pajamas/ImageEPA.cs @@ -82,26 +82,26 @@ namespace GameRes.Formats.Pajamas public override ImageData Read (IBinaryStream file, ImageMetaData info) { - var meta = (EpaMetaData)info; - file.Position = 2 == meta.Mode ? 0x18 : 0x10; - var reader = new Reader (file.AsStream, meta); + var reader = new Reader (file, (EpaMetaData)info); reader.Unpack(); - return ImageData.Create (meta, reader.Format, reader.Palette, reader.Data); + return ImageData.Create (info, reader.Format, reader.Palette, reader.Data); } internal class Reader { - private Stream m_input; + private IBinaryStream m_input; + private int m_start_pos; private int m_width; private int m_height; private int m_pixel_size; private byte[] m_output; + private bool m_has_alpha; public PixelFormat Format { get; private set; } public BitmapPalette Palette { get; private set; } public byte[] Data { get { return m_output; } } - public Reader (Stream stream, EpaMetaData info) + public Reader (IBinaryStream stream, EpaMetaData info) { m_input = stream; switch (info.ColorType) @@ -110,70 +110,55 @@ namespace GameRes.Formats.Pajamas case 1: m_pixel_size = 3; Format = PixelFormats.Bgr24; break; case 2: m_pixel_size = 4; Format = PixelFormats.Bgra32; break; case 3: m_pixel_size = 2; Format = PixelFormats.Bgr555; break; - case 4: m_pixel_size = 1; Format = PixelFormats.Indexed8; break; + case 4: m_pixel_size = 1; Format = PixelFormats.Bgra32; m_has_alpha = true; break; default: throw new NotSupportedException ("Not supported EPA color depth"); } m_width = (int)info.Width; m_height = (int)info.Height; m_output = new byte[info.Width*info.Height*m_pixel_size]; - if (8 == info.BPP) - Palette = ImageFormat.ReadPalette (m_input, 0x100, PaletteFormat.Bgr); + m_start_pos = 2 == info.Mode ? 0x18 : 0x10; } + int[] m_offset_table = new int[16]; + public void Unpack () { - int dst = 0; - var offset_table = new int[16]; + m_input.Position = m_start_pos; + if (1 == m_pixel_size) + Palette = ImageFormat.ReadPalette (m_input.AsStream, 0x100, PaletteFormat.Bgr); + m_offset_table[0] = 0; + m_offset_table[1] = 1; + m_offset_table[2] = m_width; + m_offset_table[3] = m_width + 1; + m_offset_table[4] = 2; + m_offset_table[5] = m_width - 1; + m_offset_table[6] = m_width * 2; + m_offset_table[7] = 3; + m_offset_table[8] = (m_width + 1) * 2; + m_offset_table[9] = m_width + 2; + m_offset_table[10] = m_width * 2 + 1; + m_offset_table[11] = m_width * 2 - 1; + m_offset_table[12] = (m_width - 1) * 2; + m_offset_table[13] = m_width - 2; + m_offset_table[14] = m_width * 3; + m_offset_table[15] = 4; - offset_table[0] = 0; - offset_table[1] = 1; - offset_table[2] = m_width; - offset_table[3] = m_width + 1; - offset_table[4] = 2; - offset_table[5] = m_width - 1; - offset_table[6] = m_width * 2; - offset_table[7] = 3; - offset_table[8] = (m_width + 1) * 2; - offset_table[9] = m_width + 2; - offset_table[10] = m_width * 2 + 1; - offset_table[11] = m_width * 2 - 1; - offset_table[12] = (m_width - 1) * 2; - offset_table[13] = m_width - 2; - offset_table[14] = m_width * 3; - offset_table[15] = 4; - - while (dst < m_output.Length) + UnpackChannel (m_output); + if (m_has_alpha) { - int flag = m_input.ReadByte(); - if (-1 == flag) - throw new InvalidFormatException ("Unexpected end of file"); - - if (0 == (flag & 0xf0)) + var alpha = new byte[m_output.Length]; + UnpackChannel (alpha); + var bitmap = new byte[m_width * m_height * 4]; + int dst = 0; + for (int src = 0; src < m_output.Length; ++src) { - int count = flag; - if (dst + count > m_output.Length) - count = m_output.Length - dst; - if (count != m_input.Read (m_output, dst, count)) - throw new InvalidFormatException ("Unexpected end of file"); - dst += count; - } - else - { - int count; - if (0 != (flag & 8)) - { - count = m_input.ReadByte(); - if (-1 == count) - throw new InvalidFormatException ("Unexpected end of file"); - count += (flag & 7) << 8; - } - else - count = flag & 7; - if (dst + count > m_output.Length) - break; - Binary.CopyOverlapped (m_output, dst-offset_table[flag >> 4], dst, count); - dst += count; + var color = Palette.Colors[m_output[src]]; + bitmap[dst++] = color.B; + bitmap[dst++] = color.G; + bitmap[dst++] = color.R; + bitmap[dst++] = alpha[src]; } + m_output = bitmap; } if (m_pixel_size > 1) { @@ -195,6 +180,38 @@ namespace GameRes.Formats.Pajamas m_output = bitmap; } } + + void UnpackChannel (byte[] output) + { + int dst = 0; + while (dst < output.Length) + { + int count; + int flag = m_input.ReadUInt8(); + if (0 == (flag & 0xF0)) + { + count = flag; + if (dst + count > output.Length) + count = output.Length - dst; + if (count != m_input.Read (output, dst, count)) + throw new InvalidFormatException ("Unexpected end of file"); + } + else + { + if (0 != (flag & 8)) + { + count = m_input.ReadUInt8(); + count += (flag & 7) << 8; + } + else + count = flag & 7; + if (dst + count > output.Length) + break; + Binary.CopyOverlapped (output, dst-m_offset_table[flag >> 4], dst, count); + } + dst += count; + } + } } } }