Понимание использования ColorMatrix и ColorMatrixColorFilter для изменения оттенка Drawable

Я работаю над пользовательским интерфейсом для приложения, и я пытаюсь использовать значки в оттенках серого и позволяю пользователю изменять тему до цвета по своему выбору. Чтобы сделать это, я пытаюсь применить ColorFilter какого-либо типа, чтобы наложить цвет поверх извлекаемого. Я пробовал использовать PorterDuff.Mode.MULTIPLY, и он работает почти так же, как мне нужно, за исключением того, что белые также накладываются на цвет. То, что я идеально ищу, – это что-то вроде режима смешивания «Цвет» в Photoshop, где графический объект сохраняет свою прозрачность и яркость и только изменяет цвет изображения. Например:

alt text становится alt text

После некоторых исследований выяснилось, что class ColorMatrixColorFilter может делать то, что мне нужно, но я не могу найти никаких ресурсов, указывающих на то, как используется matrix. Это matrix размером 4×5, но мне нужно знать, как я занимаюсь проектированием матрицы. Есть идеи?

EDIT: Так хорошо, то, что я нашел до сих пор на этом, выглядит следующим образом:

1 0 0 0 0 //red 0 1 0 0 0 //green 0 0 1 0 0 //blue 0 0 0 1 0 //alpha 

Где эта matrix является единичной матрицей (при ее применении не изменяется), а числа варьируются от 0 до 1 (поплавки). Эта matrix будет умножена на каждый пиксель, чтобы преобразовать его в новый цвет. Так вот, где он начинает становиться нечетким для меня. Поэтому я думаю, что каждый пиксель будет представлять собой вектор 1 x 4, содержащий значения argb (например, 0.2, 0.5, 0.8, 1 ), которые будут усеяны матрицей преобразования. Чтобы удвоить красную интенсивность изображения, вы должны использовать матрицу, такую ​​как:

 2 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 

который даст вам вектор (цвет) 0.4, 0.5, 0.8, 1 . Из ограниченного тестирования это, похоже, так и работает правильно, но на самом деле я все-таки получаю ту же проблему (например, побелка белых цветов). Дальнейшее чтение говорит мне, что это происходит потому, что он выполняет преобразование по значениям RGB, тогда как для изменения оттенков значения сначала должны быть преобразованы в значения HSL. Поэтому, возможно, я мог бы написать class, который бы читал изображение и преобразовывал цвета, и перерисовывал изображение с новыми цветами. Это создает дополнительную проблему с StateListDrawables, так как я не уверен, как я буду получать каждый из них в коде и модифицировать их все, и насколько медленным будет процесс. : /

Хм, хорошо, поэтому я полагаю, что другой вопрос, который у меня будет, заключается в том, можно ли использовать матрицу для преобразования RGB в другое цветовое пространство со световой информацией, например L a b или HSL? Если это так, я мог бы просто умножить матрицу для этого конвертирования, а затем внести корректировку оттенка в матрицу THAT, а затем применить эту матрицу в качестве ColorFilter.

9 Solutions collect form web for “Понимание использования ColorMatrix и ColorMatrixColorFilter для изменения оттенка Drawable”

