JAVA美颜相机入门(兼具图像处理和画图板功能)

美颜相机已经成为当代年轻人不可或缺的自拍神器,其具有自动美肌,完美保留细节,让照片告别模糊等功能。或许我们会觉得编写这样一个具有如此强大功能的美颜相机一定需要庞大而且复杂的代码段,其实不然,即使对于初学者而言,也可以轻而易举的做出一款入门级的美颜相机。

JAVA美颜相机入门(兼具图像处理和画图板功能)

一、思路分析

一款简易美颜相机的功能我们可以简单分为两大块:一是对拍摄出的照片可以进行马赛克,美白,灰度调整等功能;二是可以在照片上画圆圈,画直线等涂鸦功能。因此,我们在写代码时,把需要实现的功能分成如下两部分:

1、图像处理

2、画板

下面先展示本次完工后美颜相机的效果图:

JAVA美颜相机入门(兼具图像处理和画图板功能)

二、代码分析

这边先只分析重要部分代码,最终的完整代码附在文章末尾!

和前面我们做五子棋游戏类似,在实现美颜相机功能的第一步还是先画界面,首先,我们需要画一个类似于 P 图软件的界面,上面拥有照片处理涂鸦区,按钮区,颜色选择区,菜单等功能区,因此先 new 一个 DrawUI 类(当然也可以取其他名字),在这个类中,我们首先把界面画出来,为了方便管理,我们设置了一个菜单和三个 JPanel,一个 JPanel 里放 ImagePanel,用于照片处理和涂鸦,另两个 Panel 里放相关功能按钮。

    public void initUI(){
        JFrame jf = new JFrame();
        jf.setSize(1400,900);
        jf.setTitle("PC版美颜相机");
        jf.setLocationRelativeTo(null);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);

        JPanel[] jps = addPanel(jf);
        addButton(jps);
        addJSlider(jps);
        addMenu(jf);

    }

添加界面上的 JPanel :

private JPanel[] addPanel(JFrame jf) {
        JPanel[] jps = new JPanel[3];
        String[] layoustrs = {BorderLayout.CENTER,BorderLayout.SOUTH,BorderLayout.EAST};

        imgPanel.setBackground(Color.LIGHT_GRAY);
        imgPanel.addMouseListener(ul);
        jf.add(imgPanel,layoustrs[0]);
        jps[0] = imgPanel;

        Dimension dim = new Dimension(320,100);
        JPanel jp_s1 = new JPanel();
        jp_s1.setBackground(Color.ORANGE);
        jp_s1.setPreferredSize(dim);
        jf.add(jp_s1,layoustrs[1]);
        jps[1] = jp_s1;

        JPanel jp_s2 = new JPanel();
        jp_s2.setBackground(Color.YELLOW);
        jp_s2.setPreferredSize(dim);
        jf.add(jp_s2,layoustrs[2]);
        jps[2] = jp_s2;
        return jps;
    }

添加界面上的按钮:

private void addButton(JPanel[] jps) {

        String[] btnstrs1 = new String[]{"原图","撤回","马赛克","灰度","轮廓","二值化","油画",
                "美白","运动模糊","卷积","锐化","浮雕","左旋","右旋","放大","缩小","打开摄像头","关闭摄像头"};
        for(int i = 0; i < btnstrs1.length-2; i++){
            JButton btn = new JButton(btnstrs1[i]);
            Dimension dim = new Dimension(120,40);
            btn.setPreferredSize(dim);
            btn.setFont(new Font("黑体",1,20));
            btn.setBackground(Color.WHITE);
            btn.addActionListener(ul);
            jps[2].add(btn);
        }

        for(int i = btnstrs1.length-2; i < btnstrs1.length; i++){
            JButton btn = new JButton(btnstrs1[i]);
            Dimension dim = new Dimension(200,40);
            btn.setPreferredSize(dim);
            btn.setFont(new Font("黑体",1,20));
            btn.setBackground(Color.WHITE);
            btn.addActionListener(ul);
            jps[2].add(btn);
        }

        String[] btnstrs2 = new String[] {"直线","矩形","椭圆","三角形","正方形","菱形","特殊三角形","多边形","画点","迭代","树"};
        for(int i = 0; i < btnstrs2.length; i++) {
            JButton btn = new JButton(btnstrs2[i]);
            Dimension dim = new Dimension(120,40);
            btn.setPreferredSize (dim);
            btn.setFont (new Font ("黑体",1,16));
            btn.setBackground (Color.WHITE);
            btn.addActionListener (ul);
            jps[1].add (btn);
        }

        Color []color= {Color.BLUE,Color.GREEN,Color.YELLOW,Color.BLACK,Color.ORANGE,
        Color.GRAY,Color.RED};
        for(int i=0;i

添加界面上的滑动条:

private void addJSlider(JPanel[] jps) {

        JLabel j0 = new JLabel("                                                ");
        j0.setFont(new Font("黑体",1,30));
        jps[2].add(j0);
        JLabel j1 = new JLabel("大小/程度选择:");
        j1.setFont(new Font("黑体",1,30));
        jps[2].add(j1);

        JSlider jSlider = new JSlider(0,100);
        Dimension dm = new Dimension(300,80);  //设置按钮尺寸
        jSlider.setPreferredSize (dm);
        jSlider.setFont (new Font ("黑体",1,15));
        jSlider.setMajorTickSpacing(20);
        jSlider.setMinorTickSpacing(5);
        jSlider.setPaintLabels(true);//确定是否在滑块上绘制标签
        jSlider.setPaintTicks(true);//确定是否在滑块上绘制刻度标记
        jSlider.setPaintTrack(true);//确定是否在滑块上绘制滑道
        jSlider.setSnapToTicks(true);//指定为 true,则滑块(及其所表示的值)解析为最靠近用户放置滑块处的刻度标记的值
        jSlider.setOpaque(false);
        jps[2].add(jSlider);
        jSlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                System.out.println("当前值: " + jSlider.getValue());
                int p = jSlider.getValue();
                iu.p = p;
            }
        });
    }

