图像处理
画马赛克之前先来点知识储备
图像原理:
像素 :是由图像的小方格组成的,每一个小方块都有一个明显的位置和被分配的色彩数值,小方格的颜色和位置就决定该图像所呈现出来的样子(以上来自科普中国)。 分辨率:每英寸上的像素数量,单位时DPI。像素相同时,分辨率越高,则像素密度越大,实际打印的尺寸越小,图像也就越清晰。 RGB颜色模型:是一种加色模型,将红(Red)、绿(Green)、蓝(Blue)三原色的色光以不同的比例相加,以合成产生各种色彩光,共有256256256种颜色。 灰度图像:指r,g,b三个分量都相同,一般取平均值进行处理。 像素矩阵:对于一幅图像,可以把它看成一个二维数组(图像=[i][j]),对于每一个int值,就是这个点的像素值。 所以,图像处理的本质其实就是对代表图像的二维数组中的值进行处理
像素值的存储
我们知道,其实计算机都是用二进制数处理数据的,int类型有32位,byte是8位,每种原色的数量正好是一个8位,所以我们把像素值存储在一个int类型的数据中。 0000 0000 24~32位 0000 0000 16~24位,用来存储red的值 0000 0000 8~16位 ,用来存储green的值 0000 0000 0~8位,用来存储blue的值 那具体怎么存取呢?这里要用到移位操作符和位运算操作符:
移位操作符
左移 << (低位补0);右移 >>(符号位不变)
位运算操作符
&:位与,“相同保留,不同为1”; |:位或,“只有都为0时才为0”;
取数据
将二进制数据移动相应的位数,然后只取第八位的数值就可以了。如何做到只取低八位的数呢? 对0xFF(低八位全为1的数)进行位与运算。
int red=(rgb >> 16) & 0xFF;
int green=(rgb >> 8) & 0xFF;
int blue=(rgb >> 0) & 0xFF;
存数据
int rgb= ((225 & 0xFF) << 24 |
(red & 0xFF) << 16 |
(green & 0xFF)<< 8 |
(blue & 0xFF) << 0);
接下来我们就画一个马赛克吧!
package Paint0924;
import java.awt.Color;
import java.awt.Graphics;
import java.util.Random;
import javax.swing.JFrame;
public class Paint extends JFrame{
public static void main(String[] args) {
Paint p=new Paint();
p.UI();
}
public void UI() {
this.setTitle("mosaic");
this.setSize(700,500);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(3);
this.setResizable(false);
this.setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
System.out.println("开始画图");
int color[][]=new int[700][500];
Random ra=new Random();
for(int i=0;i<700;i+=25) {
for(int j=0;j<500;j+=25) {
int red=ra.nextInt(256);
int green=ra.nextInt(256);
int blue=ra.nextInt(256);
int value=((255 & 0xFF)<<24 |
(red & 0xFF)<<16 |
(green & 0xFF)<<8 |
(blue & 0xFF)<<0);
color[i][j]=value;
}
}
for(int i=0;i<700;i+=25) {
for(int j=0;j<500;j+=25) {
int value=color[i][j];
int red=(value>>16) & 0xFF;
int green=(value>>8) & 0xFF;
int blue=(value>>0) & 0xFF;
int gray=(red+green+blue)/3;
System.out.println(gray);
Color co2=new Color(gray,gray,gray);
g.setColor(co2);
g.fillRect(i, j, 25, 25);
}
}
}
}
程序运行效果如下: 另外,我们还可以画一些比较有意思的图片,比如,只要在遍历数组那儿稍微改动一下
for(int i=0;i<700;i+=2) {
for(int j=0;j<500;j+=2) {
Color co=new Color(color[i][j]);
g.setColor(co);
g.fillRect(i, j, 2, 2);
}
}
图片就会是:
我们来尝试一下做一个简单的调色板 代码及思路如下
public class Palette {
public static void main(String[] args) {
Palette p=new Palette();
p.UI();
}
class Colorchange implements ChangeListener,MouseListener{
public void mousePressed(MouseEvent e) {
int R=Integer.parseInt(red.getText());
int G=Integer.parseInt(green.getText());
int B=Integer.parseInt(blue.getText());
s1.setValue(R);
s2.setValue(G);
s3.setValue(B);
}
public void stateChanged(ChangeEvent e) {
int R=s1.getValue();
int G=s2.getValue();
int B=s3.getValue();
j.setBackground(new Color(R,G,B));
}
public void mouseClicked(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
JPanel jp1=new JPanel();
JLabel j1=new JLabel("R");
JLabel j2=new JLabel("G");
JLabel j3=new JLabel("B");
JTextField red=new JTextField();
JTextField green=new JTextField();
JTextField blue=new JTextField();
JSlider s1=new JSlider();
JSlider s2=new JSlider();
JSlider s3=new JSlider();
JButton j=new JButton();
JFrame jf=new JFrame();
public void UI() {
jf.setTitle("color_palette");
jf.setSize(700,500);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(3);
jf.setLayout(null);
s1.setMaximum(255);
s2.setMaximum(255);
s3.setMaximum(255);
Colorchange c=new Colorchange();
s1.addChangeListener(c);
s2.addChangeListener(c);
s3.addChangeListener(c);
red.addMouseListener(c);
green.addMouseListener(c);
blue.addMouseListener(c);
jp1.add(j1);
jp1.add(s1);
jp1.add(j2);
jp1.add(s2);
jp1.add(j3);
jp1.add(s3);
j.setBounds(0, 100, 700, 400);
jp1.setBounds(0, 0, 700, 100);
jf.add(jp1);
jf.add(j);
jf.setVisible(true);
}
}
程序运行结果如下:
界面有点丑哈~
|