图像处理Image Processing(二)

目录

一.界面概览 

二.功能的实现完善与一些技术细节

(1)ListenerImp类

(2)DrawPanel类

(3)解决图像加载缓慢的问题

(4)关于buffimglist

(5)录制功能:

(6)回放功能

(7)撤回与清空功能

三.Thx


一.界面概览 

这次我们用Java来实现图像处理,先给hxdm上成果:

 

 如图窗体右方(East)面板按钮的所示的功能是我们的图像处理小项目的主要内容。

关于图像处理的具体方法可以参考我的上一篇博客:

图像处理Image Processing(一)

二.功能的实现完善与一些技术细节

(1)ListenerImp类

  利用ListenerImp类来实现ActionListener等接口(并不需要实现,真正意义上的实现在ImageListener类中进行),然后再由ImageListener类来继承,来实现我们需要的方法;

这样做有如下几个好处:

  • 如果需要实现的监听器过多,类中的方法太多不便于阅读,况且并不是每个方法我们都要实现;
  • 方便进行方法的添加;
  • 增加了代码的可读性,美观就完事
public class ListenerImp implements ActionListener, MouseListener, MouseMotionListener, ChangeListener, KeyListener {

    @Override
    public void actionPerformed(ActionEvent e) {

    }


    @Override
    public void keyTyped(KeyEvent e) {

    }

    @Override
    public void keyPressed(KeyEvent e) {

    }

    @Override
    public void keyReleased(KeyEvent e) {

    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void mouseDragged(MouseEvent e) {

    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }

    @Override
    public void stateChanged(ChangeEvent e) {

    }
}

(2)DrawPanel类

DrawPanel类是用来重写paint方法实现重绘的类;

   其中buffimglist是保存每步操作图像的ArrayList<BufferedImage>,需要注意的是指针悬空问题和绘制图像时要取buffimglist中栈顶元素。(为什么是直接drawImage,而不是打印保存有像素点的二维数组,后文会提到);

public class DrawPanel extends JPanel {
    ArrayList<BufferedImage> buffimglist = new ArrayList<>();
    public void setBuffimglist(ArrayList<BufferedImage> buffimglist) {
        this.buffimglist = buffimglist;
    }
    public void paint(Graphics gr) {
        super.paint(gr);
        System.out.println("paint");
        //防止指针悬空
        if(buffimglist==null ){
            return;
        }
        if(buffimglist.size()==0){
            return;
        }
        //绘制最后存储的图像
        gr.drawImage(buffimglist.get(buffimglist.size()-1), 0, 0, null);
     
    }
}

(3)解决图像加载缓慢的问题

   尝试了鄙人上一篇博客中的方法的hxdm会发现一个问题:图像在窗体的打印十分缓慢。

   这是因为IO与底层GPU速度不匹配造成的,此时我们进行的是一个一个像素的数据传输,导致图片加载缓慢。解决方法:

  1. 将整张图片的像素点存储起来;
  2. 声明一个BufferedImage对象来存储每张图像的像素点,此操作为纯内存操作;
  3. 整体绘制:在窗体上直接绘制BufferedImage(drawImage方法);

用绘制原图的方法来给大家举例,(其他绘制方法同理):‘

     //绘制原图
     public BufferedImage drawImage(int[][] imgArr) {
        //声明一个空的BufferedImage
        BufferedImage buffimg = new BufferedImage(imgArr.length, imgArr[0].length, BufferedImage.TYPE_INT_ARGB);
        //绘制过程与屏幕刷新无关,纯内存操作
         Graphics bfg = buffimg.getGraphics();
        for(int i = 0; i < imgArr.length; i++) {
            for(int j = 0; j < imgArr[0].length; j++) {
                int rgb = imgArr[i][j];
                Color color = new Color(rgb);
               
                //方法一:把像素保存在缓冲区中
//                buffimg.setRGB(i, j, rgb);
                //方法二:先在内存中绘制
                bfg.setColor(color);
                bfg.fillRect(i,j,1,1);

            }
        }
         //窗体上绘制
         //因为imageListener中调用了repaint,按下按钮后会绘制,所以这里不需要绘制
//        gr.drawImage(buffimg, 0, 0, null);
        return buffimg;
     }
  • 我们并不需要在 drawImage方法中实现窗体绘制的功能,因为我们在imageListener中调用了repaint方法,按下按钮后会绘制,所以这里不需要绘制。这里的绘制方法都只需要存储图像在buffimg中。
  • 修改后的返回值类型为为BufferedImage,原因如下:
  if(str.equals("原图")) {
      buffimg = imageUtils.drawImage(imgArr);
      //加入队列
      buffimglist.add(buffimg);
  }

这样我们可以将每次存储在内存中的图像加入buffimglist中,便于我们的重绘、录制、回放、清空功能的实现。

(4)关于buffimglist

buffimglist的作用是保存我们每一步操作产生的图像,便于我们的重绘、录制、回放、清空功能的实现。

 ArrayList<BufferedImage> buffimglist = new ArrayList<>();

(5)录制功能:

录制功能:因为我们的每步操作都保存在了buffimglist中,所以我们只需要保存录制的起始位置即可还原操作顺序;

 //记录录制的开始与结束位置
    public int start = 0;
    public int end = 0;
    //录制
    public void recordImage() {
        start = this.buffimglist.size() - 1;
        System.out.println("开始录制:" + start);
    }

(6)回放功能

回放功能:有了起始位置,回放就是一个遍历buffimglist的过程;

    //回放
    public void playback() {
        end = this.buffimglist.size();
        for(int i = start; i < end; i++) {
            gr.drawImage(this.buffimglist.get(i), 0, 0, null);
            //相邻图片间隔1s
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

(7)撤回与清空功能

 //撤回
    public void withDraw() {
        if(this.buffimglist.size() > 1) {
            this.buffimglist.remove(this.buffimglist.size()-1);
        } else {
            System.out.println("不能撤回!!");
        }
    }

    //清空
    public void clearScreen() {
        this.buffimglist.clear();
    }

三.Thx

谢谢你这么好看还看完了我的博客!

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值