图片特效用到的函数
本文讲述的图片特效处理包括:怀旧、光照、光晕、底片、浮雕、模糊、锐化、黑白、冰冻、素描,所有这些特效都是基于一定的算法,对图像每个点的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 (ibottom || jright) {
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;
}
点击下载本文用到的图片特效处理的工程代码
点此查看Android开发笔记的完整目录