图片特效用到的函数
本文讲述的图片特效处理包括:怀旧、光照、光晕、底片、浮雕、模糊、锐化、黑白、冰冻、素描,所有这些特效都是基于一定的算法,对图像每个点的RGB值进行计算,并汇总所有点的计算结果生成新图片。
特效处理主要用到Bitmap类的三个方法:
createBitmap : 创建一张新图片。
getPixels : 从指定图片中获取所有点的像素数组。
setPixels : 对指定图片设置所有点的像素数组。
图片怀旧效果
现实生活中的老相片都是泛黄的,而黄色又是由绿色和红色混合而成,所以怀旧效果为了突出黄色,就得加大绿色和红色的比重,同时降低蓝色的比重。
下面是怀旧效果的结果截图:
下面是怀旧效果的示例代码:
// 图片怀旧效果 public static Bitmap nostalgic(Bitmap bmp) { /* * 怀旧处理算法即设置新的RGB R=0.393r+0.769g+0.189b G=0.349r+0.686g+0.168b B=0.272r+0.534g+0.131b */ int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixColor = 0; int pixR = 0; int pixG = 0; int pixB = 0; int newR = 0; int newG = 0; int newB = 0; int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 0; i < height; i++) { for (int k = 0; k < width; k++) { pixColor = pixels[width * i + k]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB); newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB); newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB); int newColor = Color.argb(255, newR > 255 ? 255 : newR, newG > 255 ? 255 : newG, newB > 255 ? 255 : newB); pixels[width * i + k] = newColor; } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; }
图片光照效果
现实生活中的相片,越靠近光源的区域,就显得越明亮。对应到图片中,便是越靠近光源中心的像素,就显得越白,越远离光源中心,就越没那么白。
下面是光照效果的结果截图:
下面是光照效果的示例代码:
// 图片光照效果 public static Bitmap sunshine(Bitmap bmp) { /* * 算法原理:图片上面的像素点按照给定圆心,按照圆半径的变化,像素点的RGB值分别加上相应的值作为当前点的RGB值 */ int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixColor = 0; int pixR = 0; int pixG = 0; int pixB = 0; int newR = 0; int newG = 0; int newB = 0; // 围绕圆形光照 int centerX = width / 2; int centerY = height / 2; int radius = Math.min(centerX, centerY); float strength = 150F;// 光照强度100-150 int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 1; i < height - 1; i++) { for (int k = 1; k < width - 1; k++) { // 获取前一个像素颜色 pixColor = pixels[width * i + k]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); newR = pixR; newG = pixG; newB = pixB; // 计算当前点到光照中心的距离,平面坐标系中两点之间的距离 int distance = (int) (Math.pow((centerY - i), 2) + Math.pow( (centerX - k), 2)); if (distance < radius * radius) { // 按照距离大小计算增强的光照值 int result = (int) (strength * (1.0 - Math.sqrt(distance) / radius)); newR = pixR + result; newG = newG + result; newB = pixB + result; } newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); pixels[width * i + k] = Color.argb(255, newR, newG, newB); } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; }
图片光晕效果
光晕与光照则恰恰相反,光晕表现为光源附近的区域显示正常,而界线以外的区域则显示暗淡。根据显示区域的形状,还可分为圆形光晕和矩形光晕两种常见类型。
下面是光晕效果(圆形光晕)的结果截图:
下面是光晕效果(圆形光晕)的示例代码:
// 图片光晕效果(圆形光晕) public static Bitmap haloCircle(Bitmap bmp) { // 高斯矩阵 int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 }; int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int x = width / 2; int y = height / 2; float r = Math.min(x, y) / 2; int pixR = 0; int pixG = 0; int pixB = 0; int pixColor = 0; int newR = 0; int newG = 0; int newB = 0; int delta = 24; // 值越小图片会越亮,越大则越暗 int idx = 0; int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 1, length = height - 1; i < length; i++) { for (int j = 1, len = width - 1; j < len; j++) { idx = 0; int distance = (int) (Math.pow(j - x, 2) + Math.pow(i - y, 2)); // 不是中心区域的点做模糊处理 if (distance > r * r) { for (int m = -1; m <= 1; m++) { for (int n = -1; n <= 1; n++) { pixColor = pixels[(i + m) * width + j + n]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); newR = newR + (int) (pixR * gauss[idx]); newG = newG + (int) (pixG * gauss[idx]); newB = newB + (int) (pixB * gauss[idx]); idx++; } } newR /= delta; newG /= delta; newB /= delta; newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); pixels[i * width + j] = Color.argb(255, newR, newG, newB); newR = 0; newG = 0; newB = 0; } } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; }
下面是光晕效果(矩形光晕)的结果截图:
下面是光晕效果(矩形光晕)的示例代码:
// 图片光晕效果(矩形光晕) public static Bitmap haloRect(Bitmap bmp) { // 高斯矩阵 int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 }; int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int top = height / 4; int bottom = height / 4 * 3; int left = width / 4; int right = width / 4 * 3; int pixR = 0; int pixG = 0; int pixB = 0; int pixColor = 0; int newR = 0; int newG = 0; int newB = 0; int delta = 24; // 值越小图片会越亮,越大则越暗 int idx = 0; int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 1, length = height - 1; i < length; i++) { for (int j = 1, len = width - 1; j < len; j++) { idx = 0; // 不是中心区域的点做模糊处理 if (i<top || i>bottom || j<left || j>right) { for (int m = -1; m <= 1; m++) { for (int n = -1; n <= 1; n++) { pixColor = pixels[(i + m) * width + j + n]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); newR = newR + (int) (pixR * gauss[idx]); newG = newG + (int) (pixG * gauss[idx]); newB = newB + (int) (pixB * gauss[idx]); idx++; } } newR /= delta; newG /= delta; newB /= delta; newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); pixels[i * width + j] = Color.argb(255, newR, newG, newB); newR = 0; newG = 0; newB = 0; } } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; }
图片底片效果
在数码相机时代之前,占统治地位的是胶卷相机,胶卷底片与洗出来的相片相比,底片的RGB值就是相片的RGB值取反,即:底片的红色=255-相片的红色,底片的绿色=255-相片的绿色,底片的蓝色=255-相片的蓝色。
下面是底片效果的结果截图:
下面是底片效果的示例代码:
// 图片底片效果 public static Bitmap negative(Bitmap bmp) { /* * 算法原理: 将当前像素点的RGB值分别与255之差后的值作为当前点的RGB值 例:ABC,求B点的底片效果: B.r = 255 - B.r; B.g = 255 - B.g; B.b = 255 - B.b; */ int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int[] oldPixels = new int[width * height]; int[] newPixels = new int[width * height]; int color; int pixelsR, pixelsG, pixelsB, pixelsA; bmp.getPixels(oldPixels, 0, width, 0, 0, width, height); for (int i = 1; i < height * width; i++) { color = oldPixels[i]; // 获取RGB分量 pixelsA = Color.alpha(color); pixelsR = Color.red(color); pixelsG = Color.green(color); pixelsB = Color.blue(color); // 转换 pixelsR = (255 - pixelsR); pixelsG = (255 - pixelsG); pixelsB = (255 - pixelsB); // 均小于等于255大于等于0 if (pixelsR > 255) { pixelsR = 255; } else if (pixelsR < 0) { pixelsR = 0; } if (pixelsG > 255) { pixelsG = 255; } else if (pixelsG < 0) { pixelsG = 0; } if (pixelsB > 255) { pixelsB = 255; } else if (pixelsB < 0) { pixelsB = 0; } // 根据新的RGB生成新像素 newPixels[i] = Color.argb(pixelsA, pixelsR, pixelsG, pixelsB); } bitmap.setPixels(newPixels, 0, width, 0, 0, width, height); return bitmap; }
图片浮雕效果
浮雕的算法原理是:用前一个像素点的RGB值分别减去当前像素点的RGB值并加上127作为当前像素点的RGB值。
下面是浮雕效果的结果截图:
下面是浮雕效果的示例代码:
// 图片浮雕效果 public static Bitmap relief(Bitmap bmp) { /* * 算法原理:(前一个像素点RGB-当前像素点RGB+127)作为当前像素点RGB值 在ABC中计算B点浮雕效果(RGB值在0~255) * B.r = C.r - B.r + 127 B.g = C.g - B.g + 127 B.b = C.b - B.b + 127 */ int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixColor = 0; int pixR = 0; int pixG = 0; int pixB = 0; int newR = 0; int newG = 0; int newB = 0; int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 1; i < height - 1; i++) { for (int k = 1; k < width - 1; k++) { // 获取前一个像素颜色 pixColor = pixels[width * i + k]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); // 获取当前像素 pixColor = pixels[(width * i + k) + 1]; newR = Color.red(pixColor) - pixR + 127; newG = Color.green(pixColor) - pixG + 127; newB = Color.blue(pixColor) - pixB + 127; newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); pixels[width * i + k] = Color.argb(255, newR, newG, newB); } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; }
图片模糊效果
要让一张图片变得模糊起来,基本原理是每个点的颜色都是附近一片像素的颜色综合得到,这样图片中每个景物的边缘就变得模糊了。
下面是模糊效果的结果截图:
下面是模糊效果的示例代码:
/** 水平方向模糊度 */ private static float hRadius = 10; /** 竖直方向模糊度 */ private static float vRadius = 10; /** 模糊迭代度 */ private static int iterations = 7; // 图片模糊效果。该算法比较明显 public static Bitmap blur(Bitmap bmp) { int width = bmp.getWidth(); int height = bmp.getHeight(); int[] inPixels = new int[width * height]; int[] outPixels = new int[width * height]; Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); bmp.getPixels(inPixels, 0, width, 0, 0, width, height); for (int i = 0; i < iterations; i++) { blur(inPixels, outPixels, width, height, hRadius); blur(outPixels, inPixels, height, width, vRadius); } blurFractional(inPixels, outPixels, width, height, hRadius); blurFractional(outPixels, inPixels, height, width, vRadius); bitmap.setPixels(inPixels, 0, width, 0, 0, width, height); return bitmap; } public static void blur(int[] in, int[] out, int width, int height, float radius) { int widthMinus1 = width - 1; int r = (int) radius; int tableSize = 2 * r + 1; int divide[] = new int[256 * tableSize]; for (int i = 0; i < 256 * tableSize; i++) { divide[i] = i / tableSize; } int inIndex = 0; for (int y = 0; y < height; y++) { int outIndex = y; int ta = 0, tr = 0, tg = 0, tb = 0; for (int i = -r; i <= r; i++) { int rgb = in[inIndex + clamp(i, 0, width - 1)]; ta += (rgb >> 24) & 0xff; tr += (rgb >> 16) & 0xff; tg += (rgb >> 8) & 0xff; tb += rgb & 0xff; } for (int x = 0; x < width; x++) { out[outIndex] = (divide[ta] << 24) | (divide[tr] << 16) | (divide[tg] << 8) | divide[tb]; int i1 = x + r + 1; if (i1 > widthMinus1) { i1 = widthMinus1; } int i2 = x - r; if (i2 < 0) { i2 = 0; } int rgb1 = in[inIndex + i1]; int rgb2 = in[inIndex + i2]; ta += ((rgb1 >> 24) & 0xff) - ((rgb2 >> 24) & 0xff); tr += ((rgb1 & 0xff0000) - (rgb2 & 0xff0000)) >> 16; tg += ((rgb1 & 0xff00) - (rgb2 & 0xff00)) >> 8; tb += (rgb1 & 0xff) - (rgb2 & 0xff); outIndex += height; } inIndex += width; } } public static void blurFractional(int[] in, int[] out, int width, int height, float radius) { radius -= (int) radius; float f = 1.0f / (1 + 2 * radius); int inIndex = 0; for (int y = 0; y < height; y++) { int outIndex = y; out[outIndex] = in[0]; outIndex += height; for (int x = 1; x < width - 1; x++) { int i = inIndex + x; int rgb1 = in[i - 1]; int rgb2 = in[i]; int rgb3 = in[i + 1]; int a1 = (rgb1 >> 24) & 0xff; int r1 = (rgb1 >> 16) & 0xff; int g1 = (rgb1 >> 8) & 0xff; int b1 = rgb1 & 0xff; int a2 = (rgb2 >> 24) & 0xff; int r2 = (rgb2 >> 16) & 0xff; int g2 = (rgb2 >> 8) & 0xff; int b2 = rgb2 & 0xff; int a3 = (rgb3 >> 24) & 0xff; int r3 = (rgb3 >> 16) & 0xff; int g3 = (rgb3 >> 8) & 0xff; int b3 = rgb3 & 0xff; a1 = a2 + (int) ((a1 + a3) * radius); r1 = r2 + (int) ((r1 + r3) * radius); g1 = g2 + (int) ((g1 + g3) * radius); b1 = b2 + (int) ((b1 + b3) * radius); a1 *= f; r1 *= f; g1 *= f; b1 *= f; out[outIndex] = (a1 << 24) | (r1 << 16) | (g1 << 8) | b1; outIndex += height; } out[outIndex] = in[width - 1]; inIndex += width; } } public static int clamp(int x, int a, int b) { return (x < a) ? a : (x > b) ? b : x; }
图片锐化效果
锐化与模糊是相反的,模糊要让景物的边缘变得模糊不清,而锐化则加强图像中景物的边缘和轮廓,从而让景物的边缘变得更加清晰和锐利。
下面是锐化效果的结果截图:
下面是锐化效果的示例代码:
// 图像锐化效果。拉普拉斯算子处理 public static Bitmap sharpen(Bitmap bmp) { /* * 锐化基本思想是加强图像中景物的边缘和轮廓,使图像变得清晰 而图像平滑是使图像中边界和轮廓变得模糊 * 拉普拉斯算子图像锐化 获取周围9个点的矩阵乘以模板9个的矩阵 卷积 * 拉普拉斯算子模板 { 0, -1, 0, -1, -5, -1, 0, -1, 0 } { -1, -1, -1, -1, 9, -1, -1, -1, -1 } */ int[] laplacian = new int[] { -1, -1, -1, -1, 9, -1, -1, -1, -1 }; int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixR = 0; int pixG = 0; int pixB = 0; int pixColor = 0; int newR = 0; int newG = 0; int newB = 0; int idx = 0; float alpha = 0.3F;// 图片透明度 int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); // 图像处理 for (int i = 1; i < height - 1; i++) { for (int k = 1; k < width - 1; k++) { idx = 0; newR = 0; newG = 0; newB = 0; for (int n = -1; n <= 1; n++) { // 取出图像3*3领域像素 for (int m = -1; m <= 1; m++) { // n行数不变 m列变换 pixColor = pixels[(i + n) * width + k + m];// 当前点(i,k) pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); // 图像像素与对应摸板相乘 newR = newR + (int) (pixR * laplacian[idx] * alpha); newG = newG + (int) (pixG * laplacian[idx] * alpha); newB = newB + (int) (pixB * laplacian[idx] * alpha); idx++; } } newR = Math.min(255, Math.max(0, newR)); newG = Math.min(255, Math.max(0, newG)); newB = Math.min(255, Math.max(0, newB)); // 赋值 pixels[i * width + k] = Color.argb(255, newR, newG, newB); } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; }
图片黑白效果
黑白照片对于彩色照片来说,就好比黑白电视机之于彩色电视机,黑白照片只有灰度的深浅区别,而没有红绿蓝之分。
下面是黑白效果的结果截图:
下面是效果的示例代码:
// 图片黑白效果 public static Bitmap black(Bitmap bmp) { int width = bmp.getWidth(); // 获取位图的宽 int height = bmp.getHeight(); // 获取位图的高 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int[] pixels = new int[width * height]; // 通过位图的大小创建像素点数组 bmp.getPixels(pixels, 0, width, 0, 0, width, height); int alpha = 0xFF << 24; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { int grey = pixels[width * i + j]; int red = ((grey & 0x00FF0000) >> 16); int green = ((grey & 0x0000FF00) >> 8); int blue = (grey & 0x000000FF); grey = (int) (red * 0.3 + green * 0.59 + blue * 0.11); grey = alpha | (grey << 16) | (grey << 8) | grey; pixels[width * i + j] = grey; } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; }
图片冰冻效果
冰冻算法对于每个像素来说,RGB值都是当前色素值减去其余两个色素之和,由于现实生活中的暖色调偏红偏黄(比如说肤色、肉色等等),因此计算出来的颜色就偏蓝了。说白了,冰冻效果就是对色调取反,原来是暖色调就变为冷色调,原来是冷色调就变为暖色调。
下面是冰冻效果的结果截图:
下面是冰冻效果的示例代码:
// 图片冰冻效果 public static Bitmap ice(Bitmap bmp) { int width = bmp.getWidth(); int height = bmp.getHeight(); Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); int pixColor = 0; int pixR = 0; int pixG = 0; int pixB = 0; int newColor = 0; int newR = 0; int newG = 0; int newB = 0; int[] pixels = new int[width * height]; bmp.getPixels(pixels, 0, width, 0, 0, width, height); for (int i = 0; i < height; i++) { for (int k = 0; k < width; k++) { // 获取前一个像素颜色 pixColor = pixels[width * i + k]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); // 红色 newColor = pixR - pixG - pixB; newColor = newColor * 3 / 2; if (newColor < 0) { newColor = -newColor; } if (newColor > 255) { newColor = 255; } newR = newColor; // 绿色 newColor = pixG - pixB - pixR; newColor = newColor * 3 / 2; if (newColor < 0) { newColor = -newColor; } if (newColor > 255) { newColor = 255; } newG = newColor; // 蓝色 newColor = pixB - pixG - pixR; newColor = newColor * 3 / 2; if (newColor < 0) { newColor = -newColor; } if (newColor > 255) { newColor = 255; } newB = newColor; pixels[width * i + k] = Color.argb(255, newR, newG, newB); } } bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; }
图片素描效果
现实生活中的素描画,都是一根根黑线条描绘出景物的轮廓,所以图片的素描算法,便是提取出景物的轮廓,然后用黑色线条画出来。
下面是素描效果的结果截图:
下面是素描效果的示例代码:
// 图片素描效果 public static Bitmap sketch(Bitmap bmp) { // 创建新Bitmap int width = bmp.getWidth(); int height = bmp.getHeight(); int[] pixels = new int[width * height]; // 存储变换图像 int[] linpix = new int[width * height]; // 存储灰度图像 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); bmp.getPixels(pixels, 0, width, 0, 0, width, height); int pixColor = 0; int pixR = 0; int pixG = 0; int pixB = 0; // 灰度图像 for (int i = 1; i < width - 1; i++) { for (int j = 1; j < height - 1; j++) { // 拉普拉斯算子模板 { 0, -1, 0, -1, -5, -1, 0, -1, 0 // 获取前一个像素颜色 pixColor = pixels[width * j + i]; pixR = Color.red(pixColor); pixG = Color.green(pixColor); pixB = Color.blue(pixColor); // 灰度图像 int gray = (int) (0.3 * pixR + 0.59 * pixG + 0.11 * pixB); linpix[width * j + i] = Color.argb(255, gray, gray, gray); // 图像反向 gray = 255 - gray; pixels[width * j + i] = Color.argb(255, gray, gray, gray); } } int radius = Math.min(width / 2, height / 2); int[] copixels = gaussBlur(pixels, width, height, 10, 10 / 3); // 高斯模糊 // 采用半径10 int[] result = colorDodge(linpix, copixels); // 素描图像 颜色减淡 bitmap.setPixels(result, 0, width, 0, 0, width, height); return bitmap; } // 高斯模糊 public static int[] gaussBlur(int[] data, int width, int height, int radius, float sigma) { float pa = (float) (1 / (Math.sqrt(2 * Math.PI) * sigma)); float pb = -1.0f / (2 * sigma * sigma); // generate the Gauss Matrix float[] gaussMatrix = new float[radius * 2 + 1]; float gaussSum = 0f; for (int i = 0, x = -radius; x <= radius; ++x, ++i) { float g = (float) (pa * Math.exp(pb * x * x)); gaussMatrix[i] = g; gaussSum += g; } for (int i = 0, length = gaussMatrix.length; i < length; ++i) { gaussMatrix[i] /= gaussSum; } // x direction for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { float r = 0, g = 0, b = 0; gaussSum = 0; for (int j = -radius; j <= radius; ++j) { int k = x + j; if (k >= 0 && k < width) { int index = y * width + k; int color = data[index]; int cr = (color & 0x00ff0000) >> 16; int cg = (color & 0x0000ff00) >> 8; int cb = (color & 0x000000ff); r += cr * gaussMatrix[j + radius]; g += cg * gaussMatrix[j + radius]; b += cb * gaussMatrix[j + radius]; gaussSum += gaussMatrix[j + radius]; } } int index = y * width + x; int cr = (int) (r / gaussSum); int cg = (int) (g / gaussSum); int cb = (int) (b / gaussSum); data[index] = cr << 16 | cg << 8 | cb | 0xff000000; } } // y direction for (int x = 0; x < width; ++x) { for (int y = 0; y < height; ++y) { float r = 0, g = 0, b = 0; gaussSum = 0; for (int j = -radius; j <= radius; ++j) { int k = y + j; if (k >= 0 && k < height) { int index = k * width + x; int color = data[index]; int cr = (color & 0x00ff0000) >> 16; int cg = (color & 0x0000ff00) >> 8; int cb = (color & 0x000000ff); r += cr * gaussMatrix[j + radius]; g += cg * gaussMatrix[j + radius]; b += cb * gaussMatrix[j + radius]; gaussSum += gaussMatrix[j + radius]; } } int index = y * width + x; int cr = (int) (r / gaussSum); int cg = (int) (g / gaussSum); int cb = (int) (b / gaussSum); data[index] = cr << 16 | cg << 8 | cb | 0xff000000; } } return data; } // 颜色减淡 public static int[] colorDodge(int[] baseColor, int[] mixColor) { for (int i = 0, length = baseColor.length; i < length; ++i) { int bColor = baseColor[i]; int br = (bColor & 0x00ff0000) >> 16; int bg = (bColor & 0x0000ff00) >> 8; int bb = (bColor & 0x000000ff); int mColor = mixColor[i]; int mr = (mColor & 0x00ff0000) >> 16; int mg = (mColor & 0x0000ff00) >> 8; int mb = (mColor & 0x000000ff); int nr = colorDodgeFormular(br, mr); int ng = colorDodgeFormular(bg, mg); int nb = colorDodgeFormular(bb, mb); baseColor[i] = nr << 16 | ng << 8 | nb | 0xff000000; } return baseColor; } private static int colorDodgeFormular(int base, int mix) { int result = base + (base * mix) / (255 - mix); result = result > 255 ? 255 : result; return result; }