图片特效用到的函数

本文讲述的图片特效处理包括:怀旧、光照、光晕、底片、浮雕、模糊、锐化、黑白、冰冻、素描,所有这些特效都是基于一定的算法,对图像每个点的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-150int[] 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大于等于0if (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) {// 创建新Bitmapint 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); // 高斯模糊// 采用半径10int[] 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 Matrixfloat[] 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 directionfor (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 directionfor (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;}

点击下载本文用到的图片特效处理的工程代码

点此查看Android开发笔记的完整目录

Android开发笔记(九十七)图片的特效处理相关推荐

  1. Android开发笔记(十七)GIF动画的实现GifAnimation

    GIF在Windows上是常见的图片格式,主要用来播放短小的动画.但在手机上由于系统资源紧张,所以Android并没有直接支持GIF格式,如果在ImageView中放入一张gif文件,你会发现显示出来 ...

  2. Android开发笔记(序)写在前面的目录

    知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教训,与网友互相切磋,从而去芜存菁进一步提升自己的水平.因此博主就想,入门的东西咱就不写了,人不能老停留在入 ...

  3. Android开发笔记(序)

    本开发笔记,借鉴与其他开发者整理的文章范例与心得体会.在这里作为开发过程中的一个总结与笔记式记录. 如有侵犯作者权益,请及时联系告知删除.俗话说:集百家成一言,去粕成金. ************** ...

  4. Android开发笔记(序)写在前面的目录大全

    转自  湖前琴亭 的博客https://blog.csdn.net/aqi00/article/details/50012511 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面 ...

  5. Andriod开发之二十:Android开发笔记(序)写在前面的目录

    https://blog.csdn.net/aqi00/article/details/50038385 知识点分类 一方面写写自己走过的弯路掉进去的坑,避免以后再犯:另一方面希望通过分享自己的经验教 ...

  6. Android开发笔记(七十七)图片缓存算法

    ImageCache 由于手机流量有限,又要加快app的运行效率,因此好的app都有做图片缓存.图片缓存说起来简单,做起来就用到很多知识点,可算是集Android技术之大全了.只要理解图片缓存的算法, ...

  7. Android开发笔记(九)特别的.9图片

    为什么使用.9图片 .9图片的扩展名是png,文件名后常带有".9"字样,因为它把一个png图片划分为3*3的九宫格来分别处理,所以得名.9图片..9.png是Android开发中 ...

  8. Android开发笔记(八十九)单例模式

    基本概念 单例模式是一种常用的软件设计模式,它确保一个类只有一个实例,从而方便对实例个数的控制并节约系统资源. 单例模式有三个特点: 1.某个类只能有一个实例: 2.它要自行创建这个实例: 3.它只有 ...

  9. Android开发笔记(七十九)资源与权限校验

    硬件资源 因为移动设备的硬件配置各不相同,为了防止使用了不存在的设备资源,所以要对设备的硬件情况进行检查.一般情况下,前置摄像头.部分传感器在低端手机上是没有的,像SD卡也可能因为用户没插卡使得找不到 ...

最新文章

  1. 200字带你看完一本书,GPT-3已经会给长篇小说写摘要了
  2. php自动配置ip,使用PHP自动PING IP
  3. [Java基础]SimpleDateFormat类基础
  4. 90行代码让微信地球转起来,太酷了!(python实现)
  5. 终于换了杀毒工具(NOD32教育网升级)
  6. 如何快速上手使用STM32库函数
  7. SpringBoot整合jsp的使用
  8. 运维系统 联想服务器,联想IT综合运维平台解决方案.pdf
  9. java+jdk+1.6+下载_jdk1.6下载_jdk1.6官方下载「32位|64位」-太平洋下载中心
  10. “缺少winload.efi”的解决办法“:Windows Boot Manager更改读取启动信息路径
  11. php截取部分pdf,如何将一个pdf文档拆分成多个
  12. Python学习笔记3——条件语句及循环语句
  13. SpringBoot应用接入Prometheus+Grafana
  14. python手机端如何下载_过去,哔哩哔哩上面的视频只能在手机上面下载;现在,我用Python爬虫实现了能在PC端上面下载...
  15. windows添加右键打开cmd命令窗口
  16. 【刷题2022/5/3 用时160min】
  17. 《自然杂志》19卷4期的 ‘探索物理学难题的科学意义'的 97个悬而未决的难题
  18. CIO应具备的基本素质要求(zt)
  19. 睿备份支持linux,【睿备份怎么用】睿备份好不好_使用技巧-ZOL软件百科
  20. mysql与access区别_access与mysql的区别

热门文章

  1. 吴恩达机器学习之逻辑回归理论部分
  2. 大数据行业到底有多少种工作岗位,各自的技能需求是什么?
  3. BOM模型中常用对象 定义计数器 网页跳转 网页前进后退
  4. Nginx内置模块简介
  5. innobackupex参数之 --throttle 限速这个值设置多少合理 原创
  6. LeetCode刷题(6)
  7. python数据分析平均时间间隔_Python数据分析中,如何把数值如(1511544070)转换成常规的时间格式?...
  8. 卷积神经网络流程图_基于卷积神经网络的叶片气孔自动计数方法
  9. 若依集成ueditor富文本编辑器
  10. Web 端 js 导出csv文件(使用a标签)