以位图的方式保存画板
一、 与自定义队列保存的不同点:
与前面用自定义对队列保存文件的方式不同,以位图方式保存是指在保存图片时,文件保存时不再记录所绘的各个形状,而是将画图的区域直接抓取下来,并记录各点的颜色;文件打开时也不再从数组中将各个形状对象逐个去处,而是在画图区域将与背景色不同的像素点以画图的颜色显现出来。
二、 这种文件保存方式的优势
如果用自定义队列进行图片的保存,在画图区域画上一条线与画一千条线所存储的数据量不同,其所占用的内存空间也不同,而且在重绘和打开图片时程序要从队列中将保存的对象按照原来存储的顺序,逐个去处。因此当所存储的对象的数目较大时,就会使打开图片和重绘的时间大大延长;而采用位图方式保存图片文件,每次都是将绘图区域内个像素的颜色记录下来,重回和打开时只是将与背景色不同的颜色显现出来,因此无论在画图区域有多少对象,其存储的数据量都是相同的,打开时的时间也基本相同。
三、 该方式的简单实现:
1、 与自定义队列放是保存图片相同,需要在所制作的窗体上加上可以调用保存和打开文件方法的按钮,
2、 位两个按钮加上监听器;
3、 为了保证重绘和打开的效率,没有必要将画图板整个区域的个像素点都记录下来,只需要记录画图区域的各像素点,因此需要在画图板窗体上加上一个 Jpanel 容器并将监听器加在上面;
4、 定义一个保存和打开图片文件的类,在其中定义保存和打开文件的方法;
5、 在监听器类中当取得点击保存和打开图片的命令式调用文件操作类中的相应方法;
6、 重绘的实现;
class Mypaint extends JPanel {
// 重写父类绘制窗体的方法
public void paint(Graphics g) {
// 调用父类的方法来绘制窗体
super.paint(g);
if (SaveFile.colors != null) {
for (int i = 0; i < SaveFile.colors.length; i++) {
for (int j = 0; j < SaveFile.colors[i].length; j++) {
int rgb = SaveFile.colors[i][j];
System.out.println(">>>"+rgb);
// 判断绘图区域的颜色与背景色不同的像素点
if (panel1.getBackground().getRGB() != rgb) {
Color color = new Color(rgb);
g.setColor(color);
g.drawLine(j, i, j, i);
}
}
}
}
}
}
四、 遇到的主要问题:
1、 在定义保存文件的方法时,我将各数据的获取与将数据写入文件写在一起,因此导致每次读到的数据就存入内存导致, cpu 的使用率一度达到 100% 。解决办法将读取位图与将各数据写入文件分成两个方法进行定义;
/**
* 将数据保存到数组
* @param panel1
*/
public static void saveBit(JPanel panel1) {
try {
if (null == robot)
robot = new java.awt.Robot();
width = panel1.getWidth();
height = panel1.getHeight();
colors = new int[height][width];
// 得到 panel 左上角的点相对于屏幕的坐标
Point p = panel1.getLocationOnScreen();
java.awt.Rectangle rect = new java.awt.Rectangle(p.x, p.y, panel1
.getWidth(), panel1.getHeight());
// 从屏幕上抓取一张图片
java.awt.image.BufferedImage img = robot.createScreenCapture(rect);
for (int i = 0; i < colors.length; i++) {
for (int j = 0; j < colors[i].length; j++) {
colors[i][j] = img.getRGB(j, i);
}
}
} catch (Exception ef) {
ef.printStackTrace();
}
}
public static void savePic(String path) {
try {
// / 创建一个文件输出流
java.io.FileOutputStream fos = new java.io.FileOutputStream(path);
// 将文件输出流包装成基本类型的数据流
java.io.DataOutputStream dos = new java.io.DataOutputStream(fos);
dos.writeInt(width);
dos.writeInt(height);
for (int i = 0; i < colors.length; i++) {
for (int j = 0; j < colors[i].length; j++) {
rgb = colors[j][i];
dos.writeInt(rgb);
}
}
dos.flush();
fos.close();
dos.close();
System.out.print(" 保存 ");
} catch (Exception ef) {
ef.printStackTrace();
}
}
2、 保存文件时将颜色数组用一个数值进行表示,而打开文件时我没有将用数值中的颜色值赋给保存的颜色数组,因此使打开时所有绘图区域的颜色都是默认的黑色。解决办法:
rgb = dis.readInt();
colors[i][j] = rgb;