GR.Image.MemoryImage Assignment(CubeInfo cube_info, GR.Image.IImage pCD) { var format = GR.Drawing.PixelFormat.Format8bppIndexed; if (m_Colors <= 2) { format = GR.Drawing.PixelFormat.Format1bppIndexed; } /* * else if ( m_Colors <= 4 ) * { * format = System.Drawing.Imaging.PixelFormat.Format2bppIndexed; * }*/ else if (m_Colors <= 16) { format = GR.Drawing.PixelFormat.Format4bppIndexed; } var pImage = new GR.Image.MemoryImage(pCD.Width, pCD.Height, format); var pal = new RetroDevStudio.Palette(m_Colors); byte index; int count, i; NodeInfo node_info; uint dither, id; // Allocate image colormap. cube_info.colormap = new PixelPacket[256]; cube_info.colors = 0; DefineColormap(cube_info, cube_info.root); // Create a reduced color image. dither = cube_info.quantize_info.dither; for (int y = 0; y < pCD.Height; y++) { //indexes=GetIndexes(image); for (int x = 0; x < pCD.Width; x += count) { // Identify the deepest node containing the pixel's color. count = 1; uint pixel = pCD.GetPixel(x, y); int r = (byte)((pixel & 0xff0000) >> 16), g = (byte)((pixel & 0xff00) >> 8), b = (byte)(pixel & 0xff); node_info = cube_info.root; for (index = MaxTreeDepth - 1; (int)index > 0; index--) { id = (uint)(((Downscale(r) >> index) & 0x01) << 2 | ((Downscale(g) >> index) & 0x01) << 1 | ((Downscale(b) >> index) & 0x01)); if ((node_info.census & (1 << (byte)id)) == 0) { break; } node_info = node_info.child[id]; } // Find closest color among siblings and their children. cube_info.color.red = (byte)r; cube_info.color.green = (byte)g; cube_info.color.blue = (byte)b; cube_info.distance = 3.0 * (MaxRGB() + 1) * (MaxRGB() + 1); ClosestColor(cube_info, node_info.parent); index = (byte)cube_info.color_number; for (i = 0; i < count; i++) { if (cube_info.quantize_info.measure_error == 0) { pImage.SetPixel(x, y, index); } } } } for (i = 0; i < cube_info.colors; i++) { pal.ColorValues[i] = (uint)(0xff000000 | (uint)(cube_info.colormap[i].red << 16) | (uint)(cube_info.colormap[i].green << 8) | (uint)cube_info.colormap[i].blue); pImage.SetPaletteColor(i, cube_info.colormap[i].red, cube_info.colormap[i].green, cube_info.colormap[i].blue); } return(pImage); }
bool Classification(CubeInfo cube_info, GR.Image.IImage Image) { double bisect, mid_red, mid_green, mid_blue; int count; NodeInfo node_info; double blue, green, red; uint index, level, id; for (int y = 0; y < Image.Height; ++y) { if (cube_info.nodes > MaxNodes) { // Prune one level if the color tree is too large. PruneLevel(cube_info, cube_info.root); --cube_info.depth; } for (int x = 0; x < Image.Width; x += count) { // Start at the root and descend the color cube tree. count = 1; index = MaxTreeDepth - 1; bisect = (MaxRGB() + 1) / 2.0; mid_red = MaxRGB() / 2.0; mid_green = MaxRGB() / 2.0; mid_blue = MaxRGB() / 2.0; node_info = cube_info.root; uint pixel = Image.GetPixel(x, y); int r = (int)((pixel & 0xff0000) >> 16); int g = (int)((pixel & 0xff00) >> 8); int b = (int)(pixel & 0xff); for (level = 1; level <= cube_info.depth; level++) { bisect *= 0.5; id = (uint)(((Downscale(r) >> (byte)index) & 0x01) << 2 | ((Downscale(g) >> (byte)index) & 0x01) << 1 | ((Downscale(b) >> (byte)index) & 0x01)); mid_red += (id & 4) != 0 ? bisect : -bisect; mid_green += (id & 2) != 0 ? bisect : -bisect; mid_blue += (id & 1) != 0 ? bisect : -bisect; if (node_info.child[id] == null) { // Set colors of new node to contain pixel. node_info.census |= (byte)(1 << (byte)id); node_info.child[id] = GetNodeInfo(cube_info, (byte)id, (byte)level, node_info); if (node_info.child[id] == null) { Debug.Log("this should never happen!"); } if (level == cube_info.depth) { ++cube_info.colors; } } // Approximate the quantization error represented by this node. node_info = node_info.child[id]; red = (double)r - mid_red; green = (double)g - mid_green; blue = (double)b - mid_blue; node_info.quantize_error += count * red * red + count * green * green + count * blue * blue; cube_info.root.quantize_error += node_info.quantize_error; --index; } // Sum RGB for this leaf for later derivation of the mean cube color. node_info.number_unique += count; node_info.total_red += count * r; node_info.total_green += count * g; node_info.total_blue += count * b; } } return(true); }