调用另一个方法后调用方法时出现 nullpointerException?

发布于 2024-12-10 03:19:38 字数 20276 浏览 1 评论 0原文

我有一个图像编辑程序。它有多种方法,例如灰度、缩放、合并图像等。每种方法都可以完美地工作。但是,在调用 mergeImg 方法后调用 GrayScale 方法时出现错误。如果我先应用灰度就不会发生这种情况。

这是错误:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Picture.width(Picture.java:51)
at Picture$4.actionPerformed(Picture.java:222)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
at java.awt.Component.processMouseEvent(Component.java:6504)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

这是我的代码:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.lang.Math;

public class Picture{
    JFileChooser fileChooser = new JFileChooser(); //file chooser
    final JFrame frame = new JFrame("ImageEdit");  //creates JFrame
    Container content; //creates container to place GUI objects in
    static BufferedImage image; //original image
    BufferedImage image2; //image after changes are made
    BufferedImage mergeImage; //used for mergeImg method
    JLabel imageLabel; //used to display image

    //constructor; welcomes user, asks for image input
    public Picture() {
        //pops up prior to JFileChooser, intstructing user on what to do
        Object[] options = {"Browse...", "Exit"};
        ImageIcon welcomeIcon = new ImageIcon("GUI-images/welcome-icon.png");
        int getFile = JOptionPane.showOptionDialog(frame, "Welcome to ImageEdit. To begin, please select an image file to edit.", 
                "Welcome!", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, welcomeIcon, options, options[0]);

        //if user selects browse option, do this:
        if (getFile == JOptionPane.YES_OPTION) {
            //asks for image file as input
            browse();
        }

        //otherwise, exit program
        else {
            //exit program
            System.exit(0); 
        }
    }

    //method returns width of image
    public int width() {
        int width = image.getWidth();
        return width;
    }

    //method returns height of image
    public int height() {
        int height = image.getHeight();
        return height;
    }

    //method sets updated image as "original" image
    public void setImage() {
        this.image = image2;
    }

    //method writes image in destination
    public void saveImage() {
        //gets file name & destination from user through JFileChooser
        fileChooser.setDialogTitle("Save As...");
        fileChooser.showSaveDialog(frame);

        //writes image to new file with given name & location
        try {
            ImageIO.write(this.image, "JPG", fileChooser.getSelectedFile());
        }
        catch (IOException f) {
            System.out.println("Saving failed! Could not save image.");
        }
    }

    //method browses for new file
    public void browse() {
        //asks for new image file
        fileChooser.setDialogTitle("Choose an image file:");
        fileChooser.showOpenDialog(frame);
        File selectedFile = fileChooser.getSelectedFile();

        //if user has selected image file, continue
        if (fileChooser.getSelectedFile() != null) {
            try {
                //reads selectedFile as image
                image = ImageIO.read(selectedFile);
            } 
            catch (IOException e) {
                System.out.println("Invalid image file: " + selectedFile);
                System.exit(0);
            }
        }

        //else print error message
        else {
            System.out.println("Error! No File Selected.");
        }
    }

    //method creates frame, adds menubar with options, provides parameters for other methods
    public void show() {
        //set frame title, set it visible, etc
        content = frame.getContentPane();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);

        //add the image to the frame
        ImageIcon icon = new ImageIcon(image);
        imageLabel = new JLabel(icon);
        frame.setContentPane(imageLabel);

        //adds a menubar on the frame with program name, File & Edit menus
        JMenuBar menuBar = new JMenuBar();
        frame.setJMenuBar(menuBar);
        JMenu progName = new JMenu("ImageEdit");
        progName.setBackground(Color.RED);
        menuBar.add(progName);
        JMenu fileMenu = new JMenu("File");
        menuBar.add(fileMenu);
        JMenu editMenu = new JMenu("Edit");
        menuBar.add(editMenu);

        //adds options to JMenus
        //option to exit application
        ImageIcon exitIcon = new ImageIcon("GUI-images/app-exit.png");
        JMenuItem exitAction = new JMenuItem("Exit", exitIcon);
        progName.add(exitAction);

