4 import java.awt.image.*;
13 static final int MAXCOLORS = 256;
14 static final int HSIZE = 32768;
16 private int[] histPtr;
18 private int[] pixels32;
19 private int width, height;
20 private IndexColorModel cm;
22 public MedianCut(
int[] pixels,
int width,
int height) {
32 hist =
new int[HSIZE];
33 for (
int i=0; i<width*height; i++) {
34 color16 = rgb(pixels32[i]);
45 for (
int i=0; i<HSIZE; i++)
46 if (hist[i]>0) count++;
51 Color getModalColor() {
54 for (
int i=0; i<HSIZE; i++)
59 return new Color(red(c), green(c), blue(c));
64 private final int rgb(
int c) {
65 int r = (c&0xf80000)>>19;
66 int g = (c&0xf800)>>6;
72 private final int red(
int x) {
77 private final int green(
int x) {
82 private final int blue(
int x) {
101 int k, level, ncubes, splitpos;
104 Cube cube, cubeA, cubeB;
108 list =
new Cube[MAXCOLORS];
109 histPtr =
new int[HSIZE];
112 for (i=0,color=0; i<=HSIZE-1; i++) {
114 histPtr[color++] = i;
115 cube.count = cube.count + hist[i];
118 cube.lower = 0; cube.upper = color-1;
121 list[ncubes++] = cube;
124 while (ncubes < maxcubes) {
127 level = 255; splitpos = -1;
128 for (k=0; k<=ncubes-1; k++) {
129 if (list[k].lower == list[k].upper)
131 else if (list[k].level < level) {
132 level = list[k].level;
140 cube = list[splitpos];
141 lr = cube.rmax - cube.rmin;
142 lg = cube.gmax - cube.gmin;
143 lb = cube.bmax - cube.bmin;
144 if (lr >= lg && lr >= lb) longdim = 0;
145 if (lg >= lr && lg >= lb) longdim = 1;
146 if (lb >= lr && lb >= lg) longdim = 2;
149 reorderColors(histPtr, cube.lower, cube.upper, longdim);
150 quickSort(histPtr, cube.lower, cube.upper);
151 restoreColorOrder(histPtr, cube.lower, cube.upper, longdim);
155 for (i=cube.lower;i<=cube.upper-1;i++) {
156 if (count >= cube.count/2)
break;
158 count = count + hist[color];
165 cubeA.lower = cube.lower;
166 cubeA.upper = median-1;
168 cubeA.level = cube.level + 1;
170 list[splitpos] = cubeA;
173 cubeB.lower = median;
174 cubeB.upper = cube.upper;
175 cubeB.count = cube.count - count;
176 cubeB.level = cube.level + 1;
178 list[ncubes++] = cubeB;
187 makeInverseMap(hist, ncubes);
192 void Shrink(Cube cube) {
198 int rmin, rmax, gmin, gmax, bmin, bmax;
200 rmin = 255; rmax = 0;
201 gmin = 255; gmax = 0;
202 bmin = 255; bmax = 0;
203 for (
int i=cube.lower; i<=cube.upper; i++) {
208 if (r > rmax) rmax = r;
209 if (r < rmin) rmin = r;
210 if (g > gmax) gmax = g;
211 if (g < gmin) gmin = g;
212 if (b > bmax) bmax = b;
213 if (b < bmin) bmin = b;
215 cube.rmin = rmin; cube.rmax = rmax;
216 cube.gmin = gmin; cube.gmax = gmax;
217 cube.gmin = gmin; cube.gmax = gmax;
221 void makeInverseMap(
int[] hist,
int ncubes) {
229 float rsum, gsum, bsum;
231 byte[] rLUT =
new byte[256];
232 byte[] gLUT =
new byte[256];
233 byte[] bLUT =
new byte[256];
235 IJ.showStatus(
"Making inverse map");
236 for (
int k=0; k<=ncubes-1; k++) {
238 rsum = gsum = bsum = (float)0.0;
239 for (
int i=cube.lower; i<=cube.upper; i++) {
242 rsum += (float)r*(
float)hist[color];
244 gsum += (float)g*(
float)hist[color];
246 bsum += (float)b*(
float)hist[color];
250 r = (int)(rsum/(
float)cube.count);
251 g = (int)(gsum/(
float)cube.count);
252 b = (int)(bsum/(
float)cube.count);
253 if (r==248 && g==248 && b==248)
259 cm =
new IndexColorModel(8, ncubes, rLUT, gLUT, bLUT);
263 for (
int k=0; k<=ncubes-1; k++) {
265 for (
int i=cube.lower; i<=cube.upper; i++) {
273 void reorderColors(
int[] a,
int lo,
int hi,
int longDim) {
280 for (
int i=lo; i<=hi; i++) {
283 a[i] = (r<<10) | (c>>5);
287 for (
int i=lo; i<=hi; i++) {
292 a[i] = (g<<10) | (b<<5) | r;
301 void restoreColorOrder(
int[] a,
int lo,
int hi,
int longDim) {
307 for (
int i=lo; i<=hi; i++) {
310 a[i] = ((c&1023)<<5) | r;
314 for (
int i=lo; i<=hi; i++) {
319 a[i] = (b<<10) | (g<<5) | r;
328 void quickSort(
int a[],
int lo0,
int hi0) {
336 mid = a[ ( lo0 + hi0 ) / 2 ];
338 while( ( lo < hi0 ) && ( a[lo] < mid ) )
340 while( ( hi > lo0 ) && ( a[hi] > mid ) )
351 quickSort( a, lo0, hi );
353 quickSort( a, lo, hi0 );
359 ImageProcessor makeImage() {
366 IJ.showStatus(
"Creating 8-bit image");
367 pixels8 =
new byte[width*height];
368 for (
int i=0; i<width*height; i++) {
369 color16 = rgb(pixels32[i]);
370 pixels8[i] = (byte)hist[color16];
372 ImageProcessor ip =
new ByteProcessor(width, height, pixels8, cm);
373 IJ.showProgress(1.0);
394 public String toString() {
395 String s =
"lower=" + lower +
" upper=" + upper;
396 s = s +
" count=" + count +
" level=" + level;
397 s = s +
" rmin=" + rmin +
" rmax=" + rmax;
398 s = s +
" gmin=" + gmin +
" gmax=" + gmax;
399 s = s +
" bmin=" + bmin +
" bmax=" + bmax;