private static byte[] getDataRF(BinaryReader br, long baseP, out long ramOffset, out long fileOffset) { ulong num = br.ReadUInt64(); ramOffset = 256u * (((uint)(num >> 0x20)) & 0x3FFFu); int bw = ((int)(num >> 0x30)) & 0x3F; uint type = ((uint)(num >> 0x38)) & 0x3F; #if TRACE br.BaseStream.Position += 8; Trace.Assert((num & 0x3fff) == 0); Trace.Assert(((num >> 16) & 0x3f) == 0); Trace.Assert(((num >> 0x18) & 0x3f) == 0); num = br.ReadUInt64(); br.BaseStream.Position += 8; Trace.Assert((num & 0x7ff) == 0); Trace.Assert(((num >> 0x10) & 0x7ff) == 0); Trace.Assert(((num >> 0x20) & 0x7ff) == 0); Trace.Assert(((num >> 0x30) & 0x7ff) == 0); Trace.Assert(((num >> 0x3b) & 3) == 0); br.BaseStream.Position += 16; Trace.Assert((br.ReadUInt64() & 2) == 0); br.BaseStream.Position += 8; #else br.BaseStream.Position += 8 + 16 + 16 + 16; #endif int size = (br.ReadUInt16() & 0x7FFF) << 4; br.BaseStream.Position += 0x12L; br.BaseStream.Position = fileOffset = baseP + br.ReadInt32(); var buffer = new byte[size]; Debug.WriteLine("Reading " + size + " bytes..."); #if DEBUG { int t = br.BaseStream.Read(buffer, 0, size); Debug.WriteLineIf(t != size, "Expected " + size + " bytes, but only got " + t + " bytes!"); } #else br.BaseStream.Read(buffer, 0, size); #endif Debug.WriteLine("bw = " + bw + "; type = " + type + "; size = " + size); size /= 8192; switch (type) { case 0: if (bw > 0) { buffer = Reform.Encode32(buffer, bw, size / bw); } break; case 19: bw /= 2; if (bw > 0) { buffer = Reform.Encode8(buffer, bw, size / bw); } break; case 20: bw /= 2; if (bw > 0) { buffer = Reform.Encode4(buffer, bw, size / bw); } break; default: throw new NotSupportedException("Unknown type: " + type); } return(buffer); }
public static byte[] Encode(Bitmap bmp, ref byte[] palbin, byte csa = 0) { int pixelSize = bmp.Width * bmp.Height; Debug.WriteLine("TexUt2.Decode: bw = " + (bmp.Width / 128) + "; BH = " + (bmp.Height / 64) + "; type = " + (bmp.PixelFormat == PixelFormat.Format8bppIndexed ? "19" : "20") + "; size = " + pixelSize + "; width = " + bmp.Width + "; height = " + bmp.Height); switch (bmp.PixelFormat) { case PixelFormat.Format8bppIndexed: csa = 0; break; case PixelFormat.Format4bppIndexed: pixelSize /= 2; csa *= 64; break; default: throw new NotSupportedException("Unsupported type"); } //Palette { var destinationArray = new byte[1024]; for (int i = 0; i < 256; i++) { Buffer.BlockCopy(palbin, 4 * i, destinationArray, 4 * (i + tbl[i & 0x7F]), 4); } ColorPalette palette = bmp.Palette; for (int i = 0; i < palette.Entries.Length; i++) { int c = csa + (i * 4); var argb = (uint)palette.Entries[i].ToArgb(); destinationArray[c + 3] = (byte)Math.Ceiling((double)(argb >> 24) / 2); destinationArray[c] = (byte)(argb >> 16); destinationArray[c + 1] = (byte)(argb >> 8); destinationArray[c + 2] = (byte)argb; } for (int i = 0; i < 256; i++) { Buffer.BlockCopy(destinationArray, 4 * (i + tbl[i & 0x7F]), palbin, 4 * i, 4); } } //Pixels var bin = new byte[pixelSize]; { BitmapData bitmapdata = bmp.LockBits(Rectangle.FromLTRB(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, bmp.PixelFormat); try { Marshal.Copy(bitmapdata.Scan0, bin, 0, pixelSize); } finally { bmp.UnlockBits(bitmapdata); } } switch (bmp.PixelFormat) { case PixelFormat.Format8bppIndexed: bin = Reform.Encode8(bin, bmp.Width / 128, bmp.Height / 64); break; case PixelFormat.Format4bppIndexed: bin = Reform.Encode4(bin, bmp.Width / 128, bmp.Height / 128); break; } return(bin); }
protected override void setBMPInternal(int index, ref Bitmap bmp) { if (!file.CanWrite) { throw new NotSupportedException("Stream is readonly."); } long pos = getIMGDOffset(index); file.Seek(pos, SeekOrigin.Begin); if (file.ReadUInt32() != 0x44474D49) { throw new InvalidDataException("IMGD has bad signature."); } file.Seek(4, SeekOrigin.Current); uint pixelOffset = file.ReadUInt32(), pixelLength = file.ReadUInt32(), paletteOffset = file.ReadUInt32(), paletteLength = file.ReadUInt32(); file.Seek(4, SeekOrigin.Current); ushort width = file.ReadUInt16(), height = file.ReadUInt16(); file.Seek(6, SeekOrigin.Current); ushort type = file.ReadUInt16(); file.Seek(20, SeekOrigin.Current); byte encode = file.ReadByte(); if (bmp.Width != width || bmp.Height != height) { throw new NotSupportedException("New image has different dimensions."); } PixelFormat pf; switch (type) { case 19: pf = PixelFormat.Format8bppIndexed; break; case 20: pf = PixelFormat.Format4bppIndexed; break; default: throw new NotSupportedException("Unsupported IMGD type"); } if (bmp.PixelFormat != pf) { requestQuantize(ref bmp, pf); } { BitmapData pix = bmp.LockBits(Rectangle.FromLTRB(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, pf); var buffer = new byte[pixelLength]; try { Marshal.Copy(pix.Scan0, buffer, 0, (int)pixelLength); } finally { bmp.UnlockBits(pix); } switch (pf) { case PixelFormat.Format8bppIndexed: if (encode == 7) { buffer = Reform.Decode32(Reform.Encode8(buffer, width / 128, height / 64), width / 128, height / 64); } break; case PixelFormat.Format4bppIndexed: if (encode == 7) { buffer = Reform.Decode32(Reform.Encode4(buffer, width / 128, height / 128), width / 128, height / 128); } else { Reform.swapHLUT(buffer); } break; } file.Seek(pos + pixelOffset, SeekOrigin.Begin); file.Write(buffer, 0, (int)pixelLength); } { ColorPalette palette = bmp.Palette; var buffer = new byte[paletteLength]; switch (pf) { case PixelFormat.Format8bppIndexed: for (int i = 0; i < 256; i++) { var argb = (uint)palette.Entries[Reform.paletteSwap34(i)].ToArgb(); buffer[(i * 4) + 3] = (byte)Math.Ceiling((double)(argb >> 24) / 2); buffer[i * 4] = (byte)(argb >> 16); buffer[i * 4 + 1] = (byte)(argb >> 8); buffer[i * 4 + 2] = (byte)argb; } break; case PixelFormat.Format4bppIndexed: for (int i = 0; i < 16; i++) { var argb = (uint)palette.Entries[i].ToArgb(); buffer[(i * 4) + 3] = (byte)Math.Ceiling((double)(argb >> 24) / 2); buffer[i * 4] = (byte)(argb >> 16); buffer[i * 4 + 1] = (byte)(argb >> 8); buffer[i * 4 + 2] = (byte)argb; } break; } file.Seek(pos + paletteOffset, SeekOrigin.Begin); file.Write(buffer, 0, (int)paletteLength); } }