        //if exit option is selected, do this:
        exitAction.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //prompts to save file before exiting
                    ImageIcon saveIcon = new ImageIcon("GUI-images/save-icon.png");
                    int askSave = JOptionPane.showConfirmDialog(null,"Save image before exit?", "Save...", 
                            JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
                    if (askSave == JOptionPane.YES_OPTION) {
                        //opens save image method, then exits
                        saveImage();
                        System.exit(0);
                    }
                    else {
                        //exits without saving
                        System.exit(0);
                    }
                }
            });

        //option to open a new image
        ImageIcon newIcon = new ImageIcon("GUI-images/new-image.png");
        JMenuItem newAction = new JMenuItem("Open Image", newIcon);
        fileMenu.add(newAction);

        //if new option is selected, do this:
        newAction.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //prompts to save image before opening new image
                    ImageIcon saveIcon = new ImageIcon("GUI-images/save-icon.png");
                    int askSave = JOptionPane.showConfirmDialog(null,"Save current image?", "Save...", 
                            JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
                    //if they do want to save first, do this:
                    if (askSave == JOptionPane.YES_OPTION) {
                        //opens save image method, then asks asks for new image file
                        saveImage();

                        //clears old image
                        imageLabel.setIcon(null);

                        //browses for new image
                        browse();
                        //displays new image
                        imageLabel.setIcon(new ImageIcon(image));

                        //resizes canvas to fit new image
                        frame.setSize(width(), height());
                    }
                    //if they don't want to save, do this:
                    else {
                        //erases old image
                        imageLabel.setIcon(null);

                        //browses for new image
                        browse();

                        //displays new image
                        imageLabel.setIcon(new ImageIcon(image));

                        //resizes canvas to fit new image
                        frame.setSize(width(), height());
                    }
                }
            });

        //option to save current image
        ImageIcon saveIcon = new ImageIcon("GUI-images/save-image.png");
        JMenuItem saveAction = new JMenuItem("Save Image As...", saveIcon);
        fileMenu.add(saveAction);

        //if save option is selected, do this:
        saveAction.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //opens save image method
                    saveImage();
                }
            });

        //option to make current image grayscale
        ImageIcon gsIcon = new ImageIcon("GUI-images/grayscale-image.png");
        JMenuItem grayScale = new JMenuItem("Grayscale", gsIcon);
        editMenu.add(grayScale);

        //if grayscale option is selected, do this:
        grayScale.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //grabs height and width of image,
                    //then calls grayscale method
                    grayscale(width(), height());
                }
            });

        //option to scale current window to new dimensions
        ImageIcon scaleIcon = new ImageIcon("GUI-images/scale-image.png");
        JMenuItem scaleImg = new JMenuItem("Scale Image", scaleIcon);
        editMenu.add(scaleImg);

        //if scale option is selected, do this:
        scaleImg.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //asks for height and width to create new image
                    ImageIcon widthIcon = new ImageIcon("GUI-images/LR-arrows.png");
                    String scaleWidth = (String)JOptionPane.showInputDialog(null,"What should the new width be?", 
                            "Scale Image", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);
                    ImageIcon heightIcon = new ImageIcon("GUI-images/UD-arrows.png");
                    String scaleHeight = (String)JOptionPane.showInputDialog(null,"What should the new height be?", 
                            "Scale Image", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);

                    //turns user input strings into doubles
                    double x = Double.parseDouble(scaleWidth);
                    double y = Double.parseDouble(scaleHeight);

                    //casts doubles as ints
                    int newWidth = (int)x;
                    int newHeight = (int)y;

                    //resizes frame to fit new image dimensions
                    frame.setSize(newWidth, newHeight);

                    //calls scale method to resize image using given dimensions
                    scale(newWidth, newHeight);
                }
            });

        //option to merge two images together
        ImageIcon mergeIcon = new ImageIcon("GUI-images/merge-image.png");
        JMenuItem mergeImg = new JMenuItem("Merge Image", mergeIcon);
        editMenu.add(mergeImg);

        //if merge option is selected, do this:
        mergeImg.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //asks for image file as input
                    fileChooser.setDialogTitle("Choose an image file to merge current image with.");
                    fileChooser.showOpenDialog(frame);
                    File mergeFile = fileChooser.getSelectedFile();

                    //if user has selected image file, continue
                    if (fileChooser.getSelectedFile() != null) {
                        try {
                            //reads selectedFile as image
                            mergeImage = ImageIO.read(mergeFile);
                        } 
                        catch (IOException f) {
                            System.out.println("Invalid image file: " + mergeFile);
                            System.exit(0);
                        }
                    }

                    //else print error message
                    else {
                        System.out.println("Error! No File Selected.");
                    }

                    //if two images are same size, merge them
                    if (width() == mergeImage.getWidth() && height() == mergeImage.getHeight()) {
                        mergeImg(width(), height(), mergeImage);
                    }
                    //else, resize the second image to size of original, then merge
                    else {
                        scale(width(), height());
                        mergeImg(width(), height(), mergeImage);
                    }
                }
            });

        //option to rotate image by x degrees
        ImageIcon rotateIcon = new ImageIcon("GUI-images/rotate-image.png");
        JMenuItem rotateImage = new JMenuItem("Rotate Image", rotateIcon);
        editMenu.add(rotateImage);

        //if rotate option is selected, do this:
        rotateImage.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    String rotateAngle = (String)JOptionPane.showInputDialog(null,"By what angle would you like to rotate?", 
                            "Input Degrees", JOptionPane.QUESTION_MESSAGE, null/*icon goes here*/, null, null);

                    //turns user input strings into doubles
                    double angleDegs = Double.parseDouble(rotateAngle);

                    //converts degrees to rads
                    double angle = Math.toRadians(angleDegs);

                    //applies sine and cosine functions
                    int sin = (int)Math.sin(angle);
                    int cos = (int)Math.cos(angle);

                    //gets new width of rotated image
                    int newWidth = width()*sin + height()*cos;
                    int newHeight = height()*sin + width()*cos;

                    //sets frame to new image size
                    frame.setSize(newWidth, newHeight);

                    //calls rotate method to rotate image
                    rotate(newWidth, newHeight, angle);
                }
            });

        //paint the frame
        frame.pack();
        frame.repaint();
        frame.setVisible(true);
    }

    //method converts image to grayscale; 6 lines of code
    public void grayscale(int width, int height) {
        // create a grayscale image with original dimensions
        image2 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);

        // convert colored image to grayscale
        ColorConvertOp grayScale = new ColorConvertOp(image.getColorModel().getColorSpace(),
                image2.getColorModel().getColorSpace(),null);
        grayScale.filter(image,image2);
        imageLabel.setIcon(new ImageIcon(image2));

        //sets new image as "original"
        setImage();
    }

    //method scales image to user-input dimensions; 5 lines of code
    public void scale(int width, int height){
        //uses user-input dimensions to create new image
        image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = image2.createGraphics();

        //gets new dimensions and resizes image
        g.drawImage(image, 0, 0, image2.getWidth(), image2.getHeight(), 0, 0, width(), height(), null);  
        imageLabel.setIcon(new ImageIcon(image2));

        //sets new image as "original"
        setImage();
    }

    //method merges two images together; 14 lines of code
    public void mergeImg(int width, int height, BufferedImage mergeImage) {
        //creates new image from two images of same size
        BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                //get color from original image
                Color c = new Color(image.getRGB(i, j));

                //get colors from merge image
                Color c2 = new Color(mergeImage.getRGB(i, j));

                //average the colors
                int r = (c.getRed()+c2.getRed())/2;
                int g = (c.getGreen()+c2.getGreen())/2;
                int b = (c.getBlue()+c2.getBlue())/2;
                Color avgColor = new Color(r, g, b);

                //set colors of new image to average of the two images
                image2.setRGB(i, j, avgColor.getRGB());
                imageLabel.setIcon(new ImageIcon(image2));
            }
        }

        mergeImage = null;
        //sets new image as "original"
        setImage();
    }

    //method rotates image by user-input angle; 18 lines of code
    public void rotate(int width, int height, double angle) {
        //rotates image around center point
        BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        //defines sin and cos functions
        double sin = Math.sin(angle);
        double cos = Math.cos(angle);

        //gets coordinates of image center
        double Xc = width/2;
        double Yc = height/2;

        //rotate
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                //new i,j at center of image
                double iPrime = i - Xc;
                double jPrime = j - Yc;
                //i,j at new points after rotation
                int xPrime = (int) (iPrime * cos - jPrime * sin + Xc);
                int yPrime = (int) (iPrime * sin + jPrime * cos + Yc);

                // plot pixel (i, j) the same color as (xPrime, yPrime) if it's in bounds
                if (xPrime >= 0 && xPrime < width && yPrime >= 0 && yPrime < height) {
                    image2.setRGB(xPrime, yPrime, image.getRGB(i, j));
                    imageLabel.setIcon(new ImageIcon(image2));
                }
            }
        }

        //sets new image as "original"
        setImage();
    }

    //main method; starts program
    public static void main(String[] args) {
        //creates new picture from image file
        Picture p = new Picture();

        //shows picture on JFrame
        p.show();
    }
}