添加界面上的菜单:

private void addMenu(JFrame jf) {
        //菜单栏
        JMenuBar jmb = new JMenuBar();
        jf.add(jmb,BorderLayout.NORTH);

        //菜单选项
        JMenu file = new JMenu("文件");
        file.setPreferredSize(new Dimension(80,40));
        file.setFont(new Font("宋体",2,22));
        jmb.add(file);

        //子菜单
        JMenuItem jmi1 = new JMenuItem("打开");
        jmi1.setPreferredSize(new Dimension(80,40));
        jmi1.setFont(new Font("宋体",2,22));
        jmi1.addActionListener(ul);
        file.add(jmi1);
        JMenuItem jmi2 = new JMenuItem("保存");
        jmi2.setPreferredSize(new Dimension(80,40));
        jmi2.setFont(new Font("宋体",2,22));
        jmi2.addActionListener(ul);
        file.add(jmi2);

        jf.setVisible(true);
    }

界面画完后就涉及到图像处理部分了,根据事先设定好的路径把图片的像素读进 imgArray[ ][ ] 数组中,后期根据需要对数组中每一个位置的值进行相应的处理变换就可以获得处理后的图像啦!代码中,width 是我们读取到的图像的宽度,height 是我们读取到的图像的高度,后面我们又设定了 width0 和 height0 的值,他们都等于图像宽度和高度中的较大者,其实, width0 和 height0 的值是我们定义的画布的宽度和高度,因为我们后面会用到图像旋转功能,所以画布的尺寸边长应为图像宽度和高度值中的较大者,(如果画布尺寸和图像尺寸一样,那么在旋转的过程中可能图像会显示不全)。

public int[][] readImagePix(String path){
        // 文件对象
        File file = new File (path);
        BufferedImage readimg = null;
        try {
            readimg = ImageIO.read (file);
        } catch (IOException e) {
            e.printStackTrace ();
        }
        int width = readimg.getWidth ();
        int height = readimg.getHeight ();
        int height0 = 0;
        int width0 = 0;
        if(width >= height){
            height0 = width;
            width0 = width;
        }
        if(width < height){
            width0 = height;
            height0 = height;
        }
        imgPanel.width = width;
        imgPanel.height= height;
        int[][] imgArray = new int[width0][height0];
        for(int i = 0; i < width; i++){
            for(int j = 0; j < height; j++){
                imgArray[i][j] = readimg.getRGB (i, j);
            }
        }
        return imgArray;
    }

为了后面处理图像方便,我们先写了一个获取灰度值的函数:

public int getRgbGray(int numPixels){
        // byte -128 127
        int red = (numPixels>>16)&0xFF;
        int green = (numPixels>>8)&255;
        int blue = (numPixels>>0)&255;
        // 灰度 -- 减少计算量 以及 更方便计算
        int gray = (red + green + blue) / 3;
        return gray;
    }

下面介绍几种图像处理的方法,第一个是原图,原图应该是最简单的部分了,我们只需要根据数组 imgArray[ ][ ] 把每一个位置的像素画出来就好。

public BufferedImage drawImage_00(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage ( imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        for(int i = 0; i < imgArray.length; i++){
            for(int j = 0; j < imgArray[i].length; j++){
                buffimg.setRGB (i,j,imgArray[i][j]);
            }
        }
        return buffimg;
    }

JAVA美颜相机入门(兼具图像处理和画图板功能)

马赛克就是在图像上每隔一定的距离画一个方块,该方块的颜色和方块中心的颜色一样,当然也可以取方块中所有像素的平均值,这边需要注意的是, 图像的长度并不一定是方块边长的整数倍,所以要注意图像边缘部分的处理。为了能够调整马赛克方块的大小,我们在界面上设置了一个滑块,可以调整滑块来调整马赛克程度 :

public BufferedImage drawImage_01(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage ( imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);

        System.out.print("iup = "+p);
        if(p < 20)p = 20;

        //可使用fillRect

        for(int i = p/10; i < imgArray.length; i += (2*(p/10)+1)){
            for(int j = p/10; j < imgArray[i].length; j += (2*(p/10)+1)){

                int mm,nn;
                if(i+(p/10+1)>imgArray.length) {
                    mm = imgArray.length;
                }else {
                    mm = i+(p/10+1);
                }
                if(j+(p/10+1)>imgArray[i].length) {
                    nn = imgArray[i].length;
                }else {
                    nn = j+(p/10+1);
                }

                for(int m=i-p/10;m

JAVA美颜相机入门(兼具图像处理和画图板功能)

滑块值为100:

JAVA美颜相机入门(兼具图像处理和画图板功能)
public BufferedImage drawImage_02(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        for(int i = 0; i < imgArray.length; i++){
            for(int j = 0; j < imgArray[i].length; j++){
                int num1 = imgArray[i][j];
                int gray1 = getRgbGray (num1);
                Color color = new Color (gray1,gray1,gray1);
                buffimg.setRGB (i, j, color.getRGB ());
            }
        }
        return buffimg;
    }

JAVA美颜相机入门(兼具图像处理和画图板功能)
public BufferedImage drawImage_03(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        for(int i = 0; i < imgArray.length - 1; i++){
            for(int j = 1; j < imgArray[i].length - 1; j++){
                int num1 = imgArray[i][j];
                int num2 = imgArray[i + 1][j + 1];
                int num3 = imgArray[i + 1][j - 1];
                int num4 = imgArray[i + 1][j];
                int num5 = imgArray[i][j + 1];
                int gray1 = getRgbGray (num1);
                int gray2 = getRgbGray (num2);
                int gray3 = getRgbGray (num3);
                int gray4 = getRgbGray (num4);
                int gray5 = getRgbGray (num5);
                // 比较相邻的像素值 差距过大表示此处颜色差距大 应该是轮廓边框
                if((Math.abs (gray1 - gray2) > (7+p/10))||(Math.abs (gray1 - gray3) > (7+p/10))||(Math.abs (gray1 - gray4) > (7+p/10))||(Math.abs (gray1 - gray5) > (7+p/10))){
                // 绘制为白色
                    buffimg.setRGB (i, j, Color.WHITE.getRGB ());
                } else{
                // 绘制为黑色
                    buffimg.setRGB (i, j, Color.BLACK.getRGB ());
                }
            }
        }
        return buffimg;
    }

JAVA美颜相机入门(兼具图像处理和画图板功能)

二值化处理只需判断该点像素值大小,并设定一个阈值( 此阈值大小可以通过人为调整滑块来决定)大于该阈值将该点像素设定为白色,小于该阈值将该点像素设定为黑色:

public BufferedImage drawImage_04(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        for(int i = 0; i < imgArray.length; i++){
            for(int j = 0; j < imgArray[i].length; j++){
                int num1 = imgArray[i][j];
                int gray1 = getRgbGray (num1);
                if(gray1 > 78+p){
                    // 绘制为白色
                    buffimg.setRGB (i, j, Color.WHITE.getRGB ());
                } else{
                    // 绘制为黑色
                    buffimg.setRGB (i, j, Color.BLACK.getRGB ());
                }
            }
        }
        return buffimg;
    }

JAVA美颜相机入门(兼具图像处理和画图板功能)
public BufferedImage drawImage_05(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        Graphics bg = buffimg.getGraphics();
        for(int i = (10+p/10); i < imgArray.length; i += (3+p/10)) {
            for(int j = (5+p/10);j < imgArray[i].length; j += (3+p/10)) {
                int num = imgArray[i][j];
                Color color = new Color (num);
                bg.setColor(color);
                int r1 = (int)(Math.random()*(40+p/5));
                int r2 = (int)(Math.random()*(30+p/5));
                bg.fillOval(i-(20+p/10), j-(15+p/10), Math.max(r1,r2), Math.min(r1,r2));
            }

        }
        return buffimg;
    }

JAVA美颜相机入门(兼具图像处理和画图板功能)

美白处理(这边我们所做的只是简易的美白,真正美颜相机里的美白需要识别出人物并只美白肤色)只需把图像上每一个像素的 RGB 值增大一定的量( 增大量可以通过人为调整滑块来决定)即可:

public BufferedImage drawImage_06(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        for(int i = 0; i < imgArray.length; i++){
            for(int j = 0; j < imgArray[i].length; j++){
                int num = imgArray[i][j];
                Color color = new Color (num);
                int red = color.getRed ();
                int green = color.getGreen ();
                int blue = color.getBlue ();

                int rednext = red + (3+p/3);
                if(rednext > 255){
                    rednext = 255;
                }
                int greennext = green + (3+p/3);
                if(greennext > 255){
                    greennext = 255;
                }
                int bluenext = blue + (3+p/3);
                if(bluenext > 255){
                    bluenext = 255;
                }
                Color newColor = new Color (rednext, greennext, bluenext);
                // 缓冲绘制
                buffimg.setRGB (i, j, newColor.getRGB ());
            }
        }
        return buffimg;
    }

JAVA美颜相机入门(兼具图像处理和画图板功能)

运动模糊:

public BufferedImage drawImage_07(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        if(p> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];

                        }
                    }
                    redvalue = redvalue/5;
                    greenvalue = greenvalue/5;
                    bluevalue = bluevalue/5;

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue50) {
            float[][] fls= {
                    {1,0,0,0,0,0,0,0,0},
                    {0,1,0,0,0,0,0,0,0},
                    {0,0,1,0,0,0,0,0,0},
                    {0,0,0,1,0,0,0,0,0},
                    {0,0,0,0,1,0,0,0,0},
                    {0,0,0,0,0,1,0,0,0},
                    {0,0,0,0,0,0,1,0,0},
                    {0,0,0,0,0,0,0,1,0},
                    {0,0,0,0,0,0,0,0,1},
            };

            for(int i=0;i> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }
                    redvalue = redvalue/9;
                    greenvalue = greenvalue/9;
                    bluevalue = bluevalue/9;

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue

JAVA美颜相机入门(兼具图像处理和画图板功能)
public BufferedImage drawImage_08(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
            if(p> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue50) {
            float[][] fls= {
                    {-1,-1,-1,-1,0},
                    {-1,-1,-1,0,1},
                    {-1,-1,0,1,1},
                    {-1,0,1,1,1},
                    {0,1,1,1,1},
            };

            for(int i=0;i> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue

JAVA美颜相机入门(兼具图像处理和画图板功能)

锐化:

public BufferedImage drawImage_09(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        if(p> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue50) {
            float[][] fls= {
                    {-1,-1,-1,-1,-1},
                    {-1,-1,-1,-1,-1},
                    {-1,-1,25,-1,-1},
                    {-1,-1,-1,-1,-1},
                    {-1,-1,-1,-1,-1},
            };

            for(int i=0;i> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue

JAVA美颜相机入门(兼具图像处理和画图板功能)

最后一项处理是浮雕效果,浮雕效果的原理是将图像的每一个像素 RGB 值在对角线上作差,并加上 128,最后做灰度处理即可:

public BufferedImage drawImage_10(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        for(int i=0;i>16)&0xFF;
                int green1 = (rgbvalue1>>8)&0xFF;
                int blue1 = (rgbvalue1)&0xFF;

                int red2 = (rgbvalue2>>16)&0xFF;
                int green2 = (rgbvalue2>>8)&0xFF;
                int blue2 = (rgbvalue2)&0xFF;

                redvalue = red1-red2+128;
                greenvalue = green1-green2+128;
                bluevalue = blue1-blue2+128;

                int gray = (redvalue + greenvalue + bluevalue) / 3;

                if(gray>255)gray=255;
                if(gray

JAVA美颜相机入门(兼具图像处理和画图板功能)

旋转处理需要先定义一个空的二维数组,宽度和高度和先前的 imgArray[ ][ ] 的宽度高度相反

左旋使用此代码:newArr[j][imgArray.length-i-1] = imgArray[i][j];

右旋使用此代码:newArr[imgArray.length-j-1][i] = imgArray[i][j];

放大处理只需将画布增大相应尺寸即可( 增大量可以通过人为调整滑块来决定);

缩小处理只需将画布增大相应尺寸即可( 缩小量可以通过人为调整滑块来决定);

JAVA美颜相机入门(兼具图像处理和画图板功能)

开启摄像头需要用到多线程:

public class ThreadPixel extends Thread {
    public Graphics g;
    public boolean flag = true;  //控制线程的标记

    //初始化画笔对象
    public ThreadPixel(Graphics g) {
        this.g = g;
    }

    // 启动线程后自定执行的方法
    // run 方法执行完,该线程结束,线程一旦结束不能再次启动
    public void run() {
        System.out.println("启动线程.."+this.getName());

        // 启动摄像头,放在线程中启动
        Webcam webcam = Webcam.getDefault();
        webcam.open();

        while (flag) {
            // 获取摄像头拍到的数据
            BufferedImage bufferedImage = webcam.getImage();
            g.drawImage(bufferedImage, 50, 50,800,600, null);
        }
    }
}

到现在为止,图像处理部分我们就讲完啦,由于画图板功能较图像处理简单,在此我们就不做详细解释,读者直接看文末源代码即可:

这边附上几张画图板效果图:

JAVA美颜相机入门(兼具图像处理和画图板功能)

JAVA美颜相机入门(兼具图像处理和画图板功能)

JAVA美颜相机入门(兼具图像处理和画图板功能)

JAVA美颜相机入门(兼具图像处理和画图板功能)

三、源代码

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;

public class DrawUI {

    ImageListener ul = new ImageListener();
    ImagePanel imgPanel = new ImagePanel();
    ImageUtils iu = new ImageUtils();

    public void initUI(){
        JFrame jf = new JFrame();
        jf.setSize(1400,900);
        jf.setTitle("PC版美颜相机");
        jf.setLocationRelativeTo(null);
        jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jf.setVisible(true);

        JPanel[] jps = addPanel(jf);
        addButton(jps);
        addJSlider(jps);
        addMenu(jf);

        Graphics gr = imgPanel.getGraphics();
        ul.g = gr;
        ul.imgPanel = imgPanel;
        imgPanel.imglist = ul.imglist;
        imgPanel.shapeArr = ul.shapeArr;

    }

    private void addJSlider(JPanel[] jps) {

        JLabel j0 = new JLabel("                                                ");
        j0.setFont(new Font("黑体",1,30));
        jps[2].add(j0);
        JLabel j1 = new JLabel("大小/程度选择:");
        j1.setFont(new Font("黑体",1,30));
        jps[2].add(j1);

        JSlider jSlider = new JSlider(0,100);
        Dimension dm = new Dimension(300,80);  //设置按钮尺寸
        jSlider.setPreferredSize (dm);
        jSlider.setFont (new Font ("黑体",1,15));
        jSlider.setMajorTickSpacing(20);
        jSlider.setMinorTickSpacing(5);
        jSlider.setPaintLabels(true);//确定是否在滑块上绘制标签
        jSlider.setPaintTicks(true);//确定是否在滑块上绘制刻度标记
        jSlider.setPaintTrack(true);//确定是否在滑块上绘制滑道
        jSlider.setSnapToTicks(true);//指定为 true,则滑块(及其所表示的值)解析为最靠近用户放置滑块处的刻度标记的值
        jSlider.setOpaque(false);
        jps[2].add(jSlider);
        jSlider.addChangeListener(new ChangeListener() {
            @Override
            public void stateChanged(ChangeEvent e) {
                System.out.println("当前值: " + jSlider.getValue());
                int p = jSlider.getValue();
                iu.p = p;
            }
        });
    }

    private void addMenu(JFrame jf) {
        //菜单栏
        JMenuBar jmb = new JMenuBar();
        jf.add(jmb,BorderLayout.NORTH);

        //菜单选项
        JMenu file = new JMenu("文件");
        file.setPreferredSize(new Dimension(80,40));
        file.setFont(new Font("宋体",2,22));
        jmb.add(file);

        //子菜单
        JMenuItem jmi1 = new JMenuItem("打开");
        jmi1.setPreferredSize(new Dimension(80,40));
        jmi1.setFont(new Font("宋体",2,22));
        jmi1.addActionListener(ul);
        file.add(jmi1);
        JMenuItem jmi2 = new JMenuItem("保存");
        jmi2.setPreferredSize(new Dimension(80,40));
        jmi2.setFont(new Font("宋体",2,22));
        jmi2.addActionListener(ul);
        file.add(jmi2);

        jf.setVisible(true);
    }

    private void addButton(JPanel[] jps) {

        String[] btnstrs1 = new String[]{"原图","撤回","马赛克","灰度","轮廓","二值化","油画",
                "美白","运动模糊","卷积","锐化","浮雕","左旋","右旋","放大","缩小","打开摄像头","关闭摄像头"};
        for(int i = 0; i < btnstrs1.length-2; i++){
            JButton btn = new JButton(btnstrs1[i]);
            Dimension dim = new Dimension(120,40);
            btn.setPreferredSize(dim);
            btn.setFont(new Font("黑体",1,20));
            btn.setBackground(Color.WHITE);
            btn.addActionListener(ul);
            jps[2].add(btn);
        }

        for(int i = btnstrs1.length-2; i < btnstrs1.length; i++){
            JButton btn = new JButton(btnstrs1[i]);
            Dimension dim = new Dimension(200,40);
            btn.setPreferredSize(dim);
            btn.setFont(new Font("黑体",1,20));
            btn.setBackground(Color.WHITE);
            btn.addActionListener(ul);
            jps[2].add(btn);
        }

        String[] btnstrs2 = new String[] {"直线","矩形","椭圆","三角形","正方形","菱形","特殊三角形","多边形","画点","迭代","树"};
        for(int i = 0; i < btnstrs2.length; i++) {
            JButton btn = new JButton(btnstrs2[i]);
            Dimension dim = new Dimension(120,40);
            btn.setPreferredSize (dim);
            btn.setFont (new Font ("黑体",1,16));
            btn.setBackground (Color.WHITE);
            btn.addActionListener (ul);
            jps[1].add (btn);
        }

        Color []color= {Color.BLUE,Color.GREEN,Color.YELLOW,Color.BLACK,Color.ORANGE,
        Color.GRAY,Color.RED};
        for(int i=0;i
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class ImageListener implements MouseListener, ActionListener {
    public Graphics g = null;
    public int p;
    public ImagePanel imgPanel;
    public ArrayList  imglist = new ArrayList<>();
    private String name = null;
    public int flag = 1;
    public int x1,y1,x2,y2,x3,y3,x4,y4;
    public Color color;
    public MyShape[] shapeArr = new MyShape[100];
    public int index;
    boolean flag1 = false;
    public ThreadPixel tp;

    ImageUtils imageUtils = new ImageUtils ();
    int[][] readImagePixArray = imageUtils.readImagePix ("D:/img1.png");
    BufferedImage buffimg = null;

    @Override
    public void actionPerformed(ActionEvent e) {
        name = e.getActionCommand();

        if (name.equals ("原图")) {
            buffimg = imageUtils.drawImage_00 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("撤回")) {
            imglist.remove(imglist.size() - 1);
            imgPanel.repaint();
        }else if (name.equals("马赛克")) {
            buffimg = imageUtils.drawImage_01 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("灰度")) {
            buffimg = imageUtils.drawImage_02 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("轮廓")) {
            buffimg = imageUtils.drawImage_03 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("二值化")) {
            buffimg = imageUtils.drawImage_04 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("油画")) {
            buffimg = imageUtils.drawImage_05 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("美白")) {
            buffimg = imageUtils.drawImage_06 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("运动模糊")) {
            buffimg = imageUtils.drawImage_07 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("卷积")) {
            buffimg = imageUtils.drawImage_08 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("锐化")) {
            buffimg = imageUtils.drawImage_09 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("浮雕")) {
            buffimg = imageUtils.drawImage_10 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("左旋")) {
            buffimg = imageUtils.drawImage_11 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("右旋")) {
            buffimg = imageUtils.drawImage_12 (readImagePixArray);
            imglist.add (buffimg);
            imgPanel.repaint();
        }else if (name.equals("放大")) {
            imageUtils.drawImage_13 (readImagePixArray);
            imgPanel.repaint();
        }else if (name.equals("缩小")) {
            imageUtils.drawImage_14 (readImagePixArray);
            imgPanel.repaint();
        }else if (name.equals("打开摄像头")) {
            // 启动多线程
            // 创建线程对象,显示该线程创建一次
            if (tp == null) {
                tp = new ThreadPixel(g);
                tp.flag = true;
                // 启动线程
                tp.start();
            }
        }else if (name.equals("关闭摄像头")) {
            tp.flag = false;
        }

        if("".equals(e.getActionCommand())) {
            JButton jbu=(JButton)e.getSource();
            color=jbu.getBackground();
            g.setColor(color);
        }

        if("画点".equals(name)) {
            int xa,xb,xc,xd,ya,yb,yc,yd;
            xa=(int)(Math.random()*920+50);
            xb=(int)(Math.random()*920+50);
            xc=(int)(Math.random()*920+50);
            xd=(int)(Math.random()*920+50);
            ya=(int)(Math.random()*800+50);
            yb=(int)(Math.random()*800+50);
            yc=(int)(Math.random()*800+50);
            yd=(int)(Math.random()*800+50);

            for (int i=0;i=0) {
                    g.drawLine((xa+xd)/2, (ya+yd)/2, (xa+xd)/2, (ya+yd)/2);
                    xd=(xa+xd)/2;
                    yd=(ya+yd)/2;
                }
                else if(p=300) {
                    g.drawLine((xb+xd)/2, (yb+yd)/2, (xb+xd)/2, (yb+yd)/2);
                    xd=(xb+xd)/2;
                    yd=(yb+yd)/2;
                }
                else {
                    g.drawLine((xc+xd)/2, (yc+yd)/2, (xc+xd)/2, (yc+yd)/2);
                    xd=(xc+xd)/2;
                    yd=(yc+yd)/2;
                }
            }
        }

        if("迭代".equals(name)) {
            double x=0,y=0;
            double a=-1.7,b=-2.5,c=-2,d=-2;
            for (int i=0;i=0) {
                    double a=0.1950,b=-0.4880,c=0.3440,d=0.4430,ee=0.4431,f=0.2452;
                    xn=a*x+b*y+ee;
                    yn=c*x+d*y+f;
                    System.out.println("x="+xn+"  y="+yn);
                    g.drawLine((int)(900-xn*1000), (int)(900-yn*1000), (int)(900-xn*1000), (int)(900-yn*1000));
                    x=xn;
                    y=yn;
                }
                else if(p1=200) {
                    double a=0.4620,b=0.4140,c=-0.2520,d=0.3610,ee=0.2511,f=0.5692;
                    xn=a*x+b*y+ee;
                    yn=c*x+d*y+f;
                    System.out.println("x="+xn+"  y="+yn);
                    g.drawLine((int)(900-xn*1000), (int)(900-yn*1000), (int)(900-xn*1000), (int)(900-yn*1000));
                    x=xn;
                    y=yn;
                }
                else if(p1=400) {
                    double a=-0.6370,b=0.0000,c=0.0000,d=0.5010,ee=0.8562,f=0.2512;
                    xn=a*x+b*y+ee;
                    yn=c*x+d*y+f;
                    System.out.println("x="+xn+"  y="+yn);
                    g.drawLine((int)(900-xn*1000), (int)(900-yn*1000), (int)(900-xn*1000), (int)(900-yn*1000));
                    x=xn;
                    y=yn;
                }
                else if(p1=600) {
                    double a=-0.0350,b=0.0700,c=-0.4690,d=0.0220,ee=0.4884,f=0.5069;
                    xn=a*x+b*y+ee;
                    yn=c*x+d*y+f;
                    System.out.println("x="+xn+"  y="+yn);
                    g.drawLine((int)(900-xn*1000), (int)(900-yn*1000), (int)(900-xn*1000), (int)(900-yn*1000));
                    x=xn;
                    y=yn;
                }
                else {
                    double a=-0.0580,b=-0.0700,c=0.4530,d=-0.1110,ee=0.5976,f=0.0969;
                    xn=a*x+b*y+ee;
                    yn=c*x+d*y+f;
                    System.out.println("x="+xn+"  y="+yn);
                    g.drawLine((int)(900-xn*1000), (int)(900-yn*1000), (int)(900-xn*1000), (int)(900-yn*1000));
                    x=xn;
                    y=yn;
                }
            }
        }

    }

    @Override
    public void mouseClicked(MouseEvent e) {
        x4=e.getX();
        y4=e.getY();

        if("特殊三角形".equals(name)&&flag==2) {
            g.drawLine(x1, y1, x4, y4);
            g.drawLine(x2, y2, x4, y4);
            flag = 1;

            MyShape shape1 = new MyShape();
            shape1.name = name;
            shape1.color = color;
            shape1.x1 = x1;
            shape1.x2 = x4;
            shape1.y1 = y1;
            shape1.y2 = y4;
            shapeArr[index++] = shape1;

            MyShape shape2 = new MyShape();
            shape2.name = name;
            shape2.color = color;
            shape2.x1 = x4;
            shape2.x2 = x2;
            shape2.y1 = y4;
            shape2.y2 = y2;
            shapeArr[index++] = shape2;

        }

        if("多边形".equals(name)&&flag==2) {
            if(!flag1) {
                x3=x2;
                y3=y2;
                flag1=true;
            }

            g.drawLine(x3, y3, x4, y4);

            MyShape shape3 = new MyShape();
            shape3.name=name;
            shape3.color=color;
            shape3.x1=x4;
            shape3.x2=x3;
            shape3.y1=y4;
            shape3.y2=y3;
            shapeArr[index++]=shape3;

            x3=x4;
            y3=y4;

            if(e.getClickCount() == 2) {
                g.drawLine(x1, y1, x4, y4);
                flag=1;

                MyShape shape4 = new MyShape();
                shape4.name=name;
                shape4.color=color;
                shape4.x1=x4;
                shape4.x2=x1;
                shape4.y1=y4;
                shape4.y2=y1;
                shapeArr[index++]=shape4;

            }
        }
    }

    @Override
    public void mousePressed(MouseEvent e) {

        if(flag==1){
            x1=e.getX();
            y1=e.getY();
        }

    }

    @Override
    public void mouseReleased(MouseEvent e) {
        System.out.println("x1="+x1+";y1="+y1+";x2="+x2+";y2="+y2);
        if(flag==1){
            x2=e.getX();
            y2=e.getY();
        }

        if("直线".equals(name)){
            g.drawLine(x1, y1, x2, y2);
        }

        if("矩形".equals(name)){
            g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2-x1), Math.abs(y2-y1));
        }

        if("椭圆".equals(name)){
            g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2-x1), Math.abs(y2-y1));
        }

        if("三角形".equals(name)){
            int[]xPoints=new int[] {x1,(x1+x2)/2,x2};
            int[]yPoints=new int[] {y2,y1,y2};
            int nPoints=3;
            g.drawPolygon(xPoints, yPoints, nPoints);
        }

        if("正方形".equals(name)){
            g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2-x1), Math.abs(x2-x1));
        }

        if("菱形".equals(name)){
            int[]xPoints=new int[] {(x1+x2)/2,x2,(x1+x2)/2,x1};
            int[]yPoints=new int[] {y2,(y1+y2)/2,y1,(y1+y2)/2};
            int nPoints=4;
            g.drawPolygon(xPoints, yPoints, nPoints);
        }

        if("特殊三角形".equals(name)&&flag==1){
            g.drawLine(x1,y1,x2,y2);
            flag++;
        }

        if("多边形".equals(name)&&flag==1){
            g.drawLine(x1,y1,x2,y2);
            flag++;
        }

        MyShape shape = new MyShape();
        shape.name = name;
        shape.color = color;
        shape.x1 = x1;
        shape.x2 = x2;
        shape.y1 = y1;
        shape.y2 = y2;
        shapeArr[index++] = shape;
    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
}
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.ArrayList;

public class ImagePanel extends JPanel {

    public ArrayList imglist = new ArrayList<>();

    public MyShape[] shapeArr = new MyShape[100];
    public static int width;
    public static int height;

    public void paint(Graphics gr) {
        super.paint(gr);
        System.out.println ("绘制" + getWidth () + " " + getHeight ());
        if(imglist.size () > 0){
            BufferedImage buffimg = imglist.get (imglist.size () - 1);
            BufferedImage newBuffimg = new BufferedImage (width,height,BufferedImage.TYPE_INT_ARGB);
            Graphics bg = newBuffimg.getGraphics ();
            bg.drawImage (buffimg,0,0,width,height,null);
            gr.drawImage (newBuffimg,0,0,null);
        }

        System.out.println("绘制组件!");
        for(int i = 0; i < shapeArr.length; i++) {
                if (shapeArr[i] == null) break;
            MyShape shape = shapeArr[i];
            shape.drawShape(gr);
        }
    }
}
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

// 继承JPanel 重写paint 方法
public class ImageUtils{

    public static int p = 50;
    ImagePanel imgPanel = new ImagePanel();

    public int[][] readImagePix(String path){
        // 文件对象
        File file = new File (path);
        BufferedImage readimg = null;
        try {
            readimg = ImageIO.read (file);
        } catch (IOException e) {
            e.printStackTrace ();
        }
        int width = readimg.getWidth ();
        int height = readimg.getHeight ();
        int height0 = 0;
        int width0 = 0;
        if(width >= height){
            height0 = width;
            width0 = width;
        }
        if(width < height){
            width0 = height;
            height0 = height;
        }
        imgPanel.width = width;
        imgPanel.height= height;
        int[][] imgArray = new int[width0][height0];
        for(int i = 0; i < width; i++){
            for(int j = 0; j < height; j++){
                imgArray[i][j] = readimg.getRGB (i, j);
            }
        }
        return imgArray;
    }

    public int getRgbGray(int numPixels){
        // byte -128 127
        int red = (numPixels>>16)&0xFF;
        int green = (numPixels>>8)&255;
        int blue = (numPixels>>0)&255;
        // 灰度 -- 减少计算量 以及 更方便计算
        int gray = (red + green + blue) / 3;
        return gray;
    }

    //根据二维数组 绘制图片
    public BufferedImage drawImage_00(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage ( imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        for(int i = 0; i < imgArray.length; i++){
            for(int j = 0; j < imgArray[i].length; j++){
                buffimg.setRGB (i,j,imgArray[i][j]);
            }
        }
        return buffimg;
    }

    //根据二维数组 绘制图片
    public BufferedImage drawImage_01(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage ( imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);

        System.out.print("iup = "+p);
        if(p < 20)p = 20;

        //可使用fillRect

        for(int i = p/10; i < imgArray.length; i += (2*(p/10)+1)){
            for(int j = p/10; j < imgArray[i].length; j += (2*(p/10)+1)){

                int mm,nn;
                if(i+(p/10+1)>imgArray.length) {
                    mm = imgArray.length;
                }else {
                    mm = i+(p/10+1);
                }
                if(j+(p/10+1)>imgArray[i].length) {
                    nn = imgArray[i].length;
                }else {
                    nn = j+(p/10+1);
                }

                for(int m=i-p/10;m (7+p/10))||(Math.abs (gray1 - gray3) > (7+p/10))||(Math.abs (gray1 - gray4) > (7+p/10))||(Math.abs (gray1 - gray5) > (7+p/10))){
                // 绘制为白色
                    buffimg.setRGB (i, j, Color.WHITE.getRGB ());
                } else{
                // 绘制为黑色
                    buffimg.setRGB (i, j, Color.BLACK.getRGB ());
                }
            }
        }
        return buffimg;
    }

    // 根据二维数组 绘制图片
    public BufferedImage drawImage_04(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        for(int i = 0; i < imgArray.length; i++){
            for(int j = 0; j < imgArray[i].length; j++){
                int num1 = imgArray[i][j];
                int gray1 = getRgbGray (num1);
                if(gray1 > 78+p){
                    // 绘制为白色
                    buffimg.setRGB (i, j, Color.WHITE.getRGB ());
                } else{
                    // 绘制为黑色
                    buffimg.setRGB (i, j, Color.BLACK.getRGB ());
                }
            }
        }
        return buffimg;
    }

    //根据二维数组 绘制图片
    public BufferedImage drawImage_05(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        Graphics bg = buffimg.getGraphics();
        for(int i = (10+p/10); i < imgArray.length; i += (3+p/10)) {
            for(int j = (5+p/10);j < imgArray[i].length; j += (3+p/10)) {
                int num = imgArray[i][j];
                Color color = new Color (num);
                bg.setColor(color);
                int r1 = (int)(Math.random()*(40+p/5));
                int r2 = (int)(Math.random()*(30+p/5));
                bg.fillOval(i-(20+p/10), j-(15+p/10), Math.max(r1,r2), Math.min(r1,r2));
            }

        }
        return buffimg;
    }

    //根据二维数组 绘制图片
    public BufferedImage drawImage_06(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        for(int i = 0; i < imgArray.length; i++){
            for(int j = 0; j < imgArray[i].length; j++){
                int num = imgArray[i][j];
                Color color = new Color (num);
                int red = color.getRed ();
                int green = color.getGreen ();
                int blue = color.getBlue ();

                int rednext = red + (3+p/3);
                if(rednext > 255){
                    rednext = 255;
                }
                int greennext = green + (3+p/3);
                if(greennext > 255){
                    greennext = 255;
                }
                int bluenext = blue + (3+p/3);
                if(bluenext > 255){
                    bluenext = 255;
                }
                Color newColor = new Color (rednext, greennext, bluenext);
                // 缓冲绘制
                buffimg.setRGB (i, j, newColor.getRGB ());
            }
        }
        return buffimg;
    }

    //根据二维数组 绘制图片
    public BufferedImage drawImage_07(int[][] imgArray){
        BufferedImage buffimg = new BufferedImage (imgArray.length, imgArray[0].length, BufferedImage.TYPE_INT_ARGB);
        if(p> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];

                        }
                    }
                    redvalue = redvalue/5;
                    greenvalue = greenvalue/5;
                    bluevalue = bluevalue/5;

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue50) {
            float[][] fls= {
                    {1,0,0,0,0,0,0,0,0},
                    {0,1,0,0,0,0,0,0,0},
                    {0,0,1,0,0,0,0,0,0},
                    {0,0,0,1,0,0,0,0,0},
                    {0,0,0,0,1,0,0,0,0},
                    {0,0,0,0,0,1,0,0,0},
                    {0,0,0,0,0,0,1,0,0},
                    {0,0,0,0,0,0,0,1,0},
                    {0,0,0,0,0,0,0,0,1},
            };

            for(int i=0;i> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }
                    redvalue = redvalue/9;
                    greenvalue = greenvalue/9;
                    bluevalue = bluevalue/9;

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue50) {
            float[][] fls= {
                    {-1,-1,-1,-1,0},
                    {-1,-1,-1,0,1},
                    {-1,-1,0,1,1},
                    {-1,0,1,1,1},
                    {0,1,1,1,1},
            };

            for(int i=0;i> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue50) {
            float[][] fls= {
                    {-1,-1,-1,-1,-1},
                    {-1,-1,-1,-1,-1},
                    {-1,-1,25,-1,-1},
                    {-1,-1,-1,-1,-1},
                    {-1,-1,-1,-1,-1},
            };

            for(int i=0;i> 16) & 0xFF;
                            int green = (rgbvalue >> 8) & 0xFF;
                            int blue = (rgbvalue) & 0xFF;
                            redvalue += red * fls[k][l];
                            greenvalue += green * fls[k][l];
                            bluevalue += blue * fls[k][l];
                        }
                    }

                    if(redvalue>255)redvalue=255;
                    if(greenvalue>255)greenvalue=255;
                    if(bluevalue>255)bluevalue=255;
                    if(redvalue>16)&0xFF;
                int green1 = (rgbvalue1>>8)&0xFF;
                int blue1 = (rgbvalue1)&0xFF;

                int red2 = (rgbvalue2>>16)&0xFF;
                int green2 = (rgbvalue2>>8)&0xFF;
                int blue2 = (rgbvalue2)&0xFF;

                redvalue = red1-red2+128;
                greenvalue = green1-green2+128;
                bluevalue = blue1-blue2+128;

                int gray = (redvalue + greenvalue + bluevalue) / 3;

                if(gray>255)gray=255;
                if(gray
import java.awt.*;

public class MyShape {
    public int x1,x2,y1,y2;
    public String name="";
    public Color color;

    public void drawShape(Graphics g) {
        System.out.println("name = "+name);
        switch(name) {

            case"直线":
                g.setColor(color);
                g.drawLine(x1,y1,x2,y2);
                break;

            case"矩形":
                g.setColor(color);
                g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2-x1), Math.abs(y2-y1));
                break;

            case"椭圆":
                g.setColor(color);
                g.drawOval(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2-x1), Math.abs(y2-y1));
                break;

            case"三角形":
                g.setColor(color);
                int[]xPoints1=new int[] {x1,(x1+x2)/2,x2};
                int[]yPoints1=new int[] {y2,y1,y2};
                int nPoints1=3;
                g.drawPolygon(xPoints1,yPoints1,nPoints1);
                break;

            case"正方形":
                g.setColor(color);
                g.drawRect(Math.min(x1, x2), Math.min(y1, y2), Math.abs(x2-x1), Math.abs(x2-x1));
                break;

            case"菱形":
                g.setColor(color);
                int[]xPoints2=new int[] {(x1+x2)/2,x2,(x1+x2)/2,x1};
                int[]yPoints2=new int[] {y2,(y1+y2)/2,y1,(y1+y2)/2};
                int nPoints2=4;
                g.drawPolygon(xPoints2, yPoints2, nPoints2);
                break;

            case"特殊三角形":
                g.setColor(color);
                g.drawLine(x1,y1,x2,y2);
                break;

            case"多边形":
                g.setColor(color);
                g.drawLine(x1,y1,x2,y2);
                break;
        }
    }
}
import java.awt.Graphics;
import java.awt.image.BufferedImage;

import com.github.sarxos.webcam.Webcam;

//定义线程类
public class ThreadPixel extends Thread {
    public Graphics g;
    public boolean flag = true;  //控制线程的标记

    //初始化画笔对象
    public ThreadPixel(Graphics g) {
        this.g = g;
    }

    // 启动线程后自定执行的方法
    // run 方法执行完,该线程结束,线程一旦结束不能再次启动
    public void run() {
        System.out.println("启动线程.."+this.getName());

        // 启动摄像头,放在线程中启动
        Webcam webcam = Webcam.getDefault();
        webcam.open();

        while (flag) {
            // 获取摄像头拍到的数据
            BufferedImage bufferedImage = webcam.getImage();
            g.drawImage(bufferedImage, 50, 50,800,600, null);
        }
    }
}

JAVA美颜相机入门(兼具图像处理和画图板功能)

Original: https://blog.csdn.net/xinghuowuyin/article/details/123158563
Author: xinghuowuyin
Title: JAVA美颜相机入门(兼具图像处理和画图板功能)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/644819/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球