summaryrefslogtreecommitdiff
path: root/NW4RTools/Texture.cs
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2011-03-03 04:53:56 +0100
committerTreeki <treeki@gmail.com>2011-03-03 04:53:56 +0100
commitab340fe4dc87086336643b6b616df6efdfac796b (patch)
treeaa01265000e80c8348631f3ae67cc6ded16d90bb /NW4RTools/Texture.cs
parent6b14bc71cb699b72ca6cf164b7b800add414dec6 (diff)
downloadnw4rtools-ab340fe4dc87086336643b6b616df6efdfac796b.tar.gz
nw4rtools-ab340fe4dc87086336643b6b616df6efdfac796b.zip
working (but not 100% tested) model and texture writing. a few other fixes, etc
Diffstat (limited to '')
-rw-r--r--NW4RTools/Texture.cs195
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