有什么想法吗?感谢您的帮助!

I have an image editing program. It has several methods, such as grayscale, scale, merge images, etc. Each method works perfectly on its own. However, I am getting an error when calling grayScale method after mergeImg method has been called. It doesn't happen if I apply grayscale first.

Here is the error:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
at Picture.width(Picture.java:51)
at Picture$4.actionPerformed(Picture.java:222)
at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
at java.awt.Component.processMouseEvent(Component.java:6504)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6269)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4860)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4686)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)

And here is my code:

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
import javax.swing.*;
import java.awt.image.*;
import javax.imageio.ImageIO;
import java.lang.Math;

public class Picture{
    JFileChooser fileChooser = new JFileChooser(); //file chooser
    final JFrame frame = new JFrame("ImageEdit");  //creates JFrame
    Container content; //creates container to place GUI objects in
    static BufferedImage image; //original image
    BufferedImage image2; //image after changes are made
    BufferedImage mergeImage; //used for mergeImg method
    JLabel imageLabel; //used to display image

    //constructor; welcomes user, asks for image input
    public Picture() {
        //pops up prior to JFileChooser, intstructing user on what to do
        Object[] options = {"Browse...", "Exit"};
        ImageIcon welcomeIcon = new ImageIcon("GUI-images/welcome-icon.png");
        int getFile = JOptionPane.showOptionDialog(frame, "Welcome to ImageEdit. To begin, please select an image file to edit.", 
                "Welcome!", JOptionPane.YES_NO_OPTION, JOptionPane.INFORMATION_MESSAGE, welcomeIcon, options, options[0]);

        //if user selects browse option, do this:
        if (getFile == JOptionPane.YES_OPTION) {
            //asks for image file as input
            browse();
        }

        //otherwise, exit program
        else {
            //exit program
            System.exit(0); 
        }
    }

