diff options
Diffstat (limited to 'NW4RTools/Texture.cs')
-rw-r--r-- | NW4RTools/Texture.cs | 195 |
1 files changed, 169 insertions, 26 deletions
diff --git a/NW4RTools/Texture.cs b/NW4RTools/Texture.cs index 0561435..078fa6b 100644 --- a/NW4RTools/Texture.cs +++ b/NW4RTools/Texture.cs @@ -82,8 +82,6 @@ namespace NW4RTools { width = Misc.AlignUp(width, info.TexelWidth); height = Misc.AlignUp(height, info.TexelHeight); - // SPECIAL CASE: - return width * height * info.NybblesPerPixel / 2; } @@ -100,46 +98,154 @@ namespace NW4RTools { return GetDataSize(Images[imageID].Width, Images[imageID].Height, Format); } - unsafe public void ImportData(int imageID, byte[] imgdata, int width, int height, TextureFormat format) { - var image = new Bitmap(width, height, PixelFormat.Format32bppArgb); - var bits = image.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, image.PixelFormat); - var info = TextureFormatInfo.GetFormat(format); + unsafe public byte[] ExportData(int imageID) { + var info = TextureFormatInfo.GetFormat(Format); int blkWidth = info.TexelWidth; int blkHeight = info.TexelHeight; - /*int blkNumY = 0; + int width = Images[imageID].Width; + int height = Images[imageID].Height; + var bits = Images[imageID].LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); - for (int blkY = 0; blkY < height; blkY += blkHeight) { - byte* pBlkY = (byte*)bits.Scan0 + (blkY * bits.Stride); + var data = new OutputStream(ByteEndian.BigEndian); - int blkNumX = 0; + switch (Format) { + case TextureFormat.RGB565: + case TextureFormat.RGB5A3: + case TextureFormat.I4: + case TextureFormat.I8: + case TextureFormat.IA4: + case TextureFormat.IA8: + // This won't be fun + bool alreadyHaveI4Nybble = false; + byte currentI4Byte = 0; - for (int blkX = 0; blkX < width; blkX += blkWidth) { - byte* pBlk = pBlkY + (blkX * sizeof(uint)); + for (int y = 0; y < height; y += blkHeight) { + int yMax = y + blkHeight; + if (yMax > height) + yMax = height; + + for (int x = 0; x < width; x += blkWidth) { + int xMax = x + blkWidth; + if (xMax > width) + xMax = width; + + for (int y1 = y; y1 < yMax; y1++) { + byte* pRow = (byte*)bits.Scan0 + (y1 * bits.Stride); + + for (int x1 = x; x1 < xMax; x1++) { + uint* pPixel = (uint*)pRow + x1; + + byte a = (byte)((*pPixel & 0xFF000000) >> 24); + byte r = (byte)((*pPixel & 0x00FF0000) >> 16); + byte g = (byte)((*pPixel & 0x0000FF00) >> 8); + byte b = (byte)(*pPixel & 0x000000FF); + + if (Format == TextureFormat.RGB565) { + ushort _r = (ushort)(r >> 3); + ushort _g = (ushort)(g >> 2); + ushort _b = (ushort)(b >> 3); + data.WriteUInt16((ushort)((_r << 11) | (_g << 5) | _b)); + + } else if (Format == TextureFormat.RGB5A3) { + if (a == 255) { + ushort _r = (ushort)(r >> 3); + ushort _g = (ushort)(g >> 3); + ushort _b = (ushort)(b >> 3); + data.WriteUInt16((ushort)(0x8000 | (_r << 10) | (_g << 5) | _b)); + } else { + ushort _a = (ushort)(a >> 5); + ushort _r = (ushort)(r >> 4); + ushort _g = (ushort)(g >> 4); + ushort _b = (ushort)(b >> 4); + data.WriteUInt16((ushort)((_a << 12) | (_r << 8) | (_g << 4) | _b)); + } - for (int y = 0; y < blkHeight; y++) { - if ((blkY + y) >= height) - break; + } else if (Format == TextureFormat.I4) { + byte _i = (byte)((r & g & b) >> 4); - byte* pRow = pBlk + (y * bits.Stride); + if (!alreadyHaveI4Nybble) { + currentI4Byte = (byte)(_i << 4); + } else { + data.WriteByte((byte)(currentI4Byte | _i)); + currentI4Byte = 0; + } - for (int x = 0; x < blkWidth; x++) { - if ((blkX + x) >= width) - break; + alreadyHaveI4Nybble = !alreadyHaveI4Nybble; + + } else if (Format == TextureFormat.I8) { + byte _i = (byte)(r & g & b); + data.WriteByte(_i); - uint* pPixel = (uint*)pRow + x; + } else if (Format == TextureFormat.IA4) { + byte _i = (byte)((r & g & b) >> 4); + byte _a = (byte)(a >> 4); + data.WriteByte((byte)((_i << 4) | _a)); + } else if (Format == TextureFormat.IA8) { + byte _i = (byte)(r & g & b); + data.WriteByte(_i); + data.WriteByte(a); + } + } } } + } + + break; + + case TextureFormat.RGBA8: + // this one is a pain because it stores an AR chunk, then a GB chunk, then ... + for (int y = 0; y < height; y += blkHeight) { + int yMax = y + blkHeight; + if (yMax > height) + yMax = height; + + for (int x = 0; x < width; x += blkWidth) { + int xMax = x + blkWidth; + if (xMax > width) + xMax = width; + + for (int blkType = 0; blkType < 2; blkType++) { + for (int y1 = y; y1 < yMax; y1++) { + byte* pRow = (byte*)bits.Scan0 + (y1 * bits.Stride); + + for (int x1 = x; x1 < xMax; x1++) { + uint* pPixel = (uint*)pRow + x1; + + ushort piece; + if (blkType == 0) { + piece = (ushort)((*pPixel & 0xFFFF0000) >> 16); + } else { + piece = (ushort)(*pPixel & 0x0000FFFF); + } - blkNumX++; + data.WriteUInt16(piece); + } + } + } + } } - blkNumY++; - }*/ + + break; + } + + Images[imageID].UnlockBits(bits); + return data.GetBuffer(); + } + - // What I'm missing overall: IA4, IA8, RGBA8, all the palette ones + unsafe public void ImportData(int imageID, byte[] imgdata, int width, int height, TextureFormat format) { + var image = new Bitmap(width, height, PixelFormat.Format32bppArgb); + var bits = image.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, image.PixelFormat); + + var info = TextureFormatInfo.GetFormat(format); + int blkWidth = info.TexelWidth; + int blkHeight = info.TexelHeight; + + // What I'm missing overall: all the palette ones // this thing probably breaks on textures which aren't multiples of the texel width/height, too // oh well @@ -168,10 +274,10 @@ namespace NW4RTools { xMax = width; for (int y1 = y; y1 < yMax; y1++) { - byte *pRow = (byte*)bits.Scan0 + (y1 * bits.Stride); + byte* pRow = (byte*)bits.Scan0 + (y1 * bits.Stride); for (int x1 = x; x1 < xMax; x1++) { - uint *pPixel = (uint*)pRow + x1; + uint* pPixel = (uint*)pRow + x1; if (format == TextureFormat.RGB565) { ushort val = data.ReadUInt16(); @@ -230,6 +336,43 @@ namespace NW4RTools { break; + case TextureFormat.RGBA8: + // this one is a pain because it stores an AR chunk, then a GB chunk, then ... + for (int y = 0; y < height; y += blkHeight) { + int yMax = y + blkHeight; + if (yMax > height) + yMax = height; + + for (int x = 0; x < width; x += blkWidth) { + int xMax = x + blkWidth; + if (xMax > width) + xMax = width; + + for (int blkType = 0; blkType < 2; blkType++) { + for (int y1 = y; y1 < yMax; y1++) { + byte* pRow = (byte*)bits.Scan0 + (y1 * bits.Stride); + + for (int x1 = x; x1 < xMax; x1++) { + uint* pPixel = (uint*)pRow + x1; + + uint val1 = data.ReadByte(); + uint val2 = data.ReadByte(); + + if (blkType == 0) { + // Alpha, Red + *pPixel = ((*pPixel & 0x0000FFFF) | (val1 << 24) | (val2 << 16)); + } else { + // Green, Blue + *pPixel = ((*pPixel & 0xFFFF0000) | (val1 << 8) | (val2 << 0)); + } + } + } + } + } + } + + break; + case TextureFormat.CMPR: // this code is messy |