首页 > 代码库 > 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
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。