Minor refactor and readability improvements

This commit is contained in:
AdAstra-LD
2021-03-27 03:58:06 +01:00
parent e909e47c65
commit b847b75860
4 changed files with 173 additions and 292 deletions

View File

@@ -346,7 +346,7 @@ namespace MKDS_Course_Editor.NSBCA {
dataoffset = toffset;
}
float keyFrame = (width != 2 ? (float)er.ReadInt32() : (float)er.ReadInt16());
ns.JAC[i].ObjInfo[j].translate_keyframes[k].Add((float)LibNDSFormats.NSBMD.NSBMDGlRenderer.sign((int)keyFrame, (width != 2 ? 32 : 16)) / 4096f);
ns.JAC[i].ObjInfo[j].translate_keyframes[k].Add((float)LibNDSFormats.NSBMD.NSBMDGlRenderer.Sign((int)keyFrame, (width != 2 ? 32 : 16)) / 4096f);
//m = (new StringBuilder()).append(m).append("\n -> #").append(t).append(": ").append(keyFrame).toString();
}
er.BaseStream.Position = curpos;

View File

@@ -514,12 +514,12 @@ namespace LibNDSFormats.NSBMD
model[0].laststackid = laststack;
model[0].modelScale = modelscale;
model[0].boundScale = boundscale;
model[0].boundXmin = (float)NSBMDGlRenderer.sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundYmin = (float)NSBMDGlRenderer.sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundZmin = (float)NSBMDGlRenderer.sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundXmax = (float)NSBMDGlRenderer.sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundYmax = (float)NSBMDGlRenderer.sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundZmax = (float)NSBMDGlRenderer.sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundXmin = (float)NSBMDGlRenderer.Sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundYmin = (float)NSBMDGlRenderer.Sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundZmin = (float)NSBMDGlRenderer.Sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundXmax = (float)NSBMDGlRenderer.Sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundYmax = (float)NSBMDGlRenderer.Sign(reader.ReadInt16(), 16) / 4096f;
model[0].boundZmax = (float)NSBMDGlRenderer.Sign(reader.ReadInt16(), 16) / 4096f;
var polyOffsets = new UInt32[polynum];
var polyDataSize = new UInt32[polynum];
@@ -670,9 +670,9 @@ namespace LibNDSFormats.NSBMD
case 1:
{
int sscale = (int)reader.ReadInt32();// >> 0 & 0xFFFFFFFF;
sscale = NSBMDGlRenderer.sign(sscale, 32);
sscale = NSBMDGlRenderer.Sign(sscale, 32);
int tscale = (int)reader.ReadInt32();// >> 0 & 0xFFFFFFFF;
tscale = NSBMDGlRenderer.sign(tscale, 32);
tscale = NSBMDGlRenderer.Sign(tscale, 32);
//int strans = (int)unknown2 >> 0 & 0xFFFF;
//int ttrans = (int)unknown2 >> 16 & 0xFFFF;
@@ -874,7 +874,7 @@ namespace LibNDSFormats.NSBMD
float fixe = value;
if (sign == 1)
{
fixe = NSBMDGlRenderer.sign(value, GetSizeOfObject(value));
fixe = NSBMDGlRenderer.Sign(value, GetSizeOfObject(value));
}
float divide = 1 << frac;
fixe /= divide;
@@ -904,7 +904,7 @@ namespace LibNDSFormats.NSBMD
{
UInt16 v = reader.ReadUInt16();
Int16 divide = reader.ReadInt16();
divide = (short)NSBMDGlRenderer.sign(divide, 16);
divide = (short)NSBMDGlRenderer.Sign(divide, 16);
int unknown = v >> 12 & 0xf;
nsbmdObject.StackID = unknown;
//nsbmdObject.isBillboard = ((v >> 12 & 0xf) == 1?true:false);
@@ -924,9 +924,9 @@ namespace LibNDSFormats.NSBMD
{
nsbmdObject.IsRotated = true;
float a = reader.ReadInt16();
a = NSBMDGlRenderer.sign((int)a, 16) / 4096f;
a = NSBMDGlRenderer.Sign((int)a, 16) / 4096f;
float b = reader.ReadInt16();
b = NSBMDGlRenderer.sign((int)b, 16) / 4096f;
b = NSBMDGlRenderer.Sign((int)b, 16) / 4096f;
nsbmdObject.Pivot = (int)(v >> 4) & 0x0f;
nsbmdObject.Neg = (int)(v >> 8) & 0x0f;
nsbmdObject.RotA = a;
@@ -946,7 +946,7 @@ namespace LibNDSFormats.NSBMD
for (int j = 0; j < rotate.Length; j++)
{
//dataParser _tmp4 = pa;
int value = NSBMDGlRenderer.sign(reader.ReadInt16(),16); //dataParser.getSign(data, offset + 4 + j * 2 + jump, 2);
int value = NSBMDGlRenderer.Sign(reader.ReadInt16(),16); //dataParser.getSign(data, offset + 4 + j * 2 + jump, 2);
rotate[j] = (float)value / 4096f;
//msg = (new StringBuilder()).append(msg).append(pad(Integer.valueOf(value), 4)).toString();
//if(j + 1 < rotate.length)

View File

@@ -645,18 +645,18 @@ namespace LibNDSFormats.NSBMD {
int pvneg = ca.JAC[selectedanim].JointData[(((int)ca.JAC[selectedanim].ObjInfo[i].rotate[0]) & 0x7fff) * 6];//Utils.Read2BytesAsInt16(ca.JAC[selectedanim].JointData, (int)ca.JAC[selectedanim].ObjInfo[i].rotate_keyframes[0][R[i]] * 6 + 0);
int a = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].JointData, (((int)ca.JAC[selectedanim].ObjInfo[i].rotate[0]) & 0x7fff) * 6 + 2);
int b = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].JointData, (((int)ca.JAC[selectedanim].ObjInfo[i].rotate[0]) & 0x7fff) * 6 + 4);
a = sign(a, 16);
b = sign(b, 16);
a = Sign(a, 16);
b = Sign(b, 16);
//mt = multMatrix(mt, Nsbmd.mtxPivot(new float[] { (float)a / 4096f, (float)b / 4096f }, (pvneg >> 0 & 0x0f), (pvneg >> 4 & 0x0f)));
//Gl.glMultMatrixf(Nsbmd.mtxPivot(new float[] { (float)a / 4096f, (float)b / 4096f }, (pvneg >> 0 & 0x0f), (pvneg >> 4 & 0x0f)));
r = NSBMD.mtxPivot(new float[] { (float)a / 4096f, (float)b / 4096f }, (pvneg >> 0 & 0x0f), (pvneg >> 4 & 0x0f));//multMatrix(r, Nsbmd.mtxPivot(new float[] { (float)a / 4096f, (float)b / 4096f }, (pvneg >> 0 & 0x0f), (pvneg >> 4 & 0x0f)));
} else {
int x = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].RotationData, (((int)ca.JAC[selectedanim].ObjInfo[i].rotate[0]) & 0x7fff) * 10 + 2);
x = sign(x, 16);
x = Sign(x, 16);
int y = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].RotationData, (((int)ca.JAC[selectedanim].ObjInfo[i].rotate[0]) & 0x7fff) * 10 + 4);
y = sign(y, 16);
y = Sign(y, 16);
int z = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].RotationData, (((int)ca.JAC[selectedanim].ObjInfo[i].rotate[0]) & 0x7fff) * 10 + 6);
z = sign(z, 16);
z = Sign(z, 16);
OpenTK.Matrix4 X = OpenTK.Matrix4.CreateRotationX((float)x / 131072F);//((float)x * (float)Math.PI) / 32768F);
OpenTK.Matrix4 Y = OpenTK.Matrix4.CreateRotationY((float)y / 131072F);//((float)y * (float)Math.PI) / 32768F);
OpenTK.Matrix4 Z = OpenTK.Matrix4.CreateRotationZ((float)z / 131072F);//((float)z * (float)Math.PI) / 32768F);
@@ -672,8 +672,8 @@ namespace LibNDSFormats.NSBMD {
int pvneg = ca.JAC[selectedanim].JointData[(int)ca.JAC[selectedanim].ObjInfo[i].rotate_keyframes[0][R[i]] * 6];//Utils.Read2BytesAsInt16(ca.JAC[selectedanim].JointData, (int)ca.JAC[selectedanim].ObjInfo[i].rotate_keyframes[0][R[i]] * 6 + 0);
int a = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].JointData, (int)ca.JAC[selectedanim].ObjInfo[i].rotate_keyframes[0][R[i]] * 6 + 2);
int b = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].JointData, (int)ca.JAC[selectedanim].ObjInfo[i].rotate_keyframes[0][R[i]] * 6 + 4);
a = sign(a, 16);
b = sign(b, 16);
a = Sign(a, 16);
b = Sign(b, 16);
//mt = multMatrix(mt, Nsbmd.mtxPivot(new float[] { (float)a / 4096f, (float)b / 4096f }, (pvneg >> 0 & 0x0f), (pvneg >> 4 & 0x0f)));
//Gl.glMultMatrixf(Nsbmd.mtxPivot(new float[] { (float)a / 4096f, (float)b / 4096f }, (pvneg >> 0 & 0x0f), (pvneg >> 4 & 0x0f)));
r = NSBMD.mtxPivot(new float[] { (float)a / 4096f, (float)b / 4096f }, (pvneg >> 0 & 0x0f), (pvneg >> 4 & 0x0f));//multMatrix(r, Nsbmd.mtxPivot(new float[] { (float)a / 4096f, (float)b / 4096f }, (pvneg >> 0 & 0x0f), (pvneg >> 4 & 0x0f)));
@@ -681,11 +681,11 @@ namespace LibNDSFormats.NSBMD {
float param = ca.JAC[selectedanim].RotationData[(int)ca.JAC[selectedanim].ObjInfo[i].rotate_keyframes[0][R[i]] * 10];
//float u = (float)Math.Pow(2.0f, param) * (float)180 / 131072F;
int x = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].RotationData, (int)ca.JAC[selectedanim].ObjInfo[i].rotate_keyframes[0][R[i]] * 10 + 2);
x = sign(x, 16);
x = Sign(x, 16);
int y = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].RotationData, (int)ca.JAC[selectedanim].ObjInfo[i].rotate_keyframes[0][R[i]] * 10 + 4);
y = sign(y, 16);
y = Sign(y, 16);
int z = Utils.Read2BytesAsInt16(ca.JAC[selectedanim].RotationData, (int)ca.JAC[selectedanim].ObjInfo[i].rotate_keyframes[0][R[i]] * 10 + 6);
z = sign(z, 16);
z = Sign(z, 16);
OpenTK.Matrix4 X = OpenTK.Matrix4.CreateRotationX((float)x / 131072F);//((float)x * (float)Math.PI) / 32768F);
OpenTK.Matrix4 Y = OpenTK.Matrix4.CreateRotationY((float)y / 131072F);//((float)y * (float)Math.PI) / 32768F);
OpenTK.Matrix4 Z = OpenTK.Matrix4.CreateRotationZ((float)z / 131072F);//((float)z * (float)Math.PI) / 32768F);
@@ -1646,7 +1646,7 @@ namespace LibNDSFormats.NSBMD {
commandptr += 4;
z = Utils.Read4BytesAsInt32(polydata, commandptr);
commandptr += 4;
CurrentMatrix.translate((float)sign(x, 32) / SCALE_IV / Model.modelScale, (float)sign(y, 32) / SCALE_IV / Model.modelScale, (float)sign(z, 32) / SCALE_IV / Model.modelScale);
CurrentMatrix.translate((float)Sign(x, 32) / SCALE_IV / Model.modelScale, (float)Sign(y, 32) / SCALE_IV / Model.modelScale, (float)Sign(z, 32) / SCALE_IV / Model.modelScale);
break;
}
case 0x20: // Directly Set Vertex Color (W)
@@ -1736,14 +1736,14 @@ namespace LibNDSFormats.NSBMD {
parameter = Utils.Read4BytesAsInt32(polydata, commandptr);
commandptr += 4;
x = sign((parameter >> 0) & 0xFFFF, 16);
x = Sign((parameter >> 0) & 0xFFFF, 16);
//if ((x & 0x8000) != 0) x |= unchecked((int)0xFFFF0000);//-65536;
y = sign((parameter >> 16) & 0xFFFF, 16);
y = Sign((parameter >> 16) & 0xFFFF, 16);
//if ((y & 0x8000) != 0) y |= unchecked((int)0xFFFF0000);//-65536;
parameter = Utils.Read4BytesAsInt32(polydata, commandptr);
commandptr += 4;
z = sign(parameter & 0xFFFF, 16);
z = Sign(parameter & 0xFFFF, 16);
// if ((z & 0x8000) != 0) z |= unchecked((int)0xFFFF0000);//-65536;
vtx_state[0] = ((float)x) / SCALE_IV;
@@ -1804,11 +1804,11 @@ namespace LibNDSFormats.NSBMD {
xyz = Utils.Read4BytesAsInt32(polydata, commandptr);
commandptr += 4;
x = sign((xyz >> 0) & 0x3FF, 10);
x = Sign((xyz >> 0) & 0x3FF, 10);
// if ((x & 0x200) != 0) x |= unchecked((int)0xFFFFFC00);//-1024;
y = sign((xyz >> 10) & 0x3FF, 10);
y = Sign((xyz >> 10) & 0x3FF, 10);
//if ((y & 0x200) != 0) y |= unchecked((int)0xFFFFFC00);//-1024;
z = sign((xyz >> 20) & 0x3FF, 10);
z = Sign((xyz >> 20) & 0x3FF, 10);
// if ((z & 0x200) != 0) z |= unchecked((int)0xFFFFFC00);//-1024;
vtx_state[0] = (float)x / 64.0f;
@@ -1867,9 +1867,9 @@ namespace LibNDSFormats.NSBMD {
xy = Utils.Read4BytesAsInt32(polydata, commandptr);
commandptr += 4;
x = sign((xy >> 0) & 0xFFFF, 16);
x = Sign((xy >> 0) & 0xFFFF, 16);
//if ((x & 0x8000) != 0) x |= unchecked((int)0xFFFF0000);//-65536;
y = sign((xy >> 16) & 0xFFFF, 16);
y = Sign((xy >> 16) & 0xFFFF, 16);
//if ((y & 0x8000) != 0) y |= unchecked((int)0xFFFF0000);//-65536;
vtx_state[0] = ((float)x) / SCALE_IV;
@@ -1927,9 +1927,9 @@ namespace LibNDSFormats.NSBMD {
xz = Utils.Read4BytesAsInt32(polydata, commandptr);
commandptr += 4;
x = sign((xz >> 0) & 0xFFFF, 16);
x = Sign((xz >> 0) & 0xFFFF, 16);
// if ((x & 0x8000) != 0) x |= unchecked((int)0xFFFF0000);//-65536;
z = sign((xz >> 16) & 0xFFFF, 16);
z = Sign((xz >> 16) & 0xFFFF, 16);
// if ((z & 0x8000) != 0) z |= unchecked((int)0xFFFF0000);//-65536;
vtx_state[0] = ((float)x) / SCALE_IV;
@@ -1986,9 +1986,9 @@ namespace LibNDSFormats.NSBMD {
yz = Utils.Read4BytesAsInt32(polydata, commandptr);
commandptr += 4;
y = sign((yz >> 0) & 0xFFFF, 16);
y = Sign((yz >> 0) & 0xFFFF, 16);
//if ((y & 0x8000) != 0) y |= unchecked((int)0xFFFF0000);//-65536;
z = sign((yz >> 16) & 0xFFFF, 16);
z = Sign((yz >> 16) & 0xFFFF, 16);
//if ((z & 0x8000) != 0) z |= unchecked((int)0xFFFF0000);//-65536;
vtx_state[1] = ((float)y) / SCALE_IV;
@@ -2047,11 +2047,11 @@ namespace LibNDSFormats.NSBMD {
xyz = Utils.Read4BytesAsInt32(polydata, commandptr);
commandptr += 4;
x = sign((xyz >> 0) & 0x3FF, 10);
x = Sign((xyz >> 0) & 0x3FF, 10);
//if ((x & 0x200) != 0) x |= unchecked((int)0xFFFFFC00);//-1024;
y = sign((xyz >> 10) & 0x3FF, 10);
y = Sign((xyz >> 10) & 0x3FF, 10);
//if ((y & 0x200) != 0) y |= unchecked((int)0xFFFFFC00);
z = sign((xyz >> 20) & 0x3FF, 10);
z = Sign((xyz >> 20) & 0x3FF, 10);
//if ((z & 0x200) != 0) z |= unchecked((int)0xFFFFFC00);
@@ -2241,7 +2241,7 @@ namespace LibNDSFormats.NSBMD {
}
}
}
public static int sign(int data, int size) {
public static int Sign(int data, int size) {
if ((data & 1 << size - 1) != 0)
data |= -1 << size;
return data;
@@ -2609,7 +2609,7 @@ namespace LibNDSFormats.NSBMD {
index += 4;
num13 = Utils.Read4BytesAsInt32(polydata, index);
index += 4;
CurrentMatrix.translate((((float)sign(num11, 0x20)) / 4096f) / this.Model.modelScale, (((float)sign(num12, 0x20)) / 4096f) / this.Model.modelScale, (((float)sign(num13, 0x20)) / 4096f) / this.Model.modelScale);
CurrentMatrix.translate((((float)Sign(num11, 0x20)) / 4096f) / this.Model.modelScale, (((float)Sign(num12, 0x20)) / 4096f) / this.Model.modelScale, (((float)Sign(num13, 0x20)) / 4096f) / this.Model.modelScale);
continue;
}
case 0x20: {
@@ -2660,11 +2660,11 @@ namespace LibNDSFormats.NSBMD {
case 0x23: {
int num25 = Utils.Read4BytesAsInt32(polydata, index);
index += 4;
num11 = sign(num25 & 0xffff, 0x10);
num12 = sign((num25 >> 0x10) & 0xffff, 0x10);
num11 = Sign(num25 & 0xffff, 0x10);
num12 = Sign((num25 >> 0x10) & 0xffff, 0x10);
num25 = Utils.Read4BytesAsInt32(polydata, index);
index += 4;
num13 = sign(num25 & 0xffff, 0x10);
num13 = Sign(num25 & 0xffff, 0x10);
v[0] = ((float)num11) / 4096f;
v[1] = ((float)num12) / 4096f;
v[2] = ((float)num13) / 4096f;
@@ -2680,9 +2680,9 @@ namespace LibNDSFormats.NSBMD {
case 0x24:
num26 = Utils.Read4BytesAsInt32(polydata, index);
index += 4;
num11 = sign(num26 & 0x3ff, 10);
num12 = sign((num26 >> 10) & 0x3ff, 10);
num13 = sign((num26 >> 20) & 0x3ff, 10);
num11 = Sign(num26 & 0x3ff, 10);
num12 = Sign((num26 >> 10) & 0x3ff, 10);
num13 = Sign((num26 >> 20) & 0x3ff, 10);
v[0] = ((float)num11) / 64f;
v[1] = ((float)num12) / 64f;
v[2] = ((float)num13) / 64f;
@@ -2698,8 +2698,8 @@ namespace LibNDSFormats.NSBMD {
case 0x25: {
int num27 = Utils.Read4BytesAsInt32(polydata, index);
index += 4;
num11 = sign(num27 & 0xffff, 0x10);
num12 = sign((num27 >> 0x10) & 0xffff, 0x10);
num11 = Sign(num27 & 0xffff, 0x10);
num12 = Sign((num27 >> 0x10) & 0xffff, 0x10);
v[0] = ((float)num11) / 4096f;
v[1] = ((float)num12) / 4096f;
if (stackID == -1) {
@@ -2714,8 +2714,8 @@ namespace LibNDSFormats.NSBMD {
case 0x26: {
int num28 = Utils.Read4BytesAsInt32(polydata, index);
index += 4;
num11 = sign(num28 & 0xffff, 0x10);
num13 = sign((num28 >> 0x10) & 0xffff, 0x10);
num11 = Sign(num28 & 0xffff, 0x10);
num13 = Sign((num28 >> 0x10) & 0xffff, 0x10);
v[0] = ((float)num11) / 4096f;
v[2] = ((float)num13) / 4096f;
if (stackID == -1) {
@@ -2730,8 +2730,8 @@ namespace LibNDSFormats.NSBMD {
case 0x27: {
int num29 = Utils.Read4BytesAsInt32(polydata, index);
index += 4;
num12 = sign(num29 & 0xffff, 0x10);
num13 = sign((num29 >> 0x10) & 0xffff, 0x10);
num12 = Sign(num29 & 0xffff, 0x10);
num13 = Sign((num29 >> 0x10) & 0xffff, 0x10);
v[1] = ((float)num12) / 4096f;
v[2] = ((float)num13) / 4096f;
if (stackID == -1) {
@@ -2746,9 +2746,9 @@ namespace LibNDSFormats.NSBMD {
case 40:
num26 = Utils.Read4BytesAsInt32(polydata, index);
index += 4;
num11 = sign(num26 & 0x3ff, 10);
num12 = sign((num26 >> 10) & 0x3ff, 10);
num13 = sign((num26 >> 20) & 0x3ff, 10);
num11 = Sign(num26 & 0x3ff, 10);
num12 = Sign((num26 >> 10) & 0x3ff, 10);
num13 = Sign((num26 >> 20) & 0x3ff, 10);
v[0] += ((float)num11) / 4096f;
v[1] += ((float)num12) / 4096f;
v[2] += ((float)num13) / 4096f;

View File

@@ -21,8 +21,7 @@ using System.Text;
using System.Drawing;
using System.Windows.Forms;
namespace NSMBe4
{
namespace NSMBe4 {
/**
* This is the core of all the image importing.
* Takes one or more RGB bitmaps and outputs:
@@ -34,8 +33,7 @@ namespace NSMBe4
* ~Dirbaio
*/
public class ImageIndexer
{
public class ImageIndexer {
private List<Box> boxes;
private Dictionary<MultiColor, int> freqTable;
private Dictionary<MultiColor, byte> colorTable;
@@ -48,17 +46,14 @@ namespace NSMBe4
public Byte[,] imageData;
public ImageIndexer(List<Bitmap> bl, bool useAlpha)
: this(bl, 256, useAlpha, 0)
{
: this(bl, 256, useAlpha, 0) {
}
public ImageIndexer(List<Bitmap> bl)
: this(bl, 256, true, 0)
{
: this(bl, 256, true, 0) {
}
public ImageIndexer(List<Bitmap> bl, int paletteCount, bool useAlpha, int transpCol)
{
public ImageIndexer(List<Bitmap> bl, int paletteCount, bool useAlpha, int transpCol) {
this.bl = bl;
this.paletteCount = paletteCount;
this.useAlpha = useAlpha;
@@ -71,19 +66,16 @@ namespace NSMBe4
//Quick check just in case...
width = bl[0].Width;
height = bl[0].Height;
foreach (Bitmap b in bl)
{
foreach (Bitmap b in bl) {
if (b.Width != width || b.Height != height)
throw new Exception("Not all images have the same size!!");
}
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
for (int y = 0; y < height; y++) {
MultiColor c = new MultiColor(boxColorCount);
for (int i = 0; i < bl.Count; i++)
{
for (int i = 0; i < bl.Count; i++) {
NSMBe4.NSBMD.ImageTexeler.LockBitmap iii = new NSBMD.ImageTexeler.LockBitmap(bl[i]);
iii.LockBits();
c.setColor(i, iii.GetPixel(x, y));
@@ -104,19 +96,15 @@ namespace NSMBe4
Dictionary<MultiColor, int> newFreqTable = new Dictionary<MultiColor, int>();
foreach (MultiColor c in freqTable.Keys)
{
if (!c.deleteFlag)
{
foreach (MultiColor c in freqTable.Keys) {
if (!c.deleteFlag) {
int cnt = freqTable[c];
foreach (MultiColor c2 in freqTable.Keys)
{
foreach (MultiColor c2 in freqTable.Keys) {
if (c2 == null) continue;
if (c2.deleteFlag) continue;
if (c2 == c) continue;
if (c.diff(c2) == 0)
{
if (c.diff(c2) == 0) {
cnt += freqTable[c2];
c.merge(c2);
c2.deleteFlag = true;
@@ -139,8 +127,7 @@ namespace NSMBe4
boxes = new List<Box>();
boxes.Add(startBox);
while (boxes.Count < (useAlpha ? paletteCount - 1 : paletteCount))
{
while (boxes.Count < (useAlpha ? paletteCount - 1 : paletteCount)) {
Console.Out.WriteLine(boxes.Count);
Box bo = getDominantBox();
if (bo == null)
@@ -157,13 +144,11 @@ namespace NSMBe4
//NOW CREATE THE PALETTE COLORS
palettes = new Color[bl.Count][];
for (int i = 0; i < bl.Count; i++)
{
for (int i = 0; i < bl.Count; i++) {
palettes[i] = new Color[paletteCount];
for (int j = useAlpha ? 1 : 0; j < paletteCount; j++)
{
for (int j = useAlpha ? 1 : 0; j < paletteCount; j++) {
if ((useAlpha ? j : j + 1) > boxes.Count)
palettes[i][j] = palettes[i][j-1];//Color.Fuchsia;
palettes[i][j] = palettes[i][j - 1];//Color.Fuchsia;
else
palettes[i][j] = boxes[useAlpha ? j - 1 : j].center().getColor(i);
// Console.Out.WriteLine(i + ": " + boxes[i] + ": "+ palette[i]);
@@ -180,13 +165,10 @@ namespace NSMBe4
//NOW INDEX THE WHOLE IMAGES
imageData = new byte[width, height];
for (int x = 0; x < width; x++)
{
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
MultiColor c = new MultiColor(boxColorCount);
for (int i = 0; i < bl.Count; i++)
{
for (int i = 0; i < bl.Count; i++) {
NSMBe4.NSBMD.ImageTexeler.LockBitmap iii = new NSBMD.ImageTexeler.LockBitmap(bl[i]);
iii.LockBits();
c.setColor(i, iii.GetPixel(x, y));
@@ -211,8 +193,7 @@ namespace NSMBe4
//PUBLIC DATA-RETRIEVING FUNCTIONS
public byte[] getTiledImageData()
{
public byte[] getTiledImageData() {
byte[] palettedImage = new byte[width * height];
int tileCount = width * height / 64;
@@ -220,8 +201,7 @@ namespace NSMBe4
for (int t = 0; t < tileCount; t++)
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++)
{
for (int x = 0; x < 8; x++) {
int tx = (t % tileWidth) * 8;
int ty = (int)(t / tileWidth) * 8;
palettedImage[t * 64 + y * 8 + x] =
@@ -229,8 +209,7 @@ namespace NSMBe4
}
return palettedImage;
}
public byte[] getTiledImageDataPart(int px, int py, int ptx, int pty)
{
public byte[] getTiledImageDataPart(int px, int py, int ptx, int pty) {
byte[] palettedImage = new byte[ptx * pty];
int tileCount = ptx * pty / 64;
@@ -238,8 +217,7 @@ namespace NSMBe4
for (int t = 0; t < tileCount; t++)
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++)
{
for (int x = 0; x < 8; x++) {
int tx = (t % tileWidth) * 8;
int ty = (int)(t / tileWidth) * 8;
palettedImage[t * 64 + y * 8 + x] =
@@ -248,12 +226,10 @@ namespace NSMBe4
return palettedImage;
}
public Bitmap previewImage(int i)
{
public Bitmap previewImage(int i) {
Bitmap b = new Bitmap(width, height);
for (int x = 0; x < width; x++)
for (int y = 0; y < height; y++)
{
for (int y = 0; y < height; y++) {
b.SetPixel(x, y, palettes[i][imageData[x, y]]);
}
return b;
@@ -264,19 +240,15 @@ namespace NSMBe4
//ALGORITHM CORE
private byte closestMultiColor(MultiColor mc)
{
private byte closestMultiColor(MultiColor mc) {
if (mc.allTransparent()) return 0;
else
{
else {
int best = -1;
float bestd = float.PositiveInfinity;
for (int i = 0; i < multiPalette.Length; i++)
{
for (int i = 0; i < multiPalette.Length; i++) {
if (multiPalette[i] == null) continue;
float d = mc.diff(multiPalette[i]);
if (d < bestd || best == -1)
{
if (d < bestd || best == -1) {
best = i;
bestd = d;
}
@@ -285,16 +257,13 @@ namespace NSMBe4
}
}
private void split(Box b)
{
private void split(Box b) {
byte dim = b.dominantDimensionNum(freqTable); //0, 1, 2 = r, g, b
List<byteint> values = new List<byteint>();
int total = 0;
foreach (MultiColor c in freqTable.Keys)
if (b.inside(c))
{
if (!c.transp[dim])
{
if (b.inside(c)) {
if (!c.transp[dim]) {
values.Add(new byteint(c.data[dim], freqTable[c]));
total += freqTable[c];
}
@@ -318,13 +287,11 @@ namespace NSMBe4
// Console.Out.WriteLine(b + " " + nb);
}
private byte median(List<byteint> values, int total)
{
private byte median(List<byteint> values, int total) {
//Naive median algorithm
//Binary search would be better?
int acum = 0;
foreach (byteint val in values)
{
foreach (byteint val in values) {
acum += val.i;
if (acum * 2 > total)
return val.b;
@@ -341,16 +308,13 @@ namespace NSMBe4
throw new Exception("Bad, bad, bad!");
}
private Box getDominantBox()
{
private Box getDominantBox() {
Box best = null;
int bestDim = 0;
foreach (Box b in boxes)
{
foreach (Box b in boxes) {
int dim = b.dominantDimension(freqTable);
if ((dim > bestDim || best == null) && b.canSplit(freqTable))
{
if ((dim > bestDim || best == null) && b.canSplit(freqTable)) {
bestDim = dim;
best = b;
}
@@ -358,25 +322,19 @@ namespace NSMBe4
return best;
}
private Box shrinkBox(Box b)
{
private Box shrinkBox(Box b) {
byte[] min = (byte[])b.min.Clone();
byte[] max = (byte[])b.max.Clone();
bool[] def = new bool[b.max.Length];
foreach (MultiColor c in freqTable.Keys)
if (b.inside(c))
{
for (int i = 0; i < c.data.Length; i++)
{
if (b.inside(c)) {
for (int i = 0; i < c.data.Length; i++) {
if (!c.transp[i])
if (def[i])
{
if (def[i]) {
if (min[i] > c.data[i]) min[i] = c.data[i];
if (max[i] < c.data[i]) max[i] = c.data[i];
}
else
{
} else {
min[i] = c.data[i];
max[i] = c.data[i];
def[i] = true;
@@ -387,8 +345,7 @@ namespace NSMBe4
return new Box(min, max);
}
public static byte reduce(int c)
{
public static byte reduce(int c) {
return (byte)((c >> 3) << 3);
}
@@ -397,77 +354,63 @@ namespace NSMBe4
//HELPER CLASSES
private class MultiColor
{
private class MultiColor {
public byte[] data;
public bool[] transp;
public bool deleteFlag;
public MultiColor(int count)
{
public MultiColor(int count) {
data = new byte[count];
transp = new bool[count];
deleteFlag = false;
}
public void setColor(int i, Color c)
{
public void setColor(int i, Color c) {
transp[i * 3 + 0] = c.A < 128;
transp[i * 3 + 1] = c.A < 128;
transp[i * 3 + 2] = c.A < 128;
if (c.A >= 128)
{
if (c.A >= 128) {
data[i * 3 + 0] = reduce(c.R);
data[i * 3 + 1] = reduce(c.G);
data[i * 3 + 2] = reduce(c.B);
}
else
{
} else {
data[i * 3 + 0] = 0;
data[i * 3 + 1] = 255;
data[i * 3 + 2] = 255;
}
}
public void merge(MultiColor b)
{
public void merge(MultiColor b) {
for (int i = 0; i < data.Length; i++)
if (transp[i])
{
if (transp[i]) {
transp[i] = b.transp[i];
data[i] = b.data[i];
}
calcHash();
}
public Color getColor(int i)
{
public Color getColor(int i) {
if (transp[i * 3]) return Color.Transparent;
return Color.FromArgb(data[i * 3], data[i * 3 + 1], data[i * 3 + 2]);
}
public bool allTransparent()
{
public bool allTransparent() {
for (int i = 0; i < transp.Length; i += 3)
if (!transp[i]) return false;
return true;
}
public bool someTransparent()
{
public bool someTransparent() {
for (int i = 0; i < transp.Length; i += 3)
if (transp[i]) return true;
return false;
}
private int thehash;
public void calcHash()
{
unchecked
{
public void calcHash() {
unchecked {
const int p = 16777619;
int hash = (int)2166136261;
for (int i = 0; i < data.Length; i++)
{
for (int i = 0; i < data.Length; i++) {
hash = (hash ^ data[i]) * p;
if (transp[i]) hash++;
}
@@ -482,84 +425,68 @@ namespace NSMBe4
}
}
public override int GetHashCode()
{
public override int GetHashCode() {
return thehash;
}
public override bool Equals(object obj)
{
if (obj is MultiColor)
{
public override bool Equals(object obj) {
if (obj is MultiColor) {
MultiColor c = obj as MultiColor;
if (data.Length != c.data.Length)
return false;
for (int i = 0; i < data.Length; i++)
{
for (int i = 0; i < data.Length; i++) {
if (data[i] != c.data[i]) return false;
if (transp[i] != c.transp[i]) return false;
}
return true;
}
else return false;
} else return false;
}
public float diff(MultiColor b)
{
public float diff(MultiColor b) {
float res = 0;
for (int i = 0; i < data.Length; i++)
if (!transp[i] && !b.transp[i])
{
if (!transp[i] && !b.transp[i]) {
float d = data[i] - b.data[i];
res += d * d;
}
return res;
}
internal void removeAllTransparent()
{
internal void removeAllTransparent() {
for (int i = 0; i < data.Length; i++)
if (transp[i])
{
if (transp[i]) {
transp[i] = false;
data[i] = 0;
}
}
}
private class Box
{
private class Box {
public byte[] min, max;
private bool splittable = false;
private bool splittablecached = false;
public Box(byte[] min, byte[] max)
{
public Box(byte[] min, byte[] max) {
this.min = min;
this.max = max;
}
public Box(int count)
{
public Box(int count) {
min = new byte[count];
max = new byte[count];
for (int i = 0; i < count; i++)
{
for (int i = 0; i < count; i++) {
min[i] = 0;
max[i] = 255;
}
}
public Box(Box b)
{
public Box(Box b) {
this.min = (byte[])b.min.Clone();
this.max = (byte[])b.max.Clone();
}
public bool inside(MultiColor c)
{
for (int i = 0; i < min.Length; i++)
{
public bool inside(MultiColor c) {
for (int i = 0; i < min.Length; i++) {
if (c.transp[i]) continue;
if (c.data[i] < min[i]) return false;
if (c.data[i] > max[i]) return false;
@@ -567,22 +494,18 @@ namespace NSMBe4
return true;
}
public int dominantDimension(Dictionary<MultiColor, int> freqTable)
{
public int dominantDimension(Dictionary<MultiColor, int> freqTable) {
int d = dominantDimensionNum(freqTable);
if (d == 255) return 0;
return max[d] - min[d];
}
public byte dominantDimensionNum(Dictionary<MultiColor, int> freqTable)
{
public byte dominantDimensionNum(Dictionary<MultiColor, int> freqTable) {
int d = -1;
int dl = -1;
for (int i = 0; i < min.Length; i++)
{
for (int i = 0; i < min.Length; i++) {
int il = max[i] - min[i];
if (il > dl && canSplitInDim(i, freqTable))
{
if (il > dl && canSplitInDim(i, freqTable)) {
dl = il;
d = i;
}
@@ -590,35 +513,27 @@ namespace NSMBe4
return (byte)d;
}
public void setDimMin(byte d, byte a)
{
public void setDimMin(byte d, byte a) {
min[d] = a;
splittablecached = false;
}
public void setDimMax(byte d, byte a)
{
public void setDimMax(byte d, byte a) {
max[d] = a;
splittablecached = false;
}
public bool canSplitInDim(int i, Dictionary<MultiColor, int> freqTable)
{
public bool canSplitInDim(int i, Dictionary<MultiColor, int> freqTable) {
byte data = 0;
bool seen = false;
foreach (MultiColor c in freqTable.Keys)
{
if (inside(c))
{
if (!c.transp[i])
{
foreach (MultiColor c in freqTable.Keys) {
if (inside(c)) {
if (!c.transp[i]) {
if (!seen) //First val we see
{
seen = true;
data = c.data[i];
}
else
{
} else {
if (data != c.data[i])
return true;
}
@@ -628,38 +543,29 @@ namespace NSMBe4
return false;
}
public bool canSplit(Dictionary<MultiColor, int> freqTable)
{
public bool canSplit(Dictionary<MultiColor, int> freqTable) {
if (splittablecached) return splittable;
else
{
else {
splittablecached = true;
splittable = canSplit2(freqTable);
return splittable;
}
}
public bool canSplit2(Dictionary<MultiColor, int> freqTable)
{
public bool canSplit2(Dictionary<MultiColor, int> freqTable) {
//Whoa... This gets complicated if I have to
//take into acount the "don't care" of transparent colors...
byte[] data = new byte[min.Length];
bool[] seen = new bool[min.Length];
foreach (MultiColor c in freqTable.Keys)
{
if (inside(c))
{
for (int i = 0; i < min.Length; i++)
{
if (!c.transp[i])
{
foreach (MultiColor c in freqTable.Keys) {
if (inside(c)) {
for (int i = 0; i < min.Length; i++) {
if (!c.transp[i]) {
if (!seen[i]) //First val we see
{
seen[i] = true;
data[i] = c.data[i];
}
else
{
} else {
if (data[i] != c.data[i])
return true;
}
@@ -670,22 +576,19 @@ namespace NSMBe4
return false;
}
public MultiColor center()
{
public MultiColor center() {
MultiColor res = new MultiColor(min.Length);
for (int i = 0; i < min.Length; i++)
res.data[i] = (byte)((min[i] + max[i]) / 2);
return res;
}
public override string ToString()
{
public override string ToString() {
return arr2str(min) + " - " + arr2str(max);
// return "("+r1+"-"+r2+","+g1+"-"+g2+","+b1+"-"+b2+")";
}
private string arr2str(byte[] a)
{
private string arr2str(byte[] a) {
string s = "(" + a[0];
for (int i = 1; i < a.Length; i++)
s += ", " + a[i];
@@ -693,33 +596,27 @@ namespace NSMBe4
}
}
private class byteint : IComparable
{
private class byteint : IComparable {
public byte b;
public int i;
public byteint(byte b, int i)
{
public byteint(byte b, int i) {
this.b = b;
this.i = i;
}
public int CompareTo(object obj)
{
public int CompareTo(object obj) {
byteint bi = obj as byteint;
return b.CompareTo(bi.b);
}
public static bool operator <(byteint a, byteint b)
{
public static bool operator <(byteint a, byteint b) {
return a.b < b.b;
}
public static bool operator >(byteint a, byteint b)
{
public static bool operator >(byteint a, byteint b) {
return a.b > b.b;
}
public override string ToString()
{
public override string ToString() {
return "(" + b + ", " + i + ")";
}
}
@@ -729,18 +626,15 @@ namespace NSMBe4
//GENERAL PURPOSE FUNCTIONS
public static Color[] createPaletteForImage(Bitmap b)
{
public static Color[] createPaletteForImage(Bitmap b) {
return createPaletteForImage(b, 256, false);
}
public static Color[] createPaletteForImage(Bitmap b, int palLen)
{
public static Color[] createPaletteForImage(Bitmap b, int palLen) {
return createPaletteForImage(b, palLen, false);
}
public static Color[] createPaletteForImage(Bitmap b, int palLen, bool alpha)
{
public static Color[] createPaletteForImage(Bitmap b, int palLen, bool alpha) {
List<Bitmap> bl = new List<Bitmap>();
bl.Add(b);
@@ -749,8 +643,7 @@ namespace NSMBe4
return i.palettes[0];
}
public static byte[] indexImageWithPalette(Bitmap b, Color[] palette)
{
public static byte[] indexImageWithPalette(Bitmap b, Color[] palette) {
//More efficient now.
byte[] palettedImage = new byte[b.Width * b.Height];
int tileCount = b.Width * b.Height / 64;
@@ -758,26 +651,22 @@ namespace NSMBe4
for (int t = 0; t < tileCount; t++)
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++)
{
for (int x = 0; x < 8; x++) {
int tx = (t % tileWidth) * 8;
int ty = (int)(t / tileWidth) * 8;
Color c = b.GetPixel(tx + x, ty + y);
if (c.A != 0)
{
if (c.A != 0) {
c = Color.FromArgb(c.R, c.G, c.B);
palettedImage[t * 64 + y * 8 + x] = closest(c, palette);
}
else
} else
palettedImage[t * 64 + y * 8 + x] = 0;
}
return palettedImage;
}
public static byte[] indexImageWithPalette2(Bitmap b, Color[] palette)
{
public static byte[] indexImageWithPalette2(Bitmap b, Color[] palette) {
//More efficient now.
byte[] palettedImage = new byte[b.Width * b.Height];
int tileCount = b.Width * b.Height / 64;
@@ -785,26 +674,22 @@ namespace NSMBe4
for (int t = 0; t < tileCount; t++)
for (int y = 0; y < 8; y++)
for (int x = 0; x < 8; x++)
{
for (int x = 0; x < 8; x++) {
int tx = (t % tileWidth) * 8;
int ty = (int)(t / tileWidth) * 8;
Color c = b.GetPixel(tx + x, ty + y);
if (c.A != 0)
{
if (c.A != 0) {
c = Color.FromArgb(c.R, c.G, c.B);
palettedImage[t * 64 + y * 8 + x] = closest(c, palette);
}
else
} else
palettedImage[t * 64 + y * 8 + x] = 0;
}
return palettedImage;
}
public static float colorDifference(Color a, Color b)
{
public static float colorDifference(Color a, Color b) {
if (a.A != b.A) return float.MaxValue;
float res = 0;
@@ -818,8 +703,7 @@ namespace NSMBe4
return res;
}
public static float colorDifferenceWithoutAlpha(Color a, Color b)
{
public static float colorDifferenceWithoutAlpha(Color a, Color b) {
int res = 0;
res += (a.R - b.R) * (a.R - b.R) / 40;
res += (a.G - b.G) * (a.G - b.G) / 40;
@@ -832,15 +716,12 @@ namespace NSMBe4
}
public static byte closest(Color c, Color[] palette)
{
public static byte closest(Color c, Color[] palette) {
int best = 0;
float bestDif = colorDifference(c, palette[0]);
for (int i = 0; i < palette.Length; i++)
{
for (int i = 0; i < palette.Length; i++) {
float dif = colorDifference(c, palette[i]);
if (dif < bestDif)
{
if (dif < bestDif) {
bestDif = dif;
best = i;
}