首页 > 代码库 > Android笔记——Bitmap自动取色(纯搬运)

Android笔记——Bitmap自动取色(纯搬运)

说明:
这个是一个老外写的自动自动从bitmap中取主色与第二主色的工具类,稍微研究了下用法,但感觉效果一般,记录下。
感兴趣的同学可以自行研究下,老外的代码没注释,这点给黄老师我造成的困惑不少。
顺便附上老外的github地址:https://gist.github.com/chrisbanes/ba8e7b9ec0e40f6949c6

大概的用法:

1 image = (ImageView)findViewById(R.id.image);2 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.test);3 DominantColorCalculator colorCalculator = new DominantColorCalculator(bitmap);4 ColorScheme scheme = colorCalculator.getColorScheme();5 View main = findViewById(R.id.main);6 View second = findViewById(R.id.second);7 main.setBackgroundColor(scheme.primaryText);8 second.setBackgroundColor(scheme.secondaryText);



老外的核心代码,及简单解释:
1、ColorScheme类,作用貌似是记录颜色,其中xxxtext都是Color对象

 1 /* 2  * Copyright 2014 Chris Banes 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); 5  * you may not use this file except in compliance with the License. 6  * You may obtain a copy of the License at 7  * 8  *     http://www.apache.org/licenses/LICENSE-2.0 9  *10  * Unless required by applicable law or agreed to in writing, software11  * distributed under the License is distributed on an "AS IS" BASIS,12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13  * See the License for the specific language governing permissions and14  * limitations under the License.15  */16 17 public class ColorScheme {18 19     public final int primaryAccent;20     public final int secondaryAccent;21     public final int tertiaryAccent;22 23     public final int primaryText;24     public final int secondaryText;25 26     public ColorScheme(int primaryAccent, int secondaryAccent, int tertiaryAccent,27             int primaryText, int secondaryText) {28         this.primaryAccent = primaryAccent;29         this.secondaryAccent = secondaryAccent;30         this.tertiaryAccent = tertiaryAccent;31         this.primaryText = primaryText;32         this.secondaryText = secondaryText;33     }34 }



2、ColorUtils类,有一些颜色操作的工具方法,比如颜色混合、亮暗调整、YIQ转换等等

 1 /* 2  * Copyright 2014 Chris Banes 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); 5  * you may not use this file except in compliance with the License. 6  * You may obtain a copy of the License at 7  * 8  *     http://www.apache.org/licenses/LICENSE-2.0 9  *10  * Unless required by applicable law or agreed to in writing, software11  * distributed under the License is distributed on an "AS IS" BASIS,12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13  * See the License for the specific language governing permissions and14  * limitations under the License.15  */16 17 import android.graphics.Color;18 19 public class ColorUtils {20 21     public static int darken(final int color, float fraction) {22         return blendColors(Color.BLACK, color, fraction);23     }24 25     public static int lighten(final int color, float fraction) {26         return blendColors(Color.WHITE, color, fraction);27     }28 29     /**30      * @return luma value according to to YIQ color space.31      */32     public static final int calculateYiqLuma(int color) {33         return Math.round((299 * Color.red(color) + 587 * Color.green(color) + 114 * Color.blue(color)) / 1000f);34     }35 36     /**37      * Blend {@code color1} and {@code color2} using the given ratio.38      *39      * @param ratio of which to blend. 1.0 will return {@code color1}, 0.5 will give an even blend,40      *              0.0 will return {@code color2}.41      */42     public static int blendColors(int color1, int color2, float ratio) {43         final float inverseRatio = 1f - ratio;44         float r = (Color.red(color1) * ratio) + (Color.red(color2) * inverseRatio);45         float g = (Color.green(color1) * ratio) + (Color.green(color2) * inverseRatio);46         float b = (Color.blue(color1) * ratio) + (Color.blue(color2) * inverseRatio);47         return Color.rgb((int) r, (int) g, (int) b);48     }49 50     public static final int changeBrightness(final int color, float fraction) {51         return calculateYiqLuma(color) >= 12852                 ? darken(color, fraction)53                 : lighten(color, fraction);54     }55 56     public static final int calculateContrast(MedianCutQuantizer.ColorNode color1,57             MedianCutQuantizer.ColorNode color2) {58         return Math.abs(ColorUtils.calculateYiqLuma(color1.getRgb())59                 - ColorUtils.calculateYiqLuma(color2.getRgb()));60     }61 62     public static final float calculateColorfulness(MedianCutQuantizer.ColorNode node) {63         float[] hsv = node.getHsv();64         return hsv[1] * hsv[2];65     }66 67 }