    //method returns width of image
    public int width() {
        int width = image.getWidth();
        return width;
    }

    //method returns height of image
    public int height() {
        int height = image.getHeight();
        return height;
    }

    //method sets updated image as "original" image
    public void setImage() {
        this.image = image2;
    }

    //method writes image in destination
    public void saveImage() {
        //gets file name & destination from user through JFileChooser
        fileChooser.setDialogTitle("Save As...");
        fileChooser.showSaveDialog(frame);

        //writes image to new file with given name & location
        try {
            ImageIO.write(this.image, "JPG", fileChooser.getSelectedFile());
        }
        catch (IOException f) {
            System.out.println("Saving failed! Could not save image.");
        }
    }

    //method browses for new file
    public void browse() {
        //asks for new image file
        fileChooser.setDialogTitle("Choose an image file:");
        fileChooser.showOpenDialog(frame);
        File selectedFile = fileChooser.getSelectedFile();

        //if user has selected image file, continue
        if (fileChooser.getSelectedFile() != null) {
            try {
                //reads selectedFile as image
                image = ImageIO.read(selectedFile);
            } 
            catch (IOException e) {
                System.out.println("Invalid image file: " + selectedFile);
                System.exit(0);
            }
        }

        //else print error message
        else {
            System.out.println("Error! No File Selected.");
        }
    }

    //method creates frame, adds menubar with options, provides parameters for other methods
    public void show() {
        //set frame title, set it visible, etc
        content = frame.getContentPane();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setResizable(false);

        //add the image to the frame
        ImageIcon icon = new ImageIcon(image);
        imageLabel = new JLabel(icon);
        frame.setContentPane(imageLabel);

        //adds a menubar on the frame with program name, File & Edit menus
        JMenuBar menuBar = new JMenuBar();
        frame.setJMenuBar(menuBar);
        JMenu progName = new JMenu("ImageEdit");
        progName.setBackground(Color.RED);
        menuBar.add(progName);
        JMenu fileMenu = new JMenu("File");
        menuBar.add(fileMenu);
        JMenu editMenu = new JMenu("Edit");
        menuBar.add(editMenu);

        //adds options to JMenus
        //option to exit application
        ImageIcon exitIcon = new ImageIcon("GUI-images/app-exit.png");
        JMenuItem exitAction = new JMenuItem("Exit", exitIcon);
        progName.add(exitAction);

        //if exit option is selected, do this:
        exitAction.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //prompts to save file before exiting
                    ImageIcon saveIcon = new ImageIcon("GUI-images/save-icon.png");
                    int askSave = JOptionPane.showConfirmDialog(null,"Save image before exit?", "Save...", 
                            JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
                    if (askSave == JOptionPane.YES_OPTION) {
                        //opens save image method, then exits
                        saveImage();
                        System.exit(0);
                    }
                    else {
                        //exits without saving
                        System.exit(0);
                    }
                }
            });

        //option to open a new image
        ImageIcon newIcon = new ImageIcon("GUI-images/new-image.png");
        JMenuItem newAction = new JMenuItem("Open Image", newIcon);
        fileMenu.add(newAction);

        //if new option is selected, do this:
        newAction.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //prompts to save image before opening new image
                    ImageIcon saveIcon = new ImageIcon("GUI-images/save-icon.png");
                    int askSave = JOptionPane.showConfirmDialog(null,"Save current image?", "Save...", 
                            JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, saveIcon);
                    //if they do want to save first, do this:
                    if (askSave == JOptionPane.YES_OPTION) {
                        //opens save image method, then asks asks for new image file
                        saveImage();

                        //clears old image
                        imageLabel.setIcon(null);

                        //browses for new image
                        browse();
                        //displays new image
                        imageLabel.setIcon(new ImageIcon(image));

                        //resizes canvas to fit new image
                        frame.setSize(width(), height());
                    }
                    //if they don't want to save, do this:
                    else {
                        //erases old image
                        imageLabel.setIcon(null);

                        //browses for new image
                        browse();

                        //displays new image
                        imageLabel.setIcon(new ImageIcon(image));

                        //resizes canvas to fit new image
                        frame.setSize(width(), height());
                    }
                }
            });

        //option to save current image
        ImageIcon saveIcon = new ImageIcon("GUI-images/save-image.png");
        JMenuItem saveAction = new JMenuItem("Save Image As...", saveIcon);
        fileMenu.add(saveAction);

        //if save option is selected, do this:
        saveAction.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //opens save image method
                    saveImage();
                }
            });

        //option to make current image grayscale
        ImageIcon gsIcon = new ImageIcon("GUI-images/grayscale-image.png");
        JMenuItem grayScale = new JMenuItem("Grayscale", gsIcon);
        editMenu.add(grayScale);

        //if grayscale option is selected, do this:
        grayScale.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //grabs height and width of image,
                    //then calls grayscale method
                    grayscale(width(), height());
                }
            });

        //option to scale current window to new dimensions
        ImageIcon scaleIcon = new ImageIcon("GUI-images/scale-image.png");
        JMenuItem scaleImg = new JMenuItem("Scale Image", scaleIcon);
        editMenu.add(scaleImg);

        //if scale option is selected, do this:
        scaleImg.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //asks for height and width to create new image
                    ImageIcon widthIcon = new ImageIcon("GUI-images/LR-arrows.png");
                    String scaleWidth = (String)JOptionPane.showInputDialog(null,"What should the new width be?", 
                            "Scale Image", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);
                    ImageIcon heightIcon = new ImageIcon("GUI-images/UD-arrows.png");
                    String scaleHeight = (String)JOptionPane.showInputDialog(null,"What should the new height be?", 
                            "Scale Image", JOptionPane.QUESTION_MESSAGE, widthIcon, null, null);

                    //turns user input strings into doubles
                    double x = Double.parseDouble(scaleWidth);
                    double y = Double.parseDouble(scaleHeight);

                    //casts doubles as ints
                    int newWidth = (int)x;
                    int newHeight = (int)y;

                    //resizes frame to fit new image dimensions
                    frame.setSize(newWidth, newHeight);

                    //calls scale method to resize image using given dimensions
                    scale(newWidth, newHeight);
                }
            });

        //option to merge two images together
        ImageIcon mergeIcon = new ImageIcon("GUI-images/merge-image.png");
        JMenuItem mergeImg = new JMenuItem("Merge Image", mergeIcon);
        editMenu.add(mergeImg);

        //if merge option is selected, do this:
        mergeImg.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    //asks for image file as input
                    fileChooser.setDialogTitle("Choose an image file to merge current image with.");
                    fileChooser.showOpenDialog(frame);
                    File mergeFile = fileChooser.getSelectedFile();

                    //if user has selected image file, continue
                    if (fileChooser.getSelectedFile() != null) {
                        try {
                            //reads selectedFile as image
                            mergeImage = ImageIO.read(mergeFile);
                        } 
                        catch (IOException f) {
                            System.out.println("Invalid image file: " + mergeFile);
                            System.exit(0);
                        }
                    }

                    //else print error message
                    else {
                        System.out.println("Error! No File Selected.");
                    }

                    //if two images are same size, merge them
                    if (width() == mergeImage.getWidth() && height() == mergeImage.getHeight()) {
                        mergeImg(width(), height(), mergeImage);
                    }
                    //else, resize the second image to size of original, then merge
                    else {
                        scale(width(), height());
                        mergeImg(width(), height(), mergeImage);
                    }
                }
            });

        //option to rotate image by x degrees
        ImageIcon rotateIcon = new ImageIcon("GUI-images/rotate-image.png");
        JMenuItem rotateImage = new JMenuItem("Rotate Image", rotateIcon);
        editMenu.add(rotateImage);

        //if rotate option is selected, do this:
        rotateImage.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    String rotateAngle = (String)JOptionPane.showInputDialog(null,"By what angle would you like to rotate?", 
                            "Input Degrees", JOptionPane.QUESTION_MESSAGE, null/*icon goes here*/, null, null);

                    //turns user input strings into doubles
                    double angleDegs = Double.parseDouble(rotateAngle);

                    //converts degrees to rads
                    double angle = Math.toRadians(angleDegs);

                    //applies sine and cosine functions
                    int sin = (int)Math.sin(angle);
                    int cos = (int)Math.cos(angle);

                    //gets new width of rotated image
                    int newWidth = width()*sin + height()*cos;
                    int newHeight = height()*sin + width()*cos;

                    //sets frame to new image size
                    frame.setSize(newWidth, newHeight);

                    //calls rotate method to rotate image
                    rotate(newWidth, newHeight, angle);
                }
            });

        //paint the frame
        frame.pack();
        frame.repaint();
        frame.setVisible(true);
    }

    //method converts image to grayscale; 6 lines of code
    public void grayscale(int width, int height) {
        // create a grayscale image with original dimensions
        image2 = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY);

        // convert colored image to grayscale
        ColorConvertOp grayScale = new ColorConvertOp(image.getColorModel().getColorSpace(),
                image2.getColorModel().getColorSpace(),null);
        grayScale.filter(image,image2);
        imageLabel.setIcon(new ImageIcon(image2));

        //sets new image as "original"
        setImage();
    }

    //method scales image to user-input dimensions; 5 lines of code
    public void scale(int width, int height){
        //uses user-input dimensions to create new image
        image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        Graphics g = image2.createGraphics();

        //gets new dimensions and resizes image
        g.drawImage(image, 0, 0, image2.getWidth(), image2.getHeight(), 0, 0, width(), height(), null);  
        imageLabel.setIcon(new ImageIcon(image2));

        //sets new image as "original"
        setImage();
    }

    //method merges two images together; 14 lines of code
    public void mergeImg(int width, int height, BufferedImage mergeImage) {
        //creates new image from two images of same size
        BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                //get color from original image
                Color c = new Color(image.getRGB(i, j));

                //get colors from merge image
                Color c2 = new Color(mergeImage.getRGB(i, j));

                //average the colors
                int r = (c.getRed()+c2.getRed())/2;
                int g = (c.getGreen()+c2.getGreen())/2;
                int b = (c.getBlue()+c2.getBlue())/2;
                Color avgColor = new Color(r, g, b);

                //set colors of new image to average of the two images
                image2.setRGB(i, j, avgColor.getRGB());
                imageLabel.setIcon(new ImageIcon(image2));
            }
        }

        mergeImage = null;
        //sets new image as "original"
        setImage();
    }

    //method rotates image by user-input angle; 18 lines of code
    public void rotate(int width, int height, double angle) {
        //rotates image around center point
        BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        //defines sin and cos functions
        double sin = Math.sin(angle);
        double cos = Math.cos(angle);

        //gets coordinates of image center
        double Xc = width/2;
        double Yc = height/2;

        //rotate
        for (int i = 0; i < width; i++) {
            for (int j = 0; j < height; j++) {
                //new i,j at center of image
                double iPrime = i - Xc;
                double jPrime = j - Yc;
                //i,j at new points after rotation
                int xPrime = (int) (iPrime * cos - jPrime * sin + Xc);
                int yPrime = (int) (iPrime * sin + jPrime * cos + Yc);

                // plot pixel (i, j) the same color as (xPrime, yPrime) if it's in bounds
                if (xPrime >= 0 && xPrime < width && yPrime >= 0 && yPrime < height) {
                    image2.setRGB(xPrime, yPrime, image.getRGB(i, j));
                    imageLabel.setIcon(new ImageIcon(image2));
                }
            }
        }

        //sets new image as "original"
        setImage();
    }

    //main method; starts program
    public static void main(String[] args) {
        //creates new picture from image file
        Picture p = new Picture();

        //shows picture on JFrame
        p.show();
    }
}

Any ideas what could be up? Appreciate the help!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

美男兮 2024-12-17 03:19:38

从堆栈跟踪和代码来看,该方法似乎

//method returns width of image
public int width() {
    int width = image.getWidth();
    return width;
}

抛出了 NullPointerException。唯一可能导致此问题的情况是 imagenull

我建议您逐步检查有问题的方法,并检查将 null 分配给 image 变量的位置和原因。


一个可能的问题是您在方法 rotatemergeImg 中重新声明了 image2

BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

这有效地“隐藏”了 this.image2。当您稍后调用 setImage 并执行

this.image = image2;

image2 时,不会引用您准备好的局部变量。

Judging from the stack trace and the code, it seems like this method

//method returns width of image
public int width() {
    int width = image.getWidth();
    return width;
}

throws a NullPointerException. The only thing that can cause this is if image is null.

I suggest you step through your problematic methods and check where and why null is assigned to the image variable.


One possible problem is that you redeclare image2 in method rotate and mergeImg.

BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

This effectively "hides" this.image2. When you later call setImage and do

this.image = image2;

image2 doesn't refer to the local variable which you have prepared.

自由如风 2024-12-17 03:19:38

从堆栈跟踪来看,您的实例变量 image 似乎为空。

    public int width() {
      int width = image.getWidth();
      return width;
    }

尝试添加:

public int width() {
    int width = 0;
    if (null != image) {
        width = image.getWidth();
    }
    return width;
}

编辑:正如有人已经评论的那样,您不应该使用这么多实例变量。没有参数的 setImage() 应该会敲响警钟;-)。我会向此方法添加一个图像参数,这样您就一定会使用您刚刚使用过的内容来更新您的图像实例变量!

就像

public void setImage(BufferedImage workingImg)

依靠许多类方法修改的不同实例变量的状态是获得不可预测结果的最佳方式一样。

祝你好运

From the stacktrace, you instance variable image seems to be null.

    public int width() {
      int width = image.getWidth();
      return width;
    }

try to add :

public int width() {
    int width = 0;
    if (null != image) {
        width = image.getWidth();
    }
    return width;
}

EDIT : as someone already commented, you should not use so many instance varibale. having a setImage() with no param should ring a bell ;-). i would add a image parameter to this method so you will be sure to update your image instance variable with something you just worked with!

like

public void setImage(BufferedImage workingImg)

Relying on the state of different instance variables modified by many class method is the best way to have unpredictable results.

Good luck

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文