package com.example.test.qtest;
import android.graphics.Bitmap;
import android.graphics.Color;
/**
* Created by scq on 17-2-13.
*/
public class ImageProcessEffect {
/**
* 底片效果
*
* ABC3个像素点
* 求B点的底片效果算法:
* B.r = 255 - B.r;
* B.g = 255 - B.g;
* B.b = 255 - B.b;
*/
public Bitmap filmEffect(Bitmap bm) {
//返回的就是像素点个数
int width = bm.getWidth();
int height = bm.getHeight();
int color; //用于存储当前取出来的颜色
int r, g, b ,a;//用于保存颜色中取出来的四个分量
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
//保存像素点数组到图像
int[] oldPx = new int[width * height];
int[] newPx = new int[width * height];
//第三个参数 stride 多少个算一行 一般为width
bm.getPixels(oldPx, 0, width, 0, 0, width, height);
for (int i = 0; i < width * height; i++) {
color = oldPx[i];
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);
r = 255 - r;
g = 255 - g;
b = 255 - b;
if (r > 255) {
r = 255;
} else if (r < 0) {
r = 0;
}
if (g > 255) {
g = 255;
} else if (g < 0) {
g = 0;
}
if (b > 255) {
b = 255;
} else if (b < 0) {
b = 0;
}
newPx[i] = Color.argb(a, r, g, b);
}
bmp.setPixels(newPx, 0, width, 0, 0, width, height);
return bmp;
}
/**
* 怀旧效果
*
* 求像素点的老照片效果算法
* 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);
*/
public Bitmap nostalgicEffect(Bitmap bm) {
int width = bm.getWidth();
int height = bm.getHeight();
int color = 0;
int r, g, b, a, r1, b1, g1;
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
int[] oldPx = new int[width * height];
int[] newPx = new int[width * height];
bm.getPixels(oldPx, 0, width, 0, 0, width, height);
for (int i = 0; i < width * height; i++) {
color = oldPx[i];
r = Color.red(color);
g = Color.green(color);
b = Color.blue(color);
a = Color.alpha(color);
r1 = (int) (0.393 * r + 0.769 * g + 0.189 * b);
g1 = (int) (0.349 * r + 0.686 * g + 0.168 * b);
b1 = (int) (0.272 * r + 0.534 * g + 0.131 * b);
if (r1 > 255) {
r1 = 255;
}
if (g1 > 255) {
g1 = 255;
}
if (b1 > 255) {
b1 = 255;
}
newPx[i] = Color.argb(a, r1, g1, b1);
}
bmp.setPixels(newPx, 0, width, 0, 0, width, height);
return bmp;
}
/**
* 浮雕效果
*
* ABC
* 求B点的浮雕效果算法:
* B.r = C.r - B.r + 127
* B.g = C.g - B.g + 127
* B.r = C.b - B.b + 127
*/
public Bitmap reliefEffect(Bitmap bm) {
int width = bm.getWidth();
int height = bm.getHeight();
int color = 0;
int colorBefore = 0;
int r, g, b, a;
int r1, b1, g1;
int oldPx[] = new int[width * height];
int newPx[] = new int[width * height];
Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bm.getPixels(oldPx, 0, width, 0, 0, width, height);
//注意要从1开始!!!
for (int i = 1; i < width * height; i++) {
colorBefore = oldPx[i - 1];
a = Color.alpha(colorBefore);
r = Color.red(colorBefore);
g = Color.green(colorBefore);
b = Color.blue(colorBefore);
color = oldPx[i];
r1 = Color.red(color);
g1 = Color.green(color);
b1 = Color.blue(color);
r = r - r1 + 127;
g = g - g1 + 127;
b = b - b1 + 127;
if (r > 255) {
r = 255;
}
if (g > 255) {
g = 255;
}
if (b > 255) {
b = 255;
}
newPx[i] = Color.argb(a, r, g, b);
}
bmp.setPixels(newPx, 0, width, 0, 0, width, height);
return bmp;
}
/**
* 模糊效果
*
* 算法原理:
* 简单算法将像素周围八个点包括自身共九个点RGB值分别相加后平均,当前像素点的RGB值
* 复杂算法采用高斯模糊
* 高斯矩阵 int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };
* 将九个点的RGB值分别与高斯矩阵中的对应项相乘的和,再除以一个相应的值作为当前像素点的RGB
*/
public Bitmap blurEffect(Bitmap bmp){
int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 }; // 高斯矩阵
int delta = 15; // 除以值 值越小图片会越亮,越大则越暗
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, newG, newB;
int pos = 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++) {
pos = 0;
newR = 0;
newG = 0;
newB = 0;
for (int m = -1; m <= 1; m++) //宽不变
{
for (int n = -1; n <= 1; n++) //高先变
{
pixColor = pixels[(i + m) * width + k + n];
pixR = Color.red(pixColor);
pixG = Color.green(pixColor);
pixB = Color.blue(pixColor);
//3*3像素相加
newR = newR + (int) (pixR * gauss[pos]);
newG = newG + (int) (pixG * gauss[pos]);
newB = newB + (int) (pixB * gauss[pos]);
pos++;
}
}
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 + k] = Color.argb(255, newR, newG, newB);
}
}
bitmap.setPixels(pixels, 0, width, 0, 0, width, height);
return bitmap;
}
/**
* 光照效果
*
* 算法原理:(前一个像素点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
* 光照中心取长宽较小值为半径,也可以自定义从左上角射过来
*/
public Bitmap lightingEffect(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 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;
}
/**
* 锐化效果 拉普拉斯算子处理
*
* 算法原理:
* 锐化基本思想是加强图像中景物的边缘和轮廓,使图像变得清晰
* 而图像平滑是使图像中边界和轮廓变得模糊
*
* 拉普拉斯算子图像锐化
* 获取周围9个点的矩阵乘以模板9个的矩阵 卷积
*/
public Bitmap sharpeningEffect(Bitmap bmp) {
//拉普拉斯算子模板 { 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 Bitmap frozenEffect(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 Bitmap sketchEffect(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;
int newR = 0;
int newG = 0;
int newB = 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 * i + j];
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 * i + j] = Color.argb(255, gray, gray, gray);
//图像反向
gray=255-gray;
pixels[width * i + j] = 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;
}
// 颜色减淡
private 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;
}
}
几种图片处理效果的整理应用
最新推荐文章于 2022-10-26 11:39:45 发布