3、和Android的Bitmap对象的接口类,构造方法中传入bitmap对象即开始转换,然后通过getColorScheme获得抓取到的颜色

  1 /*  2  * Copyright 2014 Chris Banes  3  *  4  * Licensed under the Apache License, Version 2.0 (the "License");  5  * you may not use this file except in compliance with the License.  6  * You may obtain a copy of the License at  7  *  8  *     http://www.apache.org/licenses/LICENSE-2.0  9  * 10  * Unless required by applicable law or agreed to in writing, software 11  * distributed under the License is distributed on an "AS IS" BASIS, 12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13  * See the License for the specific language governing permissions and 14  * limitations under the License. 15  */ 16  17 import android.graphics.Bitmap; 18 import android.graphics.Color; 19  20 import java.util.Arrays; 21 import java.util.Comparator; 22  23 import org.apache.chrisbanes.colorscheme.MedianCutQuantizer.ColorNode; 24  25 public class DominantColorCalculator { 26  27     private static final int NUM_COLORS = 10; 28  29     private static final int PRIMARY_TEXT_MIN_CONTRAST = 135; 30  31     private static final int SECONDARY_MIN_DIFF_HUE_PRIMARY = 120; 32  33     private static final int TERTIARY_MIN_CONTRAST_PRIMARY = 20; 34     private static final int TERTIARY_MIN_CONTRAST_SECONDARY = 90; 35  36     private final MedianCutQuantizer.ColorNode[] mPalette; 37     private final MedianCutQuantizer.ColorNode[] mWeightedPalette; 38     private ColorScheme mColorScheme; 39  40     public DominantColorCalculator(Bitmap bitmap) { 41         final int width = bitmap.getWidth(); 42         final int height = bitmap.getHeight(); 43  44         final int[] rgbPixels = new int[width * height]; 45         bitmap.getPixels(rgbPixels, 0, width, 0, 0, width, height); 46  47         final MedianCutQuantizer mcq = new MedianCutQuantizer(rgbPixels, NUM_COLORS); 48  49         mPalette = mcq.getQuantizedColors(); 50         mWeightedPalette = weight(mPalette); 51  52         findColors(); 53     } 54  55     public ColorScheme getColorScheme() { 56         return mColorScheme; 57     } 58  59     private void findColors() { 60         final ColorNode primaryAccentColor = findPrimaryAccentColor(); 61         final ColorNode secondaryAccentColor = findSecondaryAccentColor(primaryAccentColor); 62  63         final int tertiaryAccentColor = findTertiaryAccentColor( 64                 primaryAccentColor, secondaryAccentColor); 65  66         final int primaryTextColor = findPrimaryTextColor(primaryAccentColor); 67         final int secondaryTextColor = findSecondaryTextColor(primaryAccentColor); 68  69         mColorScheme = new ColorScheme( 70                 primaryAccentColor.getRgb(), 71                 secondaryAccentColor.getRgb(), 72                 tertiaryAccentColor, 73                 primaryTextColor, 74                 secondaryTextColor); 75     } 76  77     /** 78      * @return the first color from our weighted palette. 79      */ 80     private ColorNode findPrimaryAccentColor() { 81         return mWeightedPalette[0]; 82     } 83  84     /** 85      * @return the next color in the weighted palette which ideally has enough difference in hue. 86      */ 87     private ColorNode findSecondaryAccentColor(final ColorNode primary) { 88         final float primaryHue = primary.getHsv()[0]; 89  90         // Find the first color which has sufficient difference in hue from the primary 91         for (ColorNode candidate : mWeightedPalette) { 92             final float candidateHue = candidate.getHsv()[0]; 93  94             // Calculate the difference in hue, if it‘s over the threshold return it 95             if (Math.abs(primaryHue - candidateHue) >= SECONDARY_MIN_DIFF_HUE_PRIMARY) { 96                 return candidate; 97             } 98         } 99 100         // If we get here, just return the second weighted color101         return mWeightedPalette[1];102     }103 104     /**105      * @return the first color from our weighted palette which has sufficient contrast from the106      *         primary and secondary colors.107      */108     private int findTertiaryAccentColor(final ColorNode primary, final ColorNode secondary) {109         // Find the first color which has sufficient contrast from both the primary & secondary110         for (ColorNode color : mWeightedPalette) {111             if (ColorUtils.calculateContrast(color, primary) >= TERTIARY_MIN_CONTRAST_PRIMARY112                     && ColorUtils.calculateContrast(color, secondary) >= TERTIARY_MIN_CONTRAST_SECONDARY) {113                 return color.getRgb();114             }115         }116 117         // We couldn‘t find a colour. In that case use the primary colour, modifying it‘s brightness118         // by 45%119         return ColorUtils.changeBrightness(secondary.getRgb(), 0.45f);120     }121 122     /**123      * @return the first color which has sufficient contrast from the primary colors.124      */125     private int findPrimaryTextColor(final ColorNode primary) {126         // Try and find a colour with sufficient contrast from the primary colour127         for (ColorNode color : mPalette) {128             if (ColorUtils.calculateContrast(color, primary) >= PRIMARY_TEXT_MIN_CONTRAST) {129                 return color.getRgb();130             }131         }132 133         // We haven‘t found a colour, so return black/white depending on the primary colour‘s134         // brightness135         return ColorUtils.calculateYiqLuma(primary.getRgb()) >= 128 ? Color.BLACK : Color.WHITE;136     }137 138     /**139      * @return return black/white depending on the primary colour‘s brightness140      */141     private int findSecondaryTextColor(final ColorNode primary) {142         return ColorUtils.calculateYiqLuma(primary.getRgb()) >= 128 ? Color.BLACK : Color.WHITE;143     }144 145     private static ColorNode[] weight(ColorNode[] palette) {146         final MedianCutQuantizer.ColorNode[] copy = Arrays.copyOf(palette, palette.length);147         final float maxCount = palette[0].getCount();148 149         Arrays.sort(copy, new Comparator<ColorNode>() {150             @Override151             public int compare(ColorNode lhs, ColorNode rhs) {152                 final float lhsWeight = calculateWeight(lhs, maxCount);153                 final float rhsWeight = calculateWeight(rhs, maxCount);154 155                 if (lhsWeight < rhsWeight) {156                     return 1;157                 } else if (lhsWeight > rhsWeight) {158                     return -1;159                 }160                 return 0;161             }162         });163 164         return copy;165     }166 167     private static float calculateWeight(ColorNode node, final float maxCount) {168         return FloatUtils.weightedAverage(169                 ColorUtils.calculateColorfulness(node), 2f,170                 (node.getCount() / maxCount), 1f171         );172     }173 174 }



4、一个计算浮点数组平均权重平均值的工具方法类

 1 /* 2  * Copyright 2014 Chris Banes 3  * 4  * Licensed under the Apache License, Version 2.0 (the "License"); 5  * you may not use this file except in compliance with the License. 6  * You may obtain a copy of the License at 7  * 8  *     http://www.apache.org/licenses/LICENSE-2.0 9  *10  * Unless required by applicable law or agreed to in writing, software11  * distributed under the License is distributed on an "AS IS" BASIS,12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.13  * See the License for the specific language governing permissions and14  * limitations under the License.15  */16 17 public class FloatUtils {18 19     public static float weightedAverage(float... values) {20         assert values.length % 2 == 0;21 22         float sum = 0;23         float sumWeight = 0;24 25         for (int i = 0; i < values.length; i += 2) {26             float value =http://www.mamicode.com/ values[i];27             float weight = values[i + 1];28 29             sum += (value * weight);30             sumWeight += weight;31         }32 33         return sum / sumWeight;34     }35 36 }



5、关键类,获取位图中的颜色

  1 /**  2  * This sample code is made available as part of the book "Digital Image  3  * Processing - An Algorithmic Introduction using Java" by Wilhelm Burger  4  * and Mark J. Burge, Copyright (C) 2005-2008 Springer-Verlag Berlin,  5  * Heidelberg, New York.  6  * Note that this code comes with absolutely no warranty of any kind.  7  * See http://www.imagingbook.com for details and licensing conditions.  8  *  9  * Modified by Chris Banes. 10  */ 11  12 import android.graphics.Color; 13 import android.util.Log; 14  15 import java.util.ArrayList; 16 import java.util.Arrays; 17 import java.util.Comparator; 18 import java.util.List; 19  20 /* 21  * This is an implementation of Heckbert‘s median-cut color quantization algorithm 22  * (Heckbert P., "Color Image Quantization for Frame Buffer Display", ACM Transactions 23  * on Computer Graphics (SIGGRAPH), pp. 297-307, 1982). 24  * Unlike in the original algorithm, no initial uniform (scalar) quantization is used to 25  * for reducing the number of image colors. Instead, all colors contained in the original 26  * image are considered in the quantization process. After the set of representative 27  * colors has been found, each image color is mapped to the closest representative 28  * in RGB color space using the Euclidean distance. 29  * The quantization process has two steps: first a ColorQuantizer object is created from 30  * a given image using one of the constructor methods provided. Then this ColorQuantizer 31  * can be used to quantize the original image or any other image using the same set of 32  * representative colors (color table). 33  */ 34  35 public class MedianCutQuantizer { 36  37     private static final String LOG_TAG = MedianCutQuantizer.class 38             .getSimpleName(); 39  40     private ColorNode[] imageColors = null; // original (unique) image colors 41     private ColorNode[] quantColors = null; // quantized colors 42  43     public MedianCutQuantizer(int[] pixels, int Kmax) { 44         quantColors = findRepresentativeColors(pixels, Kmax); 45     } 46  47     public int countQuantizedColors() { 48         return quantColors.length; 49     } 50  51     public ColorNode[] getQuantizedColors() { 52         return quantColors; 53     } 54  55     ColorNode[] findRepresentativeColors(int[] pixels, int Kmax) { 56         ColorHistogram colorHist = new ColorHistogram(pixels); 57         int K = colorHist.getNumberOfColors(); 58         ColorNode[] rCols = null; 59  60         imageColors = new ColorNode[K]; 61         for (int i = 0; i < K; i++) { 62             int rgb = colorHist.getColor(i); 63             int cnt = colorHist.getCount(i); 64             imageColors[i] = new ColorNode(rgb, cnt); 65         } 66  67         if (K <= Kmax) { 68             // image has fewer colors than Kmax 69             rCols = imageColors; 70         } else { 71             ColorBox initialBox = new ColorBox(0, K - 1, 0); 72             List<ColorBox> colorSet = new ArrayList<ColorBox>(); 73             colorSet.add(initialBox); 74             int k = 1; 75             boolean done = false; 76             while (k < Kmax && !done) { 77                 ColorBox nextBox = findBoxToSplit(colorSet); 78                 if (nextBox != null) { 79                     ColorBox newBox = nextBox.splitBox(); 80                     colorSet.add(newBox); 81                     k = k + 1; 82                 } else { 83                     done = true; 84                 } 85             } 86             rCols = averageColors(colorSet); 87         } 88         return rCols; 89     } 90  91     public void quantizeImage(int[] pixels) { 92         for (int i = 0; i < pixels.length; i++) { 93             ColorNode color = findClosestColor(pixels[i]); 94             pixels[i] = Color.rgb(color.red, color.grn, color.blu); 95         } 96     } 97  98     ColorNode findClosestColor(int rgb) { 99         int idx = findClosestColorIndex(rgb);100         return quantColors[idx];101     }102 103     int findClosestColorIndex(int rgb) {104         int red = Color.red(rgb);105         int grn = Color.green(rgb);106         int blu = Color.blue(rgb);107         int minIdx = 0;108         int minDistance = Integer.MAX_VALUE;109         for (int i = 0; i < quantColors.length; i++) {110             ColorNode color = quantColors[i];111             int d2 = color.distance2(red, grn, blu);112             if (d2 < minDistance) {113                 minDistance = d2;114                 minIdx = i;115             }116         }117         return minIdx;118     }119 120     private ColorBox findBoxToSplit(List<ColorBox> colorBoxes) {121         ColorBox boxToSplit = null;122         // from the set of splitable color boxes123         // select the one with the minimum level124         int minLevel = Integer.MAX_VALUE;125         for (ColorBox box : colorBoxes) {126             if (box.colorCount() >= 2) { // box can be split127                 if (box.level < minLevel) {128                     boxToSplit = box;129                     minLevel = box.level;130                 }131             }132         }133         return boxToSplit;134     }135 136     private ColorNode[] averageColors(List<ColorBox> colorBoxes) {137         int n = colorBoxes.size();138         ColorNode[] avgColors = new ColorNode[n];139         int i = 0;140         for (ColorBox box : colorBoxes) {141             avgColors[i] = box.getAverageColor();142             i = i + 1;143         }144         return avgColors;145     }146 147     // -------------- class ColorNode148     // -------------------------------------------149 150     public static class ColorNode {151 152         private final int red, grn, blu;153         private final int cnt;154 155         private float[] hsv;156 157         ColorNode(int rgb, int cnt) {158             this.red = Color.red(rgb);159             this.grn = Color.green(rgb);160             this.blu = Color.blue(rgb);161             this.cnt = cnt;162         }163 164         ColorNode(int red, int grn, int blu, int cnt) {165             this.red = red;166             this.grn = grn;167             this.blu = blu;168             this.cnt = cnt;169         }170 171         public int getRgb() {172             return Color.rgb(red, grn, blu);173         }174 175         public float[] getHsv() {176             if (hsv == null) {177                 hsv = new float[3];178                 Color.RGBToHSV(red, grn, blu, hsv);179             }180             return hsv;181         }182 183         public int getCount() {184             return cnt;185         }186 187         int distance2(int red, int grn, int blu) {188             // returns the squared distance between (red, grn, blu)189             // and this this color190             int dr = this.red - red;191             int dg = this.grn - grn;192             int db = this.blu - blu;193             return dr * dr + dg * dg + db * db;194         }195 196         public String toString() {197             return new StringBuilder(getClass().getSimpleName()).append(" #")198                     .append(Integer.toHexString(getRgb())).append(". count: ")199                     .append(cnt).toString();200         }201     }202 203     // -------------- class ColorBox -------------------------------------------204 205     class ColorBox {206 207         int lower = 0; // lower index into ‘imageColors‘208         int upper = -1; // upper index into ‘imageColors‘209         int level; // split level o this color box210         int count = 0; // number of pixels represented by thos color box211         int rmin, rmax; // range of contained colors in red dimension212         int gmin, gmax; // range of contained colors in green dimension213         int bmin, bmax; // range of contained colors in blue dimension214 215         ColorBox(int lower, int upper, int level) {216             this.lower = lower;217             this.upper = upper;218             this.level = level;219             this.trim();220         }221 222         int colorCount() {223             return upper - lower;224         }225 226         void trim() {227             // recompute the boundaries of this color box228             rmin = 255;229             rmax = 0;230             gmin = 255;231             gmax = 0;232             bmin = 255;233             bmax = 0;234             count = 0;235             for (int i = lower; i <= upper; i++) {236                 ColorNode color = imageColors[i];237                 count = count + color.cnt;238                 int r = color.red;239                 int g = color.grn;240                 int b = color.blu;241                 if (r > rmax) {242                     rmax = r;243                 }244                 if (r < rmin) {245                     rmin = r;246                 }247                 if (g > gmax) {248                     gmax = g;249                 }250                 if (g < gmin) {251                     gmin = g;252                 }253                 if (b > bmax) {254                     bmax = b;255                 }256                 if (b < bmin) {257                     bmin = b;258                 }259             }260         }261 262         // Split this color box at the median point along its263         // longest color dimension264         ColorBox splitBox() {265             if (this.colorCount() < 2) // this box cannot be split266             {267                 return null;268             } else {269                 // find longest dimension of this box:270                 ColorDimension dim = getLongestColorDimension();271 272                 // find median along dim273                 int med = findMedian(dim);274 275                 // now split this box at the median return the resulting new276                 // box.277                 int nextLevel = level + 1;278                 ColorBox newBox = new ColorBox(med + 1, upper, nextLevel);279                 this.upper = med;280                 this.level = nextLevel;281                 this.trim();282                 return newBox;283             }284         }285 286         // Find longest dimension of this color box (RED, GREEN, or BLUE)287         ColorDimension getLongestColorDimension() {288             int rLength = rmax - rmin;289             int gLength = gmax - gmin;290             int bLength = bmax - bmin;291             if (bLength >= rLength && bLength >= gLength) {292                 return ColorDimension.BLUE;293             } else if (gLength >= rLength && gLength >= bLength) {294                 return ColorDimension.GREEN;295             } else {296                 return ColorDimension.RED;297             }298         }299 300         // Find the position of the median in RGB space along301         // the red, green or blue dimension, respectively.302         int findMedian(ColorDimension dim) {303             // sort color in this box along dimension dim:304             Arrays.sort(imageColors, lower, upper + 1, dim.comparator);305             // find the median point:306             int half = count / 2;307             int nPixels, median;308             for (median = lower, nPixels = 0; median < upper; median++) {309                 nPixels = nPixels + imageColors[median].cnt;310                 if (nPixels >= half) {311                     break;312                 }313             }314             return median;315         }316 317         ColorNode getAverageColor() {318             int rSum = 0;319             int gSum = 0;320             int bSum = 0;321             int n = 0;322             for (int i = lower; i <= upper; i++) {323                 ColorNode ci = imageColors[i];324                 int cnt = ci.cnt;325                 rSum = rSum + cnt * ci.red;326                 gSum = gSum + cnt * ci.grn;327                 bSum = bSum + cnt * ci.blu;328                 n = n + cnt;329             }330             double nd = n;331             int avgRed = (int) (0.5 + rSum / nd);332             int avgGrn = (int) (0.5 + gSum / nd);333             int avgBlu = (int) (0.5 + bSum / nd);334             return new ColorNode(avgRed, avgGrn, avgBlu, n);335         }336 337         public String toString() {338             String s = this.getClass().getSimpleName();339             s = s + " lower=" + lower + " upper=" + upper;340             s = s + " count=" + count + " level=" + level;341             s = s + " rmin=" + rmin + " rmax=" + rmax;342             s = s + " gmin=" + gmin + " gmax=" + gmax;343             s = s + " bmin=" + bmin + " bmax=" + bmax;344             s = s + " bmin=" + bmin + " bmax=" + bmax;345             return s;346         }347     }348 349     // --- color dimensions ------------------------350 351     // The main purpose of this enumeration class is associate352     // the color dimensions with the corresponding comparators.353     enum ColorDimension {354         RED(new redComparator()), GREEN(new grnComparator()), BLUE(355                 new bluComparator());356 357         public final Comparator<ColorNode> comparator;358 359         ColorDimension(Comparator<ColorNode> cmp) {360             this.comparator = cmp;361         }362     }363 364     // --- color comparators used for sorting colors along different dimensions365     // ---366 367     static class redComparator implements Comparator<ColorNode> {368         public int compare(ColorNode colA, ColorNode colB) {369             return colA.red - colB.red;370         }371     }372 373     static class grnComparator implements Comparator<ColorNode> {374         public int compare(ColorNode colA, ColorNode colB) {375             return colA.grn - colB.grn;376         }377     }378 379     static class bluComparator implements Comparator<ColorNode> {380         public int compare(ColorNode colA, ColorNode colB) {381             return colA.blu - colB.blu;382         }383     }384 385     // -------- utility methods -----------386 387     void listColorNodes(ColorNode[] nodes) {388         int i = 0;389         for (ColorNode color : nodes) {390             Log.d(LOG_TAG, "Color Node #" + i + " " + color.toString());391             i++;392         }393     }394 395     static class ColorHistogram {396 397         int colorArray[] = null;398         int countArray[] = null;399 400         ColorHistogram(int[] color, int[] count) {401             this.countArray = count;402             this.colorArray = color;403         }404 405         ColorHistogram(int[] pixelsOrig) {406             int N = pixelsOrig.length;407             int[] pixelsCpy = new int[N];408             for (int i = 0; i < N; i++) {409                 // remove possible alpha components410                 pixelsCpy[i] = 0xFFFFFF & pixelsOrig[i];411             }412             Arrays.sort(pixelsCpy);413 414             // count unique colors:415             int k = -1; // current color index416             int curColor = -1;417             for (int i = 0; i < pixelsCpy.length; i++) {418                 if (pixelsCpy[i] != curColor) {419                     k++;420                     curColor = pixelsCpy[i];421                 }422             }423             int nColors = k + 1;424 425             // tabulate and count unique colors:426             colorArray = new int[nColors];427             countArray = new int[nColors];428             k = -1; // current color index429             curColor = -1;430             for (int i = 0; i < pixelsCpy.length; i++) {431                 if (pixelsCpy[i] != curColor) { // new color432                     k++;433                     curColor = pixelsCpy[i];434                     colorArray[k] = curColor;435                     countArray[k] = 1;436                 } else {437                     countArray[k]++;438                 }439             }440         }441 442         public int[] getColorArray() {443             return colorArray;444         }445 446         public int[] getCountArray() {447             return countArray;448         }449 450         public int getNumberOfColors() {451             if (colorArray == null) {452                 return 0;453             } else {454                 return colorArray.length;455             }456         }457 458         public int getColor(int index) {459             return this.colorArray[index];460         }461 462         public int getCount(int index) {463             return this.countArray[index];464         }465     }466 467 } // class MedianCut



剩余的大家自行研究了,如果有研究出更详细的用法,记得联系黄老师哦!
QQ:811868948
E-Mail:halfmanhuang@gmail.com