美颜相机项目或者Photoshop的核心就是图像处理。
想要处理图像,首先需要了解图片是怎么在计算机中实现的,即图片原理。
一张图片是由很多具备色彩种类、亮度等级等信息的 基本像素点 所组成的。
每一个像素的颜色由红Red、绿Green、蓝Blue三种基本颜色组成,和美术中的不同。每种颜色的亮度范围是0-255。
颜色的数据大小为1int , 1int = 4 byte = 32bit
颜色1int 表示为二进制 : 0000 0000 0000 0000 0000 0000 0000 0000
其中从右到左: 1-8 位 为 蓝色 ;9-16 位 为 绿色 ;17-24 位 为 红色 ;25-32位 为 透明度
int类型的数据可以直接作为color的参数,当你想使用或者操作其中一种颜色的亮度时该怎么办呢?这时候需要用到位移操作和二进制逻辑运算中的与&操作,将对应颜色位数的值给取出。(位移操作和二进制逻辑运算符不会的小伙伴可以去搜一搜基础的教程呢)
举个例子,当想取出红色的值,即 17-24 位的值。
0000 0000 1000 0000 1000 0000 1000 0000 >> 8 //右移8位
= 0000 0000 0000 0000 1000 0000 1000 0000
0000 0000 0000 0000 1000 0000 1000 0000 & 0000 0000 0000 0000 0000 0000 1111 1111
= 0000 0000 0000 0000 0000 0000 1000 0000
另外两种颜色同理可得。
用代码的形式展示一下 像素的整数值 转 三原色红 绿 蓝 的值:
public void pixelToRGB(){
int num = 8421504;
int red = (num >> 16) & 0xFF;
System.out.println (red);
//与示例相同,想要取得绿色,先右移8位,再进行二进制的与&运算
int green = (num >> 8) & 0xFF;
System.out.println (green);
int blue = (num >> 0) & 0xFF;
System.out.println (blue);
}
了解了图像原理之后,图像处理的理解就变得容易了很多。
图像是像素值得矩阵,处理图像就是处理矩阵每一个值。
为了演示如何处理图像,我们先自己绘制一个马赛克mosaic图像吧
public int[][] mosaic(Graphics g){
//创建一个随机数ran
Random ran = new Random ();
//创建一个500*500的二维数组 imgarr
int[][] imgarr = new int[500][500];
//遍历imgarr数组,将随机数 ran 赋值给数组每一个位置
for(int i = 0; i < 500; i ++){
for(int j = 0; j < 500; j ++){
//Integer.MAX_VALUE表示int数据类型的最大取值数:2 147 483 647
imgarr[i][j] = ran.nextInt (Integer.MAX_VALUE);
//创建int数值对应的颜色color
Color color = new Color (imgarr[i][j]);
//设置画笔颜色为color,画出此位置的像素
g.setColor (color);
g.fillRect (i, j, 1, 1);
}
}
return imgarr;
}
绘制了马赛克图像之后,我们来试着处理一下,先做一个简单的黑白图像吧。
运用图像原理中介绍的方法将储存在 imgarr 数组中的int值拆分为三原色及其各自的亮度。
三原色的亮度值的平均值称为 灰度,当灰度大于一定值的像素画成黑色,反之为白色,就实现了黑白特效。
public void blackAndWhite(int[][] imgarr, Graphics g){
for(int i = 0; i < imgarr.length; i++){
for(int j = 0; j < imgarr[i].length; j++){
// 取出imgarr中的像素值,保存在 i1 中
int i1 = imgarr[i][j];
// 拆分为 三原色值
int red = (i1 >> 16) & 0xFF;
int green = (i1 >> 8) & 0xFF;
int blue = (i1 >> 0) & 0xFF;
// 绝大多数的滤镜都是操作三原色及其亮度得到的
// gray r=g=b 整个图片就会失去彩色 黑 白 灰度
int gray = (red + green + blue) / 3;
// 按照灰度 黑白化图片
if(gray < 50){
g.setColor (Color.BLACK);
} else{
g.setColor (Color.WHITE);
}
g.fillRect (550 + i, j+100, 1, 1);
}
}
}
如果我们想处理一张文件图片,我们需要将文件图片先缓存成图片对象。
将磁盘中的数据缓存为内存中的对象。
public BufferedImage getImage(String path){
// 根据指定文件路径 创建文件对象
File file = new File (path);
// 先声明一个缓冲图片 img
BufferedImage img = null;
try {
// IO操作 读取到的缓冲图片对象赋给 img
img = ImageIO.read (file);
} catch (IOException e) {
e.printStackTrace ();
}
// 方法返回值 img 对象
return img;
}
再将内存中缓冲的图片对象 转换为 存有像素值的二维数组
public int[][] getImageArray(BufferedImage img){
// 根据图片的宽高 初始化一个二维数组
int[][] imgarr = new int[img.getWidth ()][img.getHeight ()];
// img 对象可以调用的方法
// 遍历存入 img 对象中取出的像素值
for(int i = 0; i < img.getWidth (); i++){
for(int j = 0; j < img.getHeight (); j++){
int rgb = img.getRGB (i, j);
imgarr[i][j] = rgb;
}
}
// 返回 二维数组
return imgarr;
}
如果想直接显示图片,可以直接绘制原图,调用g.drawImage(img,x,y,width,hight,observer),也可以调用我们封装好的getImageArray方法,遍历二维数组画出。之前黑白图片的方法也封装好了,也可以在此直接调用用来黑白图片。
public void paint(Graphics g){
super.paint(g);
BufferedImage img=getImage("C:\\Users\\ZLYLF\\Desktop\\****.jpg");
// 直接绘制原图
g.drawImage(img,0,100,null);
// 遍历二维数组来绘制图片
int[][]imageArray=getImageArray(img);
// 绘制滤镜
blackAndWhite(imageArray,g);
}
学习了图像原理和图像处理的方法,和黑白特效的示例。很多简单的特效都可以动手实现了,比如灰度、油画、锐化、美白等等,并且更高级的图像算法和图像识别也可以了解和深入学习。
美颜相机的项目框架,以及更多好玩有趣的特效的源码和效果都在下面下面这篇文章里哦!
Java程序结构模板——美颜相机案例_龙与少年LYH的博客-CSDN博客我们以美颜相机举例,分析一个程序都需要什么。1、UI界面:大部分需要交互的程序都需要UI界面来实现交流互动。2、监听器:人们在UI中的操作需要监听器来捕捉和执行相应的命令。3、工具类:将执行命令的方法单独封装成工具类,供监听器调用。https://blog.csdn.net/weixin_47349244/article/details/123757487?spm=1001.2014.3001.5502