Это то, что я использую для своей игры. Это компиляция различных частей, найденных в различных статьях на сайтах. Кредиты принадлежат оригинальному автору из ссылок @see. Обратите внимание, что с цветовыми matrixми можно сделать намного больше. Включая инвертирование и т. Д.

 public class ColorFilterGenerator { /** * Creates a HUE ajustment ColorFilter * @see http://groups.google.com/group/android-developers/browse_thread/thread/9e215c83c3819953 * @see http://gskinner.com/blog/archives/2007/12/colormatrix_cla.html * @param value degrees to shift the hue. * @return */ public static ColorFilter adjustHue( float value ) { ColorMatrix cm = new ColorMatrix(); adjustHue(cm, value); return new ColorMatrixColorFilter(cm); } /** * @see http://groups.google.com/group/android-developers/browse_thread/thread/9e215c83c3819953 * @see http://gskinner.com/blog/archives/2007/12/colormatrix_cla.html * @param cm * @param value */ public static void adjustHue(ColorMatrix cm, float value) { value = cleanValue(value, 180f) / 180f * (float) Math.PI; if (value == 0) { return; } float cosVal = (float) Math.cos(value); float sinVal = (float) Math.sin(value); float lumR = 0.213f; float lumG = 0.715f; float lumB = 0.072f; float[] mat = new float[] { lumR + cosVal * (1 - lumR) + sinVal * (-lumR), lumG + cosVal * (-lumG) + sinVal * (-lumG), lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0, lumR + cosVal * (-lumR) + sinVal * (0.143f), lumG + cosVal * (1 - lumG) + sinVal * (0.140f), lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0, lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)), lumG + cosVal * (-lumG) + sinVal * (lumG), lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f }; cm.postConcat(new ColorMatrix(mat)); } protected static float cleanValue(float p_val, float p_limit) { return Math.min(p_limit, Math.max(-p_limit, p_val)); } } 

Для этого я должен добавить пример:

 ImageView Sun = (ImageView)findViewById(R.id.sun); Sun.setColorFilter(ColorFilterGenerator.adjustHue(162)); // 162 degree rotation 

вот полный код, если вы хотите настроить яркость, контрастность, насыщенность и оттенок. Наслаждайтесь! Большое спасибо @RichardLalancette

 public class ColorFilterGenerator { private static double DELTA_INDEX[] = { 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24, 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98, 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8, 10.0 }; /** * @see http://groups.google.com/group/android-developers/browse_thread/thread/9e215c83c3819953 * @see http://gskinner.com/blog/archives/2007/12/colormatrix_cla.html * @param cm * @param value */ public static void adjustHue(ColorMatrix cm, float value) { value = cleanValue(value, 180f) / 180f * (float) Math.PI; if (value == 0){ return; } float cosVal = (float) Math.cos(value); float sinVal = (float) Math.sin(value); float lumR = 0.213f; float lumG = 0.715f; float lumB = 0.072f; float[] mat = new float[] { lumR + cosVal * (1 - lumR) + sinVal * (-lumR), lumG + cosVal * (-lumG) + sinVal * (-lumG), lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0, lumR + cosVal * (-lumR) + sinVal * (0.143f), lumG + cosVal * (1 - lumG) + sinVal * (0.140f), lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0, lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)), lumG + cosVal * (-lumG) + sinVal * (lumG), lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f }; cm.postConcat(new ColorMatrix(mat)); } public static void adjustBrightness(ColorMatrix cm, float value) { value = cleanValue(value,100); if (value == 0) { return; } float[] mat = new float[] { 1,0,0,0,value, 0,1,0,0,value, 0,0,1,0,value, 0,0,0,1,0, 0,0,0,0,1 }; cm.postConcat(new ColorMatrix(mat)); } public static void adjustContrast(ColorMatrix cm, int value) { value = (int)cleanValue(value,100); if (value == 0) { return; } float x; if (value < 0) { x = 127 + (float) value / 100*127; } else { x = value % 1; if (x == 0) { x = (float)DELTA_INDEX[value]; } else { //x = DELTA_INDEX[(p_val<<0)]; // this is how the IDE does it. x = (float)DELTA_INDEX[(value<<0)]*(1-x) + (float)DELTA_INDEX[(value<<0)+1] * x; // use linear interpolation for more granularity. } x = x*127+127; } float[] mat = new float[] { x/127,0,0,0, 0.5f*(127-x), 0,x/127,0,0, 0.5f*(127-x), 0,0,x/127,0, 0.5f*(127-x), 0,0,0,1,0, 0,0,0,0,1 }; cm.postConcat(new ColorMatrix(mat)); } public static void adjustSaturation(ColorMatrix cm, float value) { value = cleanValue(value,100); if (value == 0) { return; } float x = 1+((value > 0) ? 3 * value / 100 : value / 100); float lumR = 0.3086f; float lumG = 0.6094f; float lumB = 0.0820f; float[] mat = new float[] { lumR*(1-x)+x,lumG*(1-x),lumB*(1-x),0,0, lumR*(1-x),lumG*(1-x)+x,lumB*(1-x),0,0, lumR*(1-x),lumG*(1-x),lumB*(1-x)+x,0,0, 0,0,0,1,0, 0,0,0,0,1 }; cm.postConcat(new ColorMatrix(mat)); } protected static float cleanValue(float p_val, float p_limit) { return Math.min(p_limit, Math.max(-p_limit, p_val)); } public static ColorFilter adjustColor(int brightness, int contrast, int saturation, int hue){ ColorMatrix cm = new ColorMatrix(); adjustHue(cm, hue); adjustContrast(cm, contrast); adjustBrightness(cm, brightness); adjustSaturation(cm, saturation); return new ColorMatrixColorFilter(cm); } } 

Для тех, кто заинтересован в использовании ColorMatrixColorFilter. Образец, который я использовал здесь, преобразовал каждый пиксель в красный, когда я рисую bitmap на canvasе.

Комментарий в classе от: http://developer.android.com/reference/android/graphics/ColorMatrix.html, это дает вам некоторое представление о том, как это работает

 @Override protected void onDraw(Canvas canvas) { // The matrix is stored in a single array, and its treated as follows: [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t ] // When applied to a color [r, g, b, a], the resulting color is computed as (after clamping) ; // R' = a*R + b*G + c*B + d*A + e; // G' = f*R + g*G + h*B + i*A + j; // B' = k*R + l*G + m*B + n*A + o; // A' = p*R + q*G + r*B + s*A + t; Paint paint = new Paint(); float[] matrix = { 1, 1, 1, 1, 1, //red 0, 0, 0, 0, 0, //green 0, 0, 0, 0, 0, //blue 1, 1, 1, 1, 1 //alpha }; paint.setColorFilter(new ColorMatrixColorFilter(matrix)); Rect source = new Rect(0, 0, 100, 100); Rect dest = new Rect(0, 0, 100, 100); Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.sampleimage); canvas.drawBitmap(bitmap , source, dest, paint); } 

Между Hue и RGB нет линейной связи. Хюэ определяется кусочно в 60 ° кусках ( http://en.wikipedia.org/wiki/HSL_color_space#General_approach ), и поэтому нет простого преобразования матрицы между HSV и RGB. Чтобы изменить оттенок изображения, вы можете использовать следующий метод:

 public Bitmap changeHue( Bitmap source, double hue ) { Bitmap result = Bitmap.createBitmap( source.getWidth(), source.getHeight(), source.getConfig() ); float[] hsv = new float[3]; for( int x = 0; x < source.getWidth(); x++ ) { for( int y = 0; y < source.getHeight(); y++ ) { int c = source.getPixel( x, y ); Color.colorToHSV( c, hsv ); hsv[0] = (float) ((hsv[0] + 360 * hue) % 360); c = (Color.HSVToColor( hsv ) & 0x00ffffff) | (c & 0xff000000); result.setPixel( x, y, c ); } } return result; } 

Следующий class является улучшением ответов, которые уже были опубликованы. Это облегчает чтение и создание ColorFilter из Bitmap .

Пример использования:

 ImageView imageView = ...; Drawable drawable = imageView.getDrawable(); ColorFilter colorFilter = ColorFilterGenerator.from(drawable).to(Color.RED); imageView.setColorFilter(colorFilter); 

 import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.ColorMatrix; import android.graphics.ColorMatrixColorFilter; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.graphics.drawable.PictureDrawable; import android.widget.ImageView; /** * Creates a {@link ColorMatrixColorFilter} to adjust the hue, saturation, brightness, or * contrast of an {@link Bitmap}, {@link Drawable}, or {@link ImageView}. * 

* Example usage: *
* {@code imageView.setColorFilter(ColorFilterGenerator.from(Color.BLUE).to(Color.RED));} * * @author Jared Rummler */ public class ColorFilterGenerator { // Based off answer from StackOverflow // See: http://stackoverflow.com/a/15119089/1048340 private ColorFilterGenerator() { throw new AssertionError(); } public static From from(Drawable drawable) { return new From(drawableToBitmap(drawable)); } public static From from(Bitmap bitmap) { return new From(bitmap); } public static From from(int color) { return new From(color); } // -------------------------------------------------------------------------------------------- private static final double DELTA_INDEX[] = { 0, 0.01, 0.02, 0.04, 0.05, 0.06, 0.07, 0.08, 0.1, 0.11, 0.12, 0.14, 0.15, 0.16, 0.17, 0.18, 0.20, 0.21, 0.22, 0.24, 0.25, 0.27, 0.28, 0.30, 0.32, 0.34, 0.36, 0.38, 0.40, 0.42, 0.44, 0.46, 0.48, 0.5, 0.53, 0.56, 0.59, 0.62, 0.65, 0.68, 0.71, 0.74, 0.77, 0.80, 0.83, 0.86, 0.89, 0.92, 0.95, 0.98, 1.0, 1.06, 1.12, 1.18, 1.24, 1.30, 1.36, 1.42, 1.48, 1.54, 1.60, 1.66, 1.72, 1.78, 1.84, 1.90, 1.96, 2.0, 2.12, 2.25, 2.37, 2.50, 2.62, 2.75, 2.87, 3.0, 3.2, 3.4, 3.6, 3.8, 4.0, 4.3, 4.7, 4.9, 5.0, 5.5, 6.0, 6.5, 6.8, 7.0, 7.3, 7.5, 7.8, 8.0, 8.4, 8.7, 9.0, 9.4, 9.6, 9.8, 10.0 }; public static void adjustHue(ColorMatrix cm, float value) { value = cleanValue(value, 180f) / 180f * (float) Math.PI; if (value == 0) { return; } float cosVal = (float) Math.cos(value); float sinVal = (float) Math.sin(value); float lumR = 0.213f; float lumG = 0.715f; float lumB = 0.072f; float[] mat = new float[]{ lumR + cosVal * (1 - lumR) + sinVal * (-lumR), lumG + cosVal * (-lumG) + sinVal * (-lumG), lumB + cosVal * (-lumB) + sinVal * (1 - lumB), 0, 0, lumR + cosVal * (-lumR) + sinVal * (0.143f), lumG + cosVal * (1 - lumG) + sinVal * (0.140f), lumB + cosVal * (-lumB) + sinVal * (-0.283f), 0, 0, lumR + cosVal * (-lumR) + sinVal * (-(1 - lumR)), lumG + cosVal * (-lumG) + sinVal * (lumG), lumB + cosVal * (1 - lumB) + sinVal * (lumB), 0, 0, 0f, 0f, 0f, 1f, 0f, 0f, 0f, 0f, 0f, 1f }; cm.postConcat(new ColorMatrix(mat)); } public static void adjustBrightness(ColorMatrix cm, float value) { value = cleanValue(value, 100); if (value == 0) { return; } float[] mat = new float[]{ 1, 0, 0, 0, value, 0, 1, 0, 0, value, 0, 0, 1, 0, value, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 }; cm.postConcat(new ColorMatrix(mat)); } public static void adjustContrast(ColorMatrix cm, int value) { value = (int) cleanValue(value, 100); if (value == 0) { return; } float x; if (value < 0) { x = 127 + value / 100 * 127; } else { x = value % 1; if (x == 0) { x = (float) DELTA_INDEX[value]; } else { x = (float) DELTA_INDEX[(value << 0)] * (1 - x) + (float) DELTA_INDEX[(value << 0) + 1] * x; } x = x * 127 + 127; } float[] mat = new float[]{ x / 127, 0, 0, 0, 0.5f * (127 - x), 0, x / 127, 0, 0, 0.5f * (127 - x), 0, 0, x / 127, 0, 0.5f * (127 - x), 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 }; cm.postConcat(new ColorMatrix(mat)); } public static void adjustSaturation(ColorMatrix cm, float value) { value = cleanValue(value, 100); if (value == 0) { return; } float x = 1 + ((value > 0) ? 3 * value / 100 : value / 100); float lumR = 0.3086f; float lumG = 0.6094f; float lumB = 0.0820f; float[] mat = new float[]{ lumR * (1 - x) + x, lumG * (1 - x), lumB * (1 - x), 0, 0, lumR * (1 - x), lumG * (1 - x) + x, lumB * (1 - x), 0, 0, lumR * (1 - x), lumG * (1 - x), lumB * (1 - x) + x, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1 }; cm.postConcat(new ColorMatrix(mat)); } // -------------------------------------------------------------------------------------------- private static float cleanValue(float p_val, float p_limit) { return Math.min(p_limit, Math.max(-p_limit, p_val)); } private static float[] getHsv(int color) { float[] hsv = new float[3]; Color.RGBToHSV(Color.red(color), Color.green(color), Color.blue(color), hsv); return hsv; } /** * Converts a {@link Drawable} to a {@link Bitmap} * * @param drawable * The {@link Drawable} to convert * @return The converted {@link Bitmap}. */ private static Bitmap drawableToBitmap(Drawable drawable) { if (drawable instanceof BitmapDrawable) { return ((BitmapDrawable) drawable).getBitmap(); } else if (drawable instanceof PictureDrawable) { PictureDrawable pictureDrawable = (PictureDrawable) drawable; Bitmap bitmap = Bitmap.createBitmap(pictureDrawable.getIntrinsicWidth(), pictureDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); canvas.drawPicture(pictureDrawable.getPicture()); return bitmap; } int width = drawable.getIntrinsicWidth(); width = width > 0 ? width : 1; int height = drawable.getIntrinsicHeight(); height = height > 0 ? height : 1; Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); drawable.draw(canvas); return bitmap; } /** * Calculate the average red, green, blue color values of a bitmap * * @param bitmap * a {@link Bitmap} * @return */ private static int[] getAverageColorRGB(Bitmap bitmap) { int width = bitmap.getWidth(); int height = bitmap.getHeight(); int size = width * height; int[] pixels = new int[size]; int r, g, b; r = g = b = 0; bitmap.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 0; i < size; i++) { int pixelColor = pixels[i]; if (pixelColor == Color.TRANSPARENT) { size--; continue; } r += Color.red(pixelColor); g += Color.green(pixelColor); b += Color.blue(pixelColor); } r /= size; g /= size; b /= size; return new int[]{ r, g, b }; } /** * Calculate the average color value of a bitmap * * @param bitmap * a {@link Bitmap} * @return */ private static int getAverageColor(Bitmap bitmap) { int[] rgb = getAverageColorRGB(bitmap); return Color.argb(255, rgb[0], rgb[1], rgb[2]); } // Builder // -------------------------------------------------------------------------------------------- public static final class Builder { int hue; int contrast; int brightness; int saturation; public Builder setHue(int hue) { this.hue = hue; return this; } public Builder setContrast(int contrast) { this.contrast = contrast; return this; } public Builder setBrightness(int brightness) { this.brightness = brightness; return this; } public Builder setSaturation(int saturation) { this.saturation = saturation; return this; } public ColorFilter build() { ColorMatrix cm = new ColorMatrix(); adjustHue(cm, hue); adjustContrast(cm, contrast); adjustBrightness(cm, brightness); adjustSaturation(cm, saturation); return new ColorMatrixColorFilter(cm); } } public static final class From { final int oldColor; private From(Bitmap bitmap) { oldColor = getAverageColor(bitmap); } private From(int oldColor) { this.oldColor = oldColor; } public ColorFilter to(int newColor) { float[] hsv1 = getHsv(oldColor); float[] hsv2 = getHsv(newColor); int hue = (int) (hsv2[0] - hsv1[0]); int saturation = (int) (hsv2[1] - hsv1[1]); int brightness = (int) (hsv2[2] - hsv1[2]); return new ColorFilterGenerator.Builder() .setHue(hue) .setSaturation(saturation) .setBrightness(brightness) .build(); } } }

Я думаю, что этот метод даст вам то, что вы хотите:

http://android.okhelp.cz/hue-color-colored-filter-bitmap-image-android-example/

 bitmapOrg.setColorFilter(Color.RED, PorterDuff.Mode.MULTIPLY); 

Как и остальные ответы, я использовал цветную матрицу для реализации этого поведения, но вы можете перейти в обычный цветной ресурс Android. Матрица отображает цвет в диапазон между значением изображения и белым.

 /** * Color everything that isn't white, the tint color * @param tintColor the color to tint the icon */ public void setInverseMultiplyFilter(Drawable imgCopy, @ColorInt int tintColor) { Drawable imgCopy = imageView.getDrawable().getConstantState().newDrawable(); float colorRed = Color.red(tintColor) / 255f; float colorGreen = Color.green(tintColor) / 255f; float colorBlue = Color.blue(tintColor) / 255f; imgCopy.setColorFilter(new ColorMatrixColorFilter(new ColorMatrix(new float[]{ 1 - colorRed, 0, 0, 0, colorRed * 255, 0, 1 - colorGreen, 0, 0, colorGreen * 255, 0, 0, 1 - colorBlue, 0, colorBlue * 255, 0, 0, 0, Color.alpha(tintColor) / 255f, 0, }))); imageView.setImageDrawable(imgCopy); imageView.invalidate(); } 

Я сделал небольшой тестер ColorMatrixFilter на основе следующего fragmentа:

 private Bitmap setColorFilter(Bitmap drawable) { Bitmap grayscale = Bitmap.createBitmap(drawable.getWidth(), drawable.getHeight(), drawable.getConfig()); //if(isRenderMode) bOriginal.recycle(); Canvas c = new Canvas(grayscale ); Paint p = new Paint(); final ColorMatrix matrixA = new ColorMatrix(); matrixA.setSaturation(sauturationValue/2); float[] mx = { r1Value, r2Value, r3Value, r4Value, r5Value, g1Value, g2Value, g3Value, g4Value, g5Value, b1Value, b2Value, b3Value, b4Value, b5Value, a1Value, a2Value, a3Value, a4Value, a5Value }; final ColorMatrix matrixB = new ColorMatrix(mx); matrixA.setConcat(matrixB, matrixA); final ColorMatrixColorFilter filter = new ColorMatrixColorFilter(matrixA); p.setColorFilter(filter); c.drawBitmap(drawable, 0, 0, p); return grayscale; } 

Вы можете проверить это здесь: https://play.google.com/store/apps/details?id=org.vaelostudio.colormatrixtester

Несмотря на то, что много полезных эффектов можно достичь, используя ColorMatrix я лично рассмотрю использование ColorMap[] вместе с ImageAttributes . Делая это, мы можем определить, какие цвета следует заменить цветами.

Interesting Posts

Начать процесс с высоким приоритетом

Плохо ли использовать два слота, которые не смежны друг с другом?

Извлечение аккумулятора и запуск ноутбука в подключенном режиме?

AngularJS: Когда использовать сервис вместо заводского

DVD-ROM хранится в случайном порядке, особенно при запуске Windows Explorer

как получить весь список детей от Firebase android

C ++ 11 допускает инициализацию в classе нестатических и неконстантных элементов. Что изменилось?

Регулярно ли вредит ноутбуку или Windows?

Команда gui «Open With» Ubuntu не запоминает приложение

Что на самом деле делает флаг JVM CMSClassUnloadingEnabled?

WPF: Есть ли способ переопределить часть ControlTemplate без переопределения всего стиля?

Как я могу прочитать файл даже при получении исключения «в использовании другим процессом»?

Двоичные данные в MySQL

Можно ли отмечать или выделять плохие блоки на HDD?

Сохранение файла в формате CSV в Excel всегда удаляет спецификацию

Давайте будем гением компьютера.