第一页 第二页 第三页
主窗口的背景像素不是捕获的图像的一部分;就不可能把它们包含在修剪的图片内。因此,无论何时把背景像素包含在修剪区域内,操作都会失败,并且会给出一个“Out of bounds”错误信息。
修剪操作由ImageArea的public Boolean crop()方法处理。如果完成了修剪或者没有选择子图像(当没有选中内容时调用这个方法是非常方便的)该方法(如下所示)返回true。如果在选择区域中包含了背景像素则返回false。
public boolean crop () { // There is nothing to crop if the selection rectangle is only a single // point. if (srcx == destx && srcy == desty) return true; // Assume success. boolean succeeded = true; // Compute upper-left and lower-right coordinates for selection rectangle // corners. int x1 = (srcx < destx) ? srcx : destx; int y1 = (srcy < desty) ? srcy : desty; int x2 = (srcx > destx) ? srcx : destx; int y2 = (srcy > desty) ? srcy : desty; // Compute width and height of selection rectangle. int width = (x2-x1)+1; int height = (y2-y1)+1; // Create a buffer to hold cropped image. BufferedImage biCrop = new BufferedImage (width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = biCrop.createGraphics (); // Perform the crop operation. try { BufferedImage bi = (BufferedImage) image; BufferedImage bi2 = bi.getSubimage (x1, y1, width, height); g2d.drawImage (bi2, null, 0, 0); } catch (RasterFormatException e) { succeeded = false; } g2d.dispose (); if (succeeded) setImage (biCrop); // Implicitly remove selection rectangle. else { // Prepare to remove selection rectangle. srcx = destx; srcy = desty; // Explicitly remove selection rectangle. repaint (); } return succeeded; }
crop()方法调用BufferedImage的public BufferedImage
getSubimage(int x, int y, int w, int
h)方法摘取选择区域内的子图像。如果该方法的参数没有指定BufferedImage内的图像,它就会抛出一个
java.awt.image.RasterFormatException,因此就会返回false。
图像保存
Capture允许你把捕获的图像保存为一个jpeg文件。你通过一个保存文件选择器指定文件名,选择器由Capture类的构造函数创建:
// Construct a save file-chooser. Initialize the starting directory to // the current directory, do not allow the user to select the "all files" // filter, and restrict the files that can be selected to those ending // with .jpg or .jpeg extensions. final JFileChooser fcSave = new JFileChooser (); fcSave.setCurrentDirectory (new File (System.getProperty ("user.dir"))); fcSave.setAcceptAllFileFilterUsed (false); fcSave.setFileFilter (new ImageFileFilter ());
为了限制文件选择器的选择是文件夹或者是以.jpg或.jpeg为后缀的文件,就使用了ImageFileFilter类的一个实例作为保存时文件选择器的文件过滤器。该方法对于任何非文件夹和后缀名非.jpg/.jpeg的文件都返回false:
public boolean accept (File f) { // Allow the user to select directories so that the user can navigate the // file system. if (f.isDirectory ()) return true; // Allow the user to select files ending with a .jpg or a .jpeg // extension. String s = f.getName (); int i = s.lastIndexOf ('.'); if (i > 0 && i < s.length ()-1) { String ext = s.substring (i+1).toLowerCase (); if (ext.equals ("jpg") || ext.equals ("jpeg")) return true; } // Nothing else can be selected. return false; }
当你选择了Save As…菜单项时,它的监听器就会显示一个保存文件选择器。假定你没有退出选择器,监听器就会确保你选择的文件名是以.jpg或.jpeg为后缀名。继续,监听器会确定文件是否存在,这样你就不会无意中覆盖一个存在的文件。
// Present the "save" file-chooser without any file selected. // If the user cancels this file-chooser, exit this method. fcSave.setSelectedFile (null); if (fcSave.showSaveDialog (Capture.this) != JFileChooser.APPROVE_OPTION) return; // Obtain the selected file. Validate its extension, which // must be .jpg or .jpeg. If extension not present, append // .jpg extension. File file = fcSave.getSelectedFile (); String path = file.getAbsolutePath ().toLowerCase (); if (!path.endsWith (".jpg") && !path.endsWith (".jpeg")) file = new File (path += ".jpg"); // If the file exists, inform the user, who might not want // to accidentally overwrite an existing file. Exit method // if the user specifies that it is not okay to overwrite // the file. if (file.exists ()) { int choice = JOptionPane. showConfirmDialog (null, "Overwrite file?", "Capture", JOptionPane. YES_NO_OPTION); if (choice == JOptionPane.NO_OPTION) return; }