/** Uses Heckbert's median-cut algorithm to divide the color space defined by "hist" into "maxcubes" cubes. The centroids (average value) of each cube are are used to create a color table. "hist" is then updated to function as an inverse color map that is used to generate an 8-bit image. */ public Image convert(int maxcubes) { ImageProcessor ip = convertToByte(maxcubes); return ip.createImage(); }
void quickSort(int a[], int lo0, int hi0) { // Based on the QuickSort method by James Gosling from Sun's SortDemo applet int lo = lo0; int hi = hi0; int mid, t; if ( hi0 > lo0) { mid = a[ ( lo0 + hi0 ) / 2 ]; while( lo <= hi ) { while( ( lo < hi0 ) && ( a[lo] < mid ) ) ++lo; while( ( hi > lo0 ) && ( a[hi] > mid ) ) --hi; if( lo <= hi ) { t = a[lo]; a[lo] = a[hi]; a[hi] = t; ++lo; --hi; } } if( lo0 < hi ) quickSort( a, lo0, hi ); if( lo < hi0 ) quickSort( a, lo, hi0 ); } }
/** Converts an RGB image to 8-bits indexed color. 'nColors' must be greater than 1 and less than or equal to 256. */ public void convertRGBtoIndexedColor(int nColors) { if (type!=ImagePlus.COLOR_RGB) throw new IllegalArgumentException("Image must be RGB"); if (nColors<2) nColors = 2; if (nColors>256) nColors = 256; // get RGB pixels IJ.showProgress(0.1); IJ.showStatus("Grabbing pixels"); int width = imp.getWidth(); int height = imp.getHeight(); ImageProcessor ip = imp.getProcessor(); ip.snapshot(); int[] pixels = (int[])ip.getPixels(); imp.trimProcessor(); // convert to 8-bits long start = System.currentTimeMillis(); MedianCut mc = new MedianCut(pixels, width, height); ImageProcessor ip2 = mc.convertToByte(nColors); imp.setProcessor(null, ip2); }
Shrink(cube); list[ncubes++] = cube; reorderColors(histPtr, cube.lower, cube.upper, longdim); quickSort(histPtr, cube.lower, cube.upper); restoreColorOrder(histPtr, cube.lower, cube.upper, longdim); cubeA.count = count; cubeA.level = cube.level + 1; Shrink(cubeA); cubeB.count = cube.count - count; cubeB.level = cube.level + 1; Shrink(cubeB); makeInverseMap(hist, ncubes); IJ.showProgress(0.95); return makeImage();
/** Converts an RGB image to 8-bits indexed color. 'nColors' must be greater than 1 and less than or equal to 256. */ public void convertRGBtoIndexedColor(int nColors) { if (type!=ImagePlus.COLOR_RGB) throw new IllegalArgumentException("Image must be RGB"); if (nColors<2) nColors = 2; if (nColors>256) nColors = 256; // get RGB pixels IJ.showProgress(0.1); IJ.showStatus("Grabbing pixels"); int width = imp.getWidth(); int height = imp.getHeight(); ImageProcessor ip = imp.getProcessor(); ip.snapshot(); int[] pixels = (int[])ip.getPixels(); imp.trimProcessor(); // convert to 8-bits long start = System.currentTimeMillis(); MedianCut mc = new MedianCut(pixels, width, height); ImageProcessor ip2 = mc.convertToByte(nColors); imp.setProcessor(null, ip2); }
Shrink(cube); list[ncubes++] = cube; reorderColors(histPtr, cube.lower, cube.upper, longdim); quickSort(histPtr, cube.lower, cube.upper); restoreColorOrder(histPtr, cube.lower, cube.upper, longdim); cubeA.count = count; cubeA.level = cube.level + 1; Shrink(cubeA); cubeB.count = cube.count - count; cubeB.level = cube.level + 1; Shrink(cubeB); makeInverseMap(hist, ncubes); IJ.showProgress(0.95); return makeImage();
/** Converts the stack to 8-bits indexed color. 'nColors' must be greater than 1 and less than or equal to 256. */ public void convertToIndexedColor(int nColors) { if (type!=ImagePlus.COLOR_RGB) throw new IllegalArgumentException("RGB stack required"); ImageStack stack = imp.getStack(); int size = stack.getSize(); ImageProcessor montage = new ColorProcessor(width*size, height); for (int i=0; i<size; i++) montage.insert(stack.getProcessor(i+1), i*width, 0); MedianCut mc = new MedianCut((ColorProcessor)montage); montage = mc.convertToByte(nColors); ImageStack stack2 = new ImageStack(width, height); for (int i=0; i<size; i++) { montage.setRoi(i*width, 0, width, height); stack2.addSlice(null, montage.crop()); } imp.setStack(null, stack2); }
/** Uses Heckbert's median-cut algorithm to divide the color space defined by "hist" into "maxcubes" cubes. The centroids (average value) of each cube are are used to create a color table. "hist" is then updated to function as an inverse color map that is used to generate an 8-bit image. */ public Image convert(int maxcubes) { ImageProcessor ip = convertToByte(maxcubes); return ip.createImage(); }
void quickSort(int a[], int lo0, int hi0) { // Based on the QuickSort method by James Gosling from Sun's SortDemo applet int lo = lo0; int hi = hi0; int mid, t; if ( hi0 > lo0) { mid = a[ ( lo0 + hi0 ) / 2 ]; while( lo <= hi ) { while( ( lo < hi0 ) && ( a[lo] < mid ) ) ++lo; while( ( hi > lo0 ) && ( a[hi] > mid ) ) --hi; if( lo <= hi ) { t = a[lo]; a[lo] = a[hi]; a[hi] = t; ++lo; --hi; } } if( lo0 < hi ) quickSort( a, lo0, hi ); if( lo < hi0 ) quickSort( a, lo, hi0 ); } }
/** Converts the stack to 8-bits indexed color. 'nColors' must be greater than 1 and less than or equal to 256. */ public void convertToIndexedColor(int nColors) { if (type!=ImagePlus.COLOR_RGB) throw new IllegalArgumentException("RGB stack required"); ImageStack stack = imp.getStack(); int size = stack.getSize(); ImageProcessor montage = new ColorProcessor(width*size, height); for (int i=0; i<size; i++) montage.insert(stack.getProcessor(i+1), i*width, 0); MedianCut mc = new MedianCut((ColorProcessor)montage); montage = mc.convertToByte(nColors); ImageStack stack2 = new ImageStack(width, height); for (int i=0; i<size; i++) { montage.setRoi(i*width, 0, width, height); stack2.addSlice(null, montage.crop()); } imp.setStack(null, stack2); }
void Shrink(Cube cube) { // Encloses "cube" with a tight-fitting cube by updating the // (rmin,gmin,bmin) and (rmax,gmax,bmax) members of "cube". int r, g, b; int color; int rmin, rmax, gmin, gmax, bmin, bmax; rmin = 255; rmax = 0; gmin = 255; gmax = 0; bmin = 255; bmax = 0; for (int i=cube.lower; i<=cube.upper; i++) { color = histPtr[i]; r = red(color); g = green(color); b = blue(color); if (r > rmax) rmax = r; if (r < rmin) rmin = r; if (g > gmax) gmax = g; if (g < gmin) gmin = g; if (b > bmax) bmax = b; if (b < bmin) bmin = b; } cube.rmin = rmin; cube.rmax = rmax; cube.gmin = gmin; cube.gmax = gmax; cube.bmin = bmin; cube.bmax = bmax; }
/** Does not respect local transform of the patches, this is intended for confocal stacks. */ public ImagePlus createColor256Copy() { final Rectangle box = patch[0].getBoundingBox(); final int width = box.width; final int height = box.height; Loader loader = patch[0].getProject().getLoader(); patch[0].getProject().getLoader().releaseToFit(4 * patch.length * width * height); // the montage, in RGB final ColorProcessor montage = new ColorProcessor(width*patch.length, height); for (int i=0; i<patch.length; i++) { montage.insert(this.stack.getProcessor(i+1), i*width, 0); } final MedianCut mc = new MedianCut(montage); loader.releaseToFit(patch.length * width * height); ImageProcessor m2 = mc.convertToByte(256); final ImageStack st = new ImageStack(width, height); for (int i=0; i<patch.length; i++) { m2.setRoi(i*width, 0, width, height); loader.releaseToFit(width * height); st.addSlice(null, m2.crop()); } ImagePlus imp = new ImagePlus("color256", st); imp.setCalibration(patch[0].getLayer().getParent().getCalibrationCopy()); //imp.getCalibration().pixelDepth = patch[0].getLayer().getThickness(); return imp; } }
void Shrink(Cube cube) { // Encloses "cube" with a tight-fitting cube by updating the // (rmin,gmin,bmin) and (rmax,gmax,bmax) members of "cube". int r, g, b; int color; int rmin, rmax, gmin, gmax, bmin, bmax; rmin = 255; rmax = 0; gmin = 255; gmax = 0; bmin = 255; bmax = 0; for (int i=cube.lower; i<=cube.upper; i++) { color = histPtr[i]; r = red(color); g = green(color); b = blue(color); if (r > rmax) rmax = r; if (r < rmin) rmin = r; if (g > gmax) gmax = g; if (g < gmin) gmin = g; if (b > bmax) bmax = b; if (b < bmin) bmin = b; } cube.rmin = rmin; cube.rmax = rmax; cube.gmin = gmin; cube.gmax = gmax; cube.bmin = bmin; cube.bmax = bmax; }