从零开始面向对象编程 Java & Day 5,6 (美颜相机 Day 1)

这篇具有很好参考价值的文章主要介绍了从零开始面向对象编程 Java & Day 5,6 (美颜相机 Day 1)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

零、前一天的练习

源代码如下:

package sy0118;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

public class DrawMouse implements MouseListener, ActionListener {

    public String message;
    public int cnt; //点的个数
    public int[] x = new int[105], y = new int[105];
    public Graphics g;

    public void actionPerformed(ActionEvent e){
         message = e.getActionCommand();
         //判断是否进行新动作
        if (message.equals("红色")){
            g.setColor(Color.RED);
        } else if (message.equals("黑色")){
            g.setColor(Color.BLACK);
        } else {
            cnt = 0;
        }
    }

    public void mouseClicked(MouseEvent e){
         if (message.equals("三角形")){
            g.drawLine(x[cnt-3],y[cnt-3],x[cnt],y[cnt]);
            g.drawLine(x[cnt-2],y[cnt-2],x[cnt],y[cnt]);
            cnt = 0;
         }
         if (message.equals("多边形")) {
             if (e.getClickCount() == 2) {
                 g.drawLine(x[1], y[1], x[cnt], y[cnt]);
                 cnt = 0;
             } else {
                 g.drawLine(x[cnt - 2], y[cnt - 2], x[cnt], y[cnt]);
             }
         }
    }

    public void mousePressed(MouseEvent e){
        x[++cnt] = e.getX();
        y[cnt] = e.getY();
    }

    public void mouseReleased(MouseEvent e){
        x[++cnt] = e.getX();
        y[cnt] = e.getY();

        if ((message.equals("直线")) || (message.equals("三角形")) || (message.equals("多边形"))){
            g.drawLine(x[cnt-1],y[cnt-1],x[cnt],y[cnt]);
        } else if (message.equals("矩形")){
            g.drawRect(Math.min(x[cnt-1],x[cnt]),Math.min(y[cnt-1],y[cnt]),Math.abs(x[cnt-1]-x[cnt]),Math.abs(y[cnt-1]-y[cnt]));
        }
    }

    public void mouseEntered(MouseEvent e){

    }

    public void mouseExited(MouseEvent e){

    }
}

使用了数组来存储获取鼠标的位置,并在合适的时间对已获取的点进行重置(很简单,应该都能看懂)

package sy0118;

import javax.swing.*;
import java.awt.*;

public class DrawUI {

    public void showUI(){

        JFrame jf = new JFrame();

        jf.setTitle("画图工具");
        jf.setSize(1000,1000);
        jf.setLocationRelativeTo(null);
        jf.setDefaultCloseOperation(3);

        FlowLayout flow = new FlowLayout();
        jf.setLayout(flow);

        //功能
        JButton Line = new JButton("直线");
        JButton Rectangle = new JButton("矩形");
        JButton Triangle = new JButton("三角形");
        JButton Polygon = new JButton("多边形");
        JButton Red = new JButton("红色");
        JButton Black = new JButton("黑色");
        jf.add(Line); jf.add(Rectangle); jf.add(Triangle); jf.add(Polygon); jf.add(Red); jf.add(Black);

        jf.setVisible(true);

        //监听器
        Graphics g = jf.getGraphics();
        DrawMouse mouse = new DrawMouse();
        jf.addMouseListener(mouse);
        Line.addActionListener(mouse);
        Rectangle.addActionListener(mouse);
        Triangle.addActionListener(mouse);
        Polygon.addActionListener(mouse);
        Red.addActionListener(mouse);
        Black.addActionListener(mouse);

        mouse.g = g;
    }

    public static void main(String[] args) {

        DrawUI ui = new DrawUI();

        ui.showUI();
    }
}

总的来说还是比较简单的,变化不多,只需要稍微注意一下怎么处理多边形的点、边和闭合情况即可(同样的,看不懂可以私信噢!)

一、今日内容

因为每天要做的事情稍微有点多(绝对不是因为内容太多了),后面每天的内容将只保留这部分和源代码部分 :)

前几天初步对 java 有了个初步的了解,那么今天正式开始我们的第一个项目——多功能美颜相机(这会是一个多功能的结合体,需要花费至少十多天来完成)

那么今天一开始,我们先来写写最基础的功能及框架

(怕你们弄晕,我先把全部代码贴出来,直接跳过就行)

package 多功能美颜相机.初版;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class PixelListener implements ActionListener, MouseMotionListener {

    public Graphics g;
    public int w,h;
    public String message;
    public int x,y;
    public int[][] PixelArr = new int[0][];
    public int[][] Staging = new int[0][];
    public int[][] flag = new int[1505][1505];

    @Override
    public void actionPerformed(ActionEvent e) {
        String path = "图片地址";
        message = e.getActionCommand();
        try {
            Staging = getImagePixel(path);
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
        if ((message.equals("灰度")) || (message.equals("原图"))) {
            PixelArr = Staging;
            DrawPixel();
        }
    }

    public void DrawPixel(){

        BufferedImage buffer = new BufferedImage(w+900,h+900,BufferedImage.TYPE_INT_ARGB);

        if (message.equals("马赛克")){
            //int pixel = PixelArr[(y-100)/8*8][x/8*8];
            Graphics bg = buffer.getGraphics();

            int RED=0, GREEN=0, BLUE=0;
            for (int i=x/8*8;i<(x/8+1)*8;i++){
                for (int j=y/8*8;j<(y/8+1)*8;j++){
                    flag[i][j] = 1;
                    int Pixel = PixelArr[j-100][i];
                    RED += Pixel >> 16 & 0xFF;
                    GREEN += Pixel >> 8 & 0xFF;
                    BLUE += Pixel & 0xFF;
                }
            }

            Color color = new Color(RED/64, GREEN/64, BLUE/64);
            bg.setColor(color);
            bg.fillRect(x/8*8,y/8*8,8,8);

            //buffer.setRGB(x/8*8,y/8*8);

        } else {
            for (int i = 0; i < h; i++) {
                for (int j = 0; j < w; j++) {
                    flag[i][j] = 0;
                    int pixel = PixelArr[i][j];
                    int red = pixel >> 16 & 0xFF;
                    int green = pixel >> 8 & 0xFF;
                    int blue = pixel & 0xFF;
                    int A = pixel >> 24 & 0xFF;

                    //Color color = new Color(red, green, blue);
                    if (message.equals("灰度")) {
                        int average = (int) (0.3 * red + 0.59 * green + 0.11 * blue);
                        //color = new Color(average, average, average);
                        pixel = A << 24 | average << 16 | average << 8 | average;
                        PixelArr[i][j] = pixel;
                    }

                    //g.setColor(color);
                    //g.fillRect(j, i + 100, 1, 1);

                    buffer.setRGB(j,i+100,pixel);
                }
            }
        }
        g.drawImage(buffer,0,0,null);
    }

    public int[][] getImagePixel(String path) throws IOException {
        File file = new File(path);
        BufferedImage bufferedImage = null;
        try {
            bufferedImage = ImageIO.read(file);
        } catch (IOException e){
            throw new RuntimeException(e);
        }

        w = bufferedImage.getWidth();
        h = bufferedImage.getHeight();
        int[][] PixelArr = new int[h][w];
        for(int i=0;i<h;i++){
            for(int j=0;j<w;j++){
                PixelArr[i][j] = bufferedImage.getRGB(j,i);
            }
        }
        return PixelArr;
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        if (message.equals("马赛克")){
            if (flag[x][y] == 0){
                DrawPixel();
            }
        }
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        //x = e.getX();
        //y = e.getY();
    }
}

(还有主函数)

package 多功能美颜相机.初版;

import javax.swing.*;
import java.awt.*;
import java.util.PropertyPermission;

public class PixelUI {

    public void showUI(){
        JFrame jf = new JFrame();
        jf.setLayout(new FlowLayout());
        jf.setSize(900,900);
        jf.setDefaultCloseOperation(3);
        jf.setLocationRelativeTo(null);
        jf.setTitle("图像处理");

        JButton Origin = new JButton("原图");
        JButton Grayscale = new JButton("灰度");
        JButton Mosaic = new JButton("马赛克");
        jf.add(Origin); jf.add(Grayscale); jf.add(Mosaic);

        PixelListener listener = new PixelListener();
        Origin.addActionListener(listener);
        Grayscale.addActionListener(listener);
        Mosaic.addActionListener(listener);

        jf.addMouseMotionListener(listener);

        jf.setVisible(true);

        Graphics g = jf.getGraphics();
        listener.g = g;
    }

    public static void main(String[] args) {
        PixelUI pixelUI = new PixelUI();
        pixelUI.showUI();
    }
}

主函数还是非常简单的,先把窗体和按钮创建完,并添加画笔,完成原图、灰度和马赛克三种情况的绘画。

先讲原图的绘画,先拍这部分的源代码:

BufferedImage buffer = new BufferedImage(w+900,h+900,BufferedImage.TYPE_INT_ARGB);
for (int i = 0; i < h; i++) {
    for (int j = 0; j < w; j++) {
        flag[i][j] = 0;
        int pixel = PixelArr[i][j];
        //int red = pixel >> 16 & 0xFF;
        //int green = pixel >> 8 & 0xFF;
        //int blue = pixel & 0xFF;
        //int A = pixel >> 24 & 0xFF;

        //Color color = new Color(red, green, blue);

        //g.setColor(color);
        //g.fillRect(j, i + 100, 1, 1);

        buffer.setRGB(j,i+100,pixel);
     }
}
g.drawImage(buffer,0,0,null);

原理是把图片里每个像素(pixel)的ARGB(或RGB)值(PixelArr)取出来,并存储(setRGB)给缓冲图片(BufferedImage)后,在循环结束一起输出(g.drawImage)。这里有两种做法,注释掉的是另一种做法,不需要使用缓冲图片,虽然绘制慢,但是助于理解什么是ARGB值。

这里有个问题,我们该怎么取出图片中的像素值(ARGB)并存储到数组 PixelArr 呢?同样的,先贴代码:

    public int[][] getImagePixel(String path) throws IOException {
        File file = new File(path);
        BufferedImage bufferedImage = null;
        try {
            bufferedImage = ImageIO.read(file);
        } catch (IOException e){
            throw new RuntimeException(e);
        }

        w = bufferedImage.getWidth();
        h = bufferedImage.getHeight();
        int[][] PixelArr = new int[h][w];
        for(int i=0;i<h;i++){
            for(int j=0;j<w;j++){
                PixelArr[i][j] = bufferedImage.getRGB(j,i);
            }
        }
        return PixelArr;
    }

可以看到,当我们有图片的地址(path)后,通过文件(File)读入(ImageIO.read)并存储到缓冲图片区(BufferedImage)后,通过 getRGB 值赋值给对应位置的 PixelArr 即可!(千万注意这里的位置坐标!还有包括后面对图片处理时的位置坐标)

从零开始面向对象编程 Java & Day 5,6 (美颜相机 Day 1),java,开发语言

这样一顿操作之后,我们就可以画出原图啦!然后是灰度的算法,其实非常简单,只需要特判一波,并采用灰度算法均衡 RED,GREEN,BLUE 值即可!

if (message.equals("灰度")) {
    int average = (int) (0.3 * red + 0.59 * green + 0.11 * blue);
    //color = new Color(average, average, average);
    pixel = A << 24 | average << 16 | average << 8 | average;
    PixelArr[i][j] = pixel;
}

从零开始面向对象编程 Java & Day 5,6 (美颜相机 Day 1),java,开发语言

同样的是两种方法,注释掉的是不用缓冲图片的方法(但是画的慢)。

马赛克其实是同理,只需要把一个区块(比如10*10)内的全部像素值(其实就是颜色)变成同一种颜色即可!

        if (message.equals("马赛克")){
            //int pixel = PixelArr[(y-100)/8*8][x/8*8];
            Graphics bg = buffer.getGraphics();

            int RED=0, GREEN=0, BLUE=0;
            for (int i=x/8*8;i<(x/8+1)*8;i++){
                for (int j=y/8*8;j<(y/8+1)*8;j++){
                    flag[i][j] = 1;
                    int Pixel = PixelArr[j-100][i];
                    RED += Pixel >> 16 & 0xFF;
                    GREEN += Pixel >> 8 & 0xFF;
                    BLUE += Pixel & 0xFF;
                }
            }

            Color color = new Color(RED/64, GREEN/64, BLUE/64);
            bg.setColor(color);
            bg.fillRect(x/8*8,y/8*8,8,8);

            //buffer.setRGB(x/8*8,y/8*8);

        }

同样的是两种方法(但是这里我没有完全用注释区分开来),我选用的是 8*8 的区块全部变成一个颜色。为了使得画面颜色更加平滑,我将这个颜色设置为区块内所有像素(也就是64个像素)颜色的平均值,然后 fillRect 画矩形即可!

另外,我们可以让马赛克的绘制变成通过鼠标拖动来控制,初步实现截屏里面的马赛克功能。这就需要用到上一天里获取鼠标位置的方法了!

    public void mouseDragged(MouseEvent e) {
        x = e.getX();
        y = e.getY();
        if (message.equals("马赛克")){
            if (flag[x][y] == 0){
                DrawPixel();
            }
        }
    }

这里我使用了标记数组 flag 来判断一个像素之前是否被打过马赛克,防止重复打出不同颜色的马赛克。

那么事情到这里就已经完成啦,支持画出原图、画出灰度图、在原图或者灰度图上用鼠标进行马赛克,所有的源码在最上面。

接下来就是一些问题或者后面几天需要改进的地方:

1. 打马赛克时不连贯,鼠标移动快的时候中间会断开

2. 代码不太美观

3. 添加新的画面算法(如二值化、底片、浮雕等)

4. 添加滑动条组件来控制各种数据(如马赛克画笔大小调整、图片大小调整、RGB值调整等等)

5. 对比微信截图里的马赛克,我们可以发现:它的马赛克宽度固定,但长度末端位于鼠标位置(说白了就是拖到哪打到哪),而我们是一块一块涂上去的,有点像量子态一样,怪怪的

6. 添加新功能,如高清修复等等文章来源地址https://www.toymoban.com/news/detail-837102.html

到了这里,关于从零开始面向对象编程 Java & Day 5,6 (美颜相机 Day 1)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • Java面向对象编程

    A.邮件服务的设置文件 B.DHCP的设置文件 C.DNS解析的设置文件 D.网络路由的设置文件 答案:C A.本机网关设置错误 B.本机没有正确设置DNS C.对方运行的是不同的操作系统 D.二层交换机故障 答案:A A.侵入目标服务器,获取重要数据 B.采用穷举的方式获得登录账号 C.发送无效的请求

    2024年02月07日
    浏览(19)
  • Java——面向对象编程思想

    如果有人问你,C和Java的区别是什么呢? 我想大部分人肯定脱口而出的是:C是面向过程的,Java是面向对象的。 那如何理解面向过程和面向对象呢? 首先,面向过程和面向对象都是编程思想。 ①面向过程,以C语言为代表,它是按解决一个问题的的流程或者先后步骤来编程的

    2024年02月11日
    浏览(12)
  • Java面向对象编程·上

    大家好,我是晓星航。今天为大家带来的是面向对象编程相关的讲解!😀 包 (package) 是组织类的一种方式. 使用包的主要目的是保证类的唯一性. 例如, 你在代码中写了一个 Test 类. 然后你的同事也可能写一个 Test 类. 如果出现两个同名的类, 就会冲突, 导致代码不能编译通过

    2023年04月15日
    浏览(16)
  • JAVA- 面向对象编程(上)

    JAVA- 面向对象编程(上)

      🌈个人主页:  Aileen_0v0 🔥系列专栏: PYTHON学习系列专栏 💫个人格言:\\\"没有罗马,那就自己创造罗马~\\\" 目录 面向对象的特征及理解  new  Static Summary:   面试题:oop的三大特征是什么?  --- 封装,继承,多态 类,对象是什么? 类是自定义类型, 对象是实体 通俗的讲类相当于建房子的

    2024年02月05日
    浏览(8)
  • 【零基础??天速成 Java】Day2 - 初识面向对象

    【零基础??天速成 Java】Day2 - 初识面向对象

    目录 前言 1. 可变参数的使用 2. 构造器 3. 包 1、包的创建 2、包的使用 3、包的命名规范 4、常用的包 5. 访问修饰符 6. 继承  7. super 8. 方法重写 Override 写在最后: 我的 java 基础学习,跟的是韩顺平的 java 课程~ 本篇文章涵盖视频 216 ~ 305 集里面 java 与 C++ 不同的知识

    2024年02月12日
    浏览(11)
  • 【java】面向对象的编程基础

    【java】面向对象的编程基础

    true false 这里输入set和get可以自动将函数补全,传参初始化在构造属性之后 cc ccccc coleak 这里说明先构造属性,再执行代码块,再初始化 静态代码块 4 4 我是静态变量初始化 我是静态代码块 我是成员变量初始化 我是普通代码块 我是构造方法 快速构造,点击生成,构造函数,

    2023年04月16日
    浏览(12)
  • Java基础(七)面向对象编程(高级)

    Java基础(七)面向对象编程(高级)

    回顾类中的实例变量(即非static的成员变量) 创建两个Circle对象: Circle类中的变量radius是一个实例变量(instance variable),它属于类的每一个对象,c1中的radius变化不会影响c2的radius,反之亦然。 如果想让一个成员变量被类的所有实例所共享,就用static修饰即可,称为类变量(

    2023年04月16日
    浏览(16)
  • Java奠基】实现面向对象编程方法

    Java奠基】实现面向对象编程方法

    目录 标准的JavaBean类 设计对象并使用 对象封装 this 构造方法 要知道对象是一个又一个能帮助我们解决问题的东西,但是这些东西并不是凭空出现的,需要我们根据设计图来进行制造,而这些一个一个的设计图就是一个一个的类。 1)类名需要见名知意 2)成员变量使用

    2024年02月06日
    浏览(13)
  • 从零开始学习 Java:简单易懂的入门指南之类和对象(七)

    从零开始学习 Java:简单易懂的入门指南之类和对象(七)

    1.1 类和对象的理解 客观存在的事物皆为对象 ,所以我们也常常说万物皆对象。 类 类的理解 类是对现实生活中一类具有共同属性和行为的事物的抽象 类是对象的数据类型,类是具有相同属性和行为的一组对象的集合 简单理解:类就是对现实事物的一种描述 类的组成 属性:

    2024年02月14日
    浏览(47)
  • 【Java高级语法】(十)面向对象:掀开Java 的面向对象盖章时代,一起来发现OOP的有趣编程秘密!~

    【Java高级语法】(十)面向对象:掀开Java 的面向对象盖章时代,一起来发现OOP的有趣编程秘密!~

    面向对象编程(Object-Oriented Programming, OOP)是一种广泛应用于软件开发的编程范式 。Java是一种面向对象的编程语言,它提供了丰富的工具和特性来支持面向对象编程。本文将详细介绍Java面向对象的全部知识。 我们可以把一个Java类想象成是一个蓝图或者模具,用来创建对象。就

    2024年02月11日
    浏览(14)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包