nullpointerexception при вызове метода после вызова другого метода? - PullRequest
1 голос
/ 17 октября 2011

У меня есть программа для редактирования изображений.Он имеет несколько методов, таких как оттенки серого, масштабирование, объединение изображений и т. Д. Каждый метод отлично работает сам по себе.Тем не менее я получаю сообщение об ошибке при вызове метода grayScale после вызова метода mergeImg.Это не произойдет, если я сначала применю оттенки серого.

Вот ошибка:

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();
    }
}

Любые идеи, которые могли быбыть на ногах?Ценю помощь!

Ответы [ 2 ]

5 голосов
/ 17 октября 2011

Судя по трассировке стека и коду, похоже, что этот метод

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

бросает NullPointerException. Единственное, что может вызвать это, если image это null.

Я предлагаю вам пройтись по вашим проблемным методам и проверить, где и почему null присваивается переменной image.


Одной из возможных проблем является переопределение image2 в методе rotate и mergeImg.

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

Это эффективно "скрывает" this.image2. Когда вы позже позвоните setImage и сделаете

this.image = image2;

image2 не относится к локальной переменной, которую вы подготовили.

2 голосов
/ 17 октября 2011

Из стека трассировки ваше переменное изображение экземпляра кажется пустым.

    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)

Опираясь на состояние другого экземплярапеременные, модифицированные методом многих классов, - лучший способ получить непредсказуемые результаты.

Удачи

...