public void convert_4x4texel_b(byte[] tex, int width, int height, byte[] data, Color[] pal, ImageTexeler.LockBitmap rgbaOut) { var list1 = new List <uint>(); for (int i = 0; i < (tex.Length + 1) / 4; ++i) { list1.Add(LibNDSFormats.Utils.Read4BytesAsUInt32(tex, i * 4)); } var list2 = new List <UInt16>(); for (int i = 0; i < (data.Length + 1) / 2; ++i) { list2.Add(LibNDSFormats.Utils.Read2BytesAsUInt16(data, i * 2)); } var b = convert_4x4texel(list1.ToArray(), width, height, list2.ToArray(), pal, rgbaOut); }
public ImageIndexer(List <Bitmap> bl, int paletteCount, bool useAlpha, int transpCol) { this.bl = bl; this.paletteCount = paletteCount; this.useAlpha = useAlpha; boxColorCount = bl.Count * 3; //COMPUTE FREQUENCY TABLE freqTable = new Dictionary <MultiColor, int>(); //Quick check just in case... width = bl[0].Width; height = bl[0].Height; 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++) { MultiColor c = new MultiColor(boxColorCount); 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)); iii.UnlockBits(); } c.calcHash(); if (!c.allTransparent()) { if (freqTable.ContainsKey(c)) { freqTable[c]++; } else { freqTable[c] = 1; } } } } int ct = 0; foreach (MultiColor c in freqTable.Keys) { if (c.someTransparent()) { ct++; } } Console.Out.WriteLine("Transparent: " + ct); Dictionary <MultiColor, int> newFreqTable = new Dictionary <MultiColor, int>(); foreach (MultiColor c in freqTable.Keys) { if (!c.deleteFlag) { int cnt = freqTable[c]; foreach (MultiColor c2 in freqTable.Keys) { if (c2 == null) { continue; } if (c2.deleteFlag) { continue; } if (c2 == c) { continue; } if (c.diff(c2) == 0) { cnt += freqTable[c2]; c.merge(c2); c2.deleteFlag = true; } } c.deleteFlag = true; c.removeAllTransparent(); newFreqTable.Add(c, cnt); } } freqTable = newFreqTable; ct = 0; foreach (MultiColor c in freqTable.Keys) { if (c.someTransparent()) { ct++; } } Console.Out.WriteLine("Transparent2: " + ct); // NOW CREATE THE PALETTE ZONES Box startBox = shrinkBox(new Box(boxColorCount)); boxes = new List <Box>(); boxes.Add(startBox); while (boxes.Count < (useAlpha ? paletteCount - 1 : paletteCount)) { Console.Out.WriteLine(boxes.Count); Box bo = getDominantBox(); if (bo == null) { break; } split(bo); } multiPalette = new MultiColor[paletteCount]; for (int j = useAlpha ? 1 : 0; j < paletteCount; j++) { if ((useAlpha ? j : j + 1) <= boxes.Count) { multiPalette[j] = boxes[useAlpha ? j - 1 : j].center(); } } //NOW CREATE THE PALETTE COLORS palettes = new Color[bl.Count][]; for (int i = 0; i < bl.Count; i++) { palettes[i] = new Color[paletteCount]; 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; } else { palettes[i][j] = boxes[useAlpha ? j - 1 : j].center().getColor(i); } // Console.Out.WriteLine(i + ": " + boxes[i] + ": "+ palette[i]); } if (useAlpha) { palettes[i][0] = Color.Transparent; } } //NOW MAP ORIGINAL COLORS TO PALETTE ENTRIES colorTable = new Dictionary <MultiColor, byte>(); foreach (MultiColor c in freqTable.Keys) { colorTable[c] = closestMultiColor(c); } //NOW INDEX THE WHOLE IMAGES imageData = new byte[width, height]; 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++) { NSMBe4.NSBMD.ImageTexeler.LockBitmap iii = new NSBMD.ImageTexeler.LockBitmap(bl[i]); iii.LockBits(); c.setColor(i, iii.GetPixel(x, y)); iii.UnlockBits(); } c.calcHash(); if (c.allTransparent()) { imageData[x, y] = (byte)transpCol; } else { imageData[x, y] = closestMultiColor(c); } } } Console.Out.WriteLine("DONE"); /* * * }*/ }
public bool convert_4x4texel(uint[] tex, int width, int height, UInt16[] data, Color[] pal, ImageTexeler.LockBitmap rgbaOut) { int w = width / 4; int h = height / 4; // traverse 'w x h blocks' of 4x4-texel for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int index = y * w + x; UInt32 t = tex[index]; UInt16 d = data[index]; UInt16 addr = (ushort)(d & 0x3fff); UInt16 mode = (ushort)((d >> 14) & 3); // traverse every texel in the 4x4 texels for (int r = 0; r < 4; r++) { for (int c = 0; c < 4; c++) { int texel = (int)((t >> ((r * 4 + c) * 2)) & 3); Color pixel = rgbaOut.GetPixel((x * 4 + c), (y * 4 + r)); switch (mode) { case 0: pixel = pal[(addr << 1) + texel]; if (texel == 3) { pixel = Color.Transparent; // make it transparent, alpha = 0 } break; case 2: pixel = pal[(addr << 1) + texel]; break; case 1: switch (texel) { case 0: case 1: pixel = pal[(addr << 1) + texel]; break; case 2: byte R = (byte)((pal[(addr << 1)].R + pal[(addr << 1) + 1].R) / 2L); byte G = (byte)((pal[(addr << 1)].G + pal[(addr << 1) + 1].G) / 2L); byte B = (byte)((pal[(addr << 1)].B + pal[(addr << 1) + 1].B) / 2L); byte A = 0xff; pixel = Color.FromArgb(A, R, G, B); break; case 3: pixel = Color.Transparent; // make it transparent, alpha = 0 break; } break; case 3: switch (texel) { case 0: case 1: pixel = pal[(addr << 1) + texel]; break; case 2: { byte R = (byte)((pal[(addr << 1)].R * 5L + pal[(addr << 1) + 1].R * 3L) / 8); byte G = (byte)((pal[(addr << 1)].G * 5L + pal[(addr << 1) + 1].G * 3L) / 8); byte B = (byte)((pal[(addr << 1)].B * 5L + pal[(addr << 1) + 1].B * 3L) / 8); byte A = 0xff; pixel = Color.FromArgb(A, R, G, B); break; } case 3: { byte R = (byte)((pal[(addr << 1)].R * 3L + pal[(addr << 1) + 1].R * 5L) / 8); byte G = (byte)((pal[(addr << 1)].G * 3L + pal[(addr << 1) + 1].G * 5L) / 8); byte B = (byte)((pal[(addr << 1)].B * 3L + pal[(addr << 1) + 1].B * 5L) / 8); byte A = 0xff; pixel = Color.FromArgb(A, R, G, B); break; } } break; } rgbaOut.SetPixel((x * 4 + c), (y * 4 + r), pixel); //rgbaOut[(y * 4 + r) * width + (x * 4 + c)] = pixel; } } } } return(true); }