/// <summary> /// Applies edge mask (edgeEntry) on parentTile, result is stored in bit /// </summary> public void ApplyEdgeMask(Bitmap bit, int edgeID, int coverID) { FileEntry edgeEntry = Entries[edgeID]; FileEntry coverTile = Entries[coverID]; // prepare cover Section sect = coverTile.BaseSection; byte[] sectionUncompressedData = sectionCache.LookupCache(sect); if (sectionUncompressedData == null) { videoBagStream.BaseStream.Seek(sect.VideoBagOffset, SeekOrigin.Begin); byte[] sectionCompressedData = videoBagStream.ReadBytes((int)sect.SizeCompressed); sectionUncompressedData = new byte[sect.SizeUncompressed]; NoxLzCompression.Decompress(sectionCompressedData, sectionUncompressedData); // add data in cache sectionCache.AddToCache(sect, sectionUncompressedData); } int[] coverColorData = ReadType0Image(coverTile, sectionUncompressedData); // prepare edge sect = edgeEntry.BaseSection; sectionUncompressedData = sectionCache.LookupCache(sect); if (sectionUncompressedData == null) { videoBagStream.BaseStream.Seek(sect.VideoBagOffset, SeekOrigin.Begin); byte[] sectionCompressedData = videoBagStream.ReadBytes((int)sect.SizeCompressed); sectionUncompressedData = new byte[sect.SizeUncompressed]; NoxLzCompression.Decompress(sectionCompressedData, sectionUncompressedData); // add data in cache sectionCache.AddToCache(sect, sectionUncompressedData); } // build up TileEdgeMixer edge = new TileEdgeMixer(bit, coverColorData, sectionUncompressedData, Palette8Bit, (int)edgeEntry.SectionOffset, (int)edgeEntry.SizeUncompressed); edge.Apply(); }
/// <summary> /// Returns ready-to-go Bitmap and offset values for given Entry /// </summary> public unsafe Bitmap GetBitmap(FileEntry fe, out int offsX, out int offsY) { int[] bitmap = null; PixelFormat format = PixelFormat.Format32bppArgb; Bitmap result = null; Section sect = fe.BaseSection; // look up uncompressed data in cache byte[] sectionUncompressedData = sectionCache.LookupCache(sect); if (sectionUncompressedData == null) { videoBagStream.BaseStream.Seek(sect.VideoBagOffset, SeekOrigin.Begin); byte[] sectionCompressedData = videoBagStream.ReadBytes((int)sect.SizeCompressed); sectionUncompressedData = new byte[sect.SizeUncompressed]; NoxLzCompression.Decompress(sectionCompressedData, sectionUncompressedData); // add data in cache sectionCache.AddToCache(sect, sectionUncompressedData); } int width = 0, height = 0; uint moff; offsX = 0; offsY = 0; fixed(byte *imgSectionPtr = sectionUncompressedData) { switch (fe.EntryType) { case 0: // Tiles width = 46; height = 46; bitmap = ReadType0Image(fe, imgSectionPtr); break; case 1: // // Tile edges width = 46; height = 46; throw new InvalidOperationException("Use ApplyEdgeMask() instead"); case 3: // kinda PCX moff = fe.SectionOffset; width = *((int *)(imgSectionPtr + moff)); moff += 4; height = *((int *)(imgSectionPtr + moff)); moff += 4; offsX = *((int *)(imgSectionPtr + moff)); moff += 4; offsY = *((int *)(imgSectionPtr + moff)); bitmap = ReadType3Image(fe, imgSectionPtr); break; case 4: case 5: case 6: // Same as 3 but with dynamic colors moff = fe.SectionOffset; width = *((int *)(imgSectionPtr + moff)); moff += 4; height = *((int *)(imgSectionPtr + moff)); moff += 4; offsX = *((int *)(imgSectionPtr + moff)); moff += 4; offsY = *((int *)(imgSectionPtr + moff)); bitmap = ReadType456Image(fe, imgSectionPtr); break; } } if (width > 0 && height > 0) { result = new Bitmap(width, height, format); int stride = 4 * width; // copy bitmap BitmapData bd = result.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, format); Marshal.Copy(bitmap, 0, bd.Scan0, bitmap.Length); result.UnlockBits(bd); } return(result); }