- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个图像编辑程序。它有多种方法,如灰度、缩放、合并图像等。每种方法都可以完美地独立工作。但是,在调用 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();
}
}
有什么想法吗?感谢您的帮助!
最佳答案
从堆栈轨迹和代码来看,好像是这个方法
//method returns width of image
public int width() {
int width = image.getWidth();
return width;
}
抛出一个 NullPointerException
。如果 image
为 null
,唯一会导致这种情况。
我建议您逐步检查有问题的方法,并检查将 null
分配给 image
变量的位置和原因。
一个可能的问题是您在方法 rotate
和 mergeImg
中重新声明了 image2
。
BufferedImage image2 = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
这有效地“隐藏”了 this.image2
。当您稍后调用 setImage
并执行
this.image = image2;
image2
没有引用您准备的局部变量。
关于java - 在调用另一个方法后调用方法时出现空指针异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7798406/
我想了解 Ruby 方法 methods() 是如何工作的。 我尝试使用“ruby 方法”在 Google 上搜索,但这不是我需要的。 我也看过 ruby-doc.org,但我没有找到这种方法。
Test 方法 对指定的字符串执行一个正则表达式搜索,并返回一个 Boolean 值指示是否找到匹配的模式。 object.Test(string) 参数 object 必选项。总是一个
Replace 方法 替换在正则表达式查找中找到的文本。 object.Replace(string1, string2) 参数 object 必选项。总是一个 RegExp 对象的名称。
Raise 方法 生成运行时错误 object.Raise(number, source, description, helpfile, helpcontext) 参数 object 应为
Execute 方法 对指定的字符串执行正则表达式搜索。 object.Execute(string) 参数 object 必选项。总是一个 RegExp 对象的名称。 string
Clear 方法 清除 Err 对象的所有属性设置。 object.Clear object 应为 Err 对象的名称。 说明 在错误处理后,使用 Clear 显式地清除 Err 对象。此
CopyFile 方法 将一个或多个文件从某位置复制到另一位置。 object.CopyFile source, destination[, overwrite] 参数 object 必选
Copy 方法 将指定的文件或文件夹从某位置复制到另一位置。 object.Copy destination[, overwrite] 参数 object 必选项。应为 File 或 F
Close 方法 关闭打开的 TextStream 文件。 object.Close object 应为 TextStream 对象的名称。 说明 下面例子举例说明如何使用 Close 方
BuildPath 方法 向现有路径后添加名称。 object.BuildPath(path, name) 参数 object 必选项。应为 FileSystemObject 对象的名称
GetFolder 方法 返回与指定的路径中某文件夹相应的 Folder 对象。 object.GetFolder(folderspec) 参数 object 必选项。应为 FileSy
GetFileName 方法 返回指定路径(不是指定驱动器路径部分)的最后一个文件或文件夹。 object.GetFileName(pathspec) 参数 object 必选项。应为
GetFile 方法 返回与指定路径中某文件相应的 File 对象。 object.GetFile(filespec) 参数 object 必选项。应为 FileSystemObject
GetExtensionName 方法 返回字符串,该字符串包含路径最后一个组成部分的扩展名。 object.GetExtensionName(path) 参数 object 必选项。应
GetDriveName 方法 返回包含指定路径中驱动器名的字符串。 object.GetDriveName(path) 参数 object 必选项。应为 FileSystemObjec
GetDrive 方法 返回与指定的路径中驱动器相对应的 Drive 对象。 object.GetDrive drivespec 参数 object 必选项。应为 FileSystemO
GetBaseName 方法 返回字符串,其中包含文件的基本名 (不带扩展名), 或者提供的路径说明中的文件夹。 object.GetBaseName(path) 参数 object 必
GetAbsolutePathName 方法 从提供的指定路径中返回完整且含义明确的路径。 object.GetAbsolutePathName(pathspec) 参数 object
FolderExists 方法 如果指定的文件夹存在,则返回 True;否则返回 False。 object.FolderExists(folderspec) 参数 object 必选项
FileExists 方法 如果指定的文件存在返回 True;否则返回 False。 object.FileExists(filespec) 参数 object 必选项。应为 FileS
我是一名优秀的程序员,十分优秀!