/* ClosestColor traverses the color cube tree at a * particular node and determines which colormap entry * best represents the input color. */ void closestColor(int red, int green, int blue, Search search) { if (nchild != 0) { for (int id = 0; id < 8; id++) { if (child[id] != null) { child[id].closestColor(red, green, blue, search); } } } if (unique != 0) { int color = cube.colormap[color_number]; int distance = distance(color, red, green, blue); if (distance < search.distance) { search.distance = distance; search.color_number = color_number; } } }
/* * Procedure assignment generates the output image from the * pruned tree. The output image consists of two parts: (1) A * color map, which is an array of color descriptions (RGB * triples) for each color present in the output image; (2) A * pixel array, which represents each pixel as an index into * the color map array. * * First, the assignment phase makes one pass over the pruned * color description tree to establish the image's color map. * For each node with n2 > 0, it divides Sr, Sg, and Sb by n2. * This produces the mean color of all pixels that classify no * lower than this node. Each of these colors becomes an entry * in the color map. * * Finally, the assignment phase reclassifies each pixel in * the pruned tree to identify the deepest node containing the * pixel's color. The pixel's value in the pixel array becomes * the index of this node's mean color in the color map. */ void assignment() { colormap = new int[colors]; colors = 0; root.colormap(); int pixels[][] = this.pixels; int width = pixels.length; int height = pixels[0].length; Search search = new Search(); int transPad = hasTrans ? 1 : 0; // convert to indexed color for (int x = width; x-- > 0; ) { for (int y = height; y-- > 0; ) { int pixel = pixels[x][y]; int alpha = (pixel >> 24) & 0xFF; if (alpha != 255) { pixels[x][y] = 0; // transparent continue; } int red = (pixel >> 16) & 0xFF; int green = (pixel >> 8) & 0xFF; int blue = (pixel >> 0) & 0xFF; // walk the tree to find the cube containing that color Node node = root; for (; ; ) { int id = (((red > node.mid_red ? 1 : 0) << 0) | ((green > node.mid_green ? 1 : 0) << 1) | ((blue > node.mid_blue ? 1 : 0) << 2)); if (node.child[id] == null) { break; } node = node.child[id]; } if (QUICK) { // if QUICK is set, just use that // node. Strictly speaking, this isn't // necessarily best match. pixels[x][y] = node.color_number + transPad; } else { // Find the closest color. search.distance = Integer.MAX_VALUE; node.parent.closestColor(red, green, blue, search); pixels[x][y] = search.color_number + transPad; } } } // expand the colormap by one to account for the transparent if (hasTrans) { int[] newcmap = new int[colormap.length + 1]; System.arraycopy(colormap, 0, newcmap, 1, colormap.length); colormap = newcmap; } }