public SpriteParser(byte[] ChunkData, List <PaletteMap> PMaps, int ChunkID) { m_ChunkID = ChunkID; MemoryStream MemStream = new MemoryStream(ChunkData); BinaryReader Reader = new BinaryReader(MemStream); Reader.BaseStream.Position = INDEX_SPRID; m_ID = Reader.ReadByte(); Reader.BaseStream.Position = INDEX_SPRVERSION; m_Version = Reader.ReadUInt32(); if (m_Version != 1000 && m_Version != 1001) { throw new Exception("Version was: " + m_Version); } m_FrameCount = Reader.ReadUInt32(); if (m_Version == 1000) { m_PaletteID = Reader.ReadUInt32(); } bool PaletteFound = false; foreach (PaletteMap Map in PMaps) { if (Map.ID == m_PaletteID) { m_PMap = Map; PaletteFound = true; } } //This is guesswork, but when the PaletteID is 1, it seems to typically indicate //that there's only one palette to choose from... if (m_PaletteID == 1) { m_PMap = PMaps[0]; PaletteFound = true; } if (!PaletteFound) { throw new Exception("No palette found!"); } for (int i = 0; i < m_FrameCount; i++) { SpriteFrame Frame = new SpriteFrame(); Reader.BaseStream.Position = INDEX_SPROFFSETTABLE + 4 * i; Reader.BaseStream.Position = Reader.ReadUInt32() + INDEX_SPRVERSION; Frame.Width = Reader.ReadUInt16(); Frame.Height = Reader.ReadUInt16(); Frame.Flag = Reader.ReadUInt16(); //Zero value skipped. Reader.BaseStream.Position += 2; Frame.PaletteID = Reader.ReadUInt16(); Frame.PalMap = PMaps[0]; foreach (PaletteMap PMap in PMaps) { if (PMap.ID == m_PaletteID) { Frame.PalMap = PMap; } } Frame.TransparentPixel = m_PMap.GetColorAtIndex(Reader.ReadUInt16()); Frame.XLocation = Reader.ReadUInt16(); Frame.YLocation = Reader.ReadUInt16(); Frame.Init(); EncryptedRowHeader RowHeader = new EncryptedRowHeader(); int RowID = 0; for (int j = 0; j < Frame.Height; j++) { long InitPos = Reader.BaseStream.Position; RowHeader = GetDecryptedValues(Reader.ReadUInt16()); if (RowHeader.Code == 0) { //byte[] RowSegmentData = Reader.ReadBytes(RowHeader.Count - 2); ReadRowSegment(Reader, RowID, ref Frame); Reader.BaseStream.Position = InitPos + RowHeader.Count; RowID++; } else if (RowHeader.Code == 4) { RowID += RowHeader.Count; } else if (RowHeader.Code == 5) { break; } } m_Frames.Add(Frame); } Reader.Close(); }
private void DecompressFrame2(ref SpriteFrame Frame, ref BinaryReader Reader) { bool quit = false; byte Clr = 0; Color Transparent; int CurrentRow = 0, CurrentColumn = 0; byte PixCommand, PixCount = 0; if (m_PMap == null) { m_PMap = new PaletteMap(); } while (quit == false) { byte RowCommand = Reader.ReadByte(); byte RowCount = Reader.ReadByte(); switch (RowCommand) { case 0x00: //Start marker; the count byte is ignored. break; //Fill this row with pixel data that directly follows; the count byte of the row command denotes the //size in bytes of the row and pixel data. case 0x04: RowCount -= 2; CurrentColumn = 0; while (RowCount > 0) { PixCommand = Reader.ReadByte(); PixCount = Reader.ReadByte(); RowCount -= 2; switch (PixCommand) { case 1: //Leave the next pixel count pixels as transparent. Transparent = Color.FromArgb(0, 0, 0, 0); for (int j = CurrentColumn; j < (CurrentColumn + PixCount); j++) { Frame.BitmapData.SetPixel(new Point(j, CurrentRow), Transparent); } CurrentColumn += PixCount; break; case 2: //Fill the next pixel count pixels with a palette color. //The pixel data is two bytes: the first byte denotes the palette color index, and the //second byte is padding (which is always equal to the first byte but is ignored). Clr = Reader.ReadByte(); Reader.ReadByte(); //Padding RowCount -= 2; for (int j = CurrentColumn; j < (CurrentColumn + PixCount); j++) { Frame.BitmapData.SetPixel(new Point(j, CurrentRow), m_PMap.GetColorAtIndex(Clr)); } CurrentColumn += PixCount; break; case 3: //Set the next pixel count pixels to the palette color indices defined by the //pixel data provided directly after this command. byte Padding = (byte)(PixCount % 2); if (Padding != 0) { RowCount -= (byte)(PixCount + Padding); } else { RowCount -= PixCount; } for (int j = CurrentColumn; j < (CurrentColumn + PixCount); j++) { Clr = Reader.ReadByte(); Frame.BitmapData.SetPixel(new Point(j, CurrentRow), m_PMap.GetColorAtIndex(Clr)); } CurrentColumn += PixCount; if (Padding != 0) { Reader.ReadByte(); } break; } } CurrentRow++; break; case 0x05: //End marker. The count byte is always 0, but may be ignored. //Some sprites don't have these, so read them using ReadBytes(), which //simply returns an empty array if the stream couldn't be read. Reader.ReadBytes(2); //PixCommand and PixCount. quit = true; break; case 0x09: //Leave the next count rows as transparent. PixCommand = Reader.ReadByte(); PixCount = Reader.ReadByte(); Transparent = Color.FromArgb(0, 0, 0, 0); for (int i = 0; i < RowCount; i++) { for (int j = CurrentColumn; j < Frame.Width; j++) { Frame.BitmapData.SetPixel(new Point(j, CurrentRow), Transparent); } CurrentRow++; } break; case 0x10: //Start marker, equivalent to 0x00; the count byte is ignored. break; } if (Reader.BaseStream.Position == Reader.BaseStream.Length) { break; } } }
public SPR2Parser(IffChunk Chunk, List <PaletteMap> PMaps) : base(Chunk) { m_Name = Name; int[] offsets; MemoryStream MemStream = new MemoryStream(Chunk.Data); BinaryReader Reader = new BinaryReader(MemStream); m_Version = Reader.ReadUInt32(); //In version 1001, all frames are decompressed from the beginning, and there's no point in storing //the compressed data AS WELL as the decompressed frames...! if (m_Version == 1000) { m_ChunkData = Chunk.Data; } if (m_Version == 1001) { m_PaletteID = Reader.ReadUInt32(); m_FrameCount = Reader.ReadUInt32(); } else { m_FrameCount = Reader.ReadUInt32(); m_PaletteID = Reader.ReadUInt32(); } if (PMaps.Count == 1 && m_PaletteID == 1) { m_PMap = PMaps[0]; } else { m_PMap = PMaps.Find(delegate(PaletteMap PMap) { if (PMap.ID == m_PaletteID) { return(true); } return(false); }); } //Some SPR2s blatantly specify the wrong ID because there's only one palettemap... if (m_PMap == null) { m_PMap = PMaps[0]; } offsets = new int[m_FrameCount]; if (m_Version == 1000) { for (int i = 0; i < m_FrameCount; i++) { offsets[i] = Reader.ReadInt32(); m_FrameOffsets.Add(offsets[i]); } } if (m_Version == 1001) { for (int l = 0; l < m_FrameCount; l++) { SpriteFrame Frame = new SpriteFrame(); Frame.Version = Reader.ReadUInt32(); Frame.Size = Reader.ReadUInt32(); Frame.Width = Reader.ReadUInt16(); Frame.Height = Reader.ReadUInt16(); Frame.Flag = Reader.ReadUInt32(); Frame.PaletteID = Reader.ReadUInt16(); Frame.TransparentPixel = m_PMap.GetColorAtIndex(Reader.ReadUInt16()); Frame.YLocation = Reader.ReadUInt16(); Frame.XLocation = Reader.ReadUInt16(); if ((SPR2Flags)Frame.Flag == SPR2Flags.HasAlphaChannel) { Frame.Init(true, true); } else { if ((SPR2Flags)Frame.Flag == SPR2Flags.HasZBufferChannel) { Frame.Init(false, true); } else { Frame.Init(false, false); } } DecompressFrame2(ref Frame, ref Reader); Frame.BitmapData.Unlock(true); //The bitmapdata is locked when the frame is created. if (Frame.HasZBuffer) { Frame.ZBuffer.Unlock(true); //The bitmapdata is locked when the frame is created. } m_Frames.Add(Frame); } } Reader.Close(); }