如何制作Javafx图像裁剪应用程序
发布时间:2020-12-15 05:13:07 所属栏目:Java 来源:网络整理
导读:我正在为同事构建一个应用程序来裁剪图像. 我在场景生成器中使用F XML来构建GUI.用户单击按钮从他的计算机中选择图像.然后,图像显示在GUI中.用户可以在窗格中缩放和移动.最后,单击一个按钮将编辑后的图像保存到他的计算机上.但是,我真的不知道应该使用哪个库
我正在为同事构建一个应用程序来裁剪图像.
我在场景生成器中使用F XML来构建GUI.用户单击按钮从他的计算机中选择图像.然后,图像显示在GUI中.用户可以在窗格中缩放和移动.最后,单击一个按钮将编辑后的图像保存到他的计算机上.但是,我真的不知道应该使用哪个库来构建应用程序.这是我第一次处理图形.我不知道如何阅读图像,裁剪图像和写图像. Javafx Canvas for Pane?除了java doc之外还有什么好的资源可以学习如何做到这一点? 解决方法
您的问题太多,无法在StackOverflow上得到解答.我建议你先阅读
official Oracle documentation about JavaFX.
但是,由于这是一个有趣的话题,这里是代码中的答案. 您需要考虑以下几点: >使用ImageView作为容器 这就是它.在下面的示例中,使用鼠标左键进行选择,使用鼠标右键选择裁剪上下文菜单,然后在选择边界处获取ImageView节点的快照,然后将图像保存到文件中. import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javafx.application.Application; import javafx.embed.swing.SwingFXUtils; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Bounds; import javafx.geometry.Rectangle2D; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.SnapshotParameters; import javafx.scene.control.ContextMenu; import javafx.scene.control.MenuItem; import javafx.scene.control.ScrollPane; import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.image.WritableImage; import javafx.scene.input.MouseEvent; import javafx.scene.layout.BorderPane; import javafx.scene.paint.Color; import javafx.scene.shape.Rectangle; import javafx.scene.shape.StrokeLineCap; import javafx.stage.FileChooser; import javafx.stage.Stage; import javax.imageio.ImageIO; /** * Load image,provide rectangle for rubberband selection. Press right mouse button for "crop" context menu which then crops the image at the selection rectangle and saves it as jpg. */ public class ImageCropWithRubberBand extends Application { RubberBandSelection rubberBandSelection; ImageView imageView; Stage primaryStage; public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { this.primaryStage = primaryStage; primaryStage.setTitle("Image Crop"); BorderPane root = new BorderPane(); // container for image layers ScrollPane scrollPane = new ScrollPane(); // image layer: a group of images Group imageLayer = new Group(); // load the image // Image image = new Image( getClass().getResource( "cat.jpg").toExternalForm()); Image image = new Image("https://upload.wikimedia.org/wikipedia/commons/thumb/1/14/Gatto_europeo4.jpg/1024px-Gatto_europeo4.jpg"); // the container for the image as a javafx node imageView = new ImageView( image); // add image to layer imageLayer.getChildren().add( imageView); // use scrollpane for image view in case the image is large scrollPane.setContent(imageLayer); // put scrollpane in scene root.setCenter(scrollPane); // rubberband selection rubberBandSelection = new RubberBandSelection(imageLayer); // create context menu and menu items ContextMenu contextMenu = new ContextMenu(); MenuItem cropMenuItem = new MenuItem("Crop"); cropMenuItem.setOnAction(new EventHandler<ActionEvent>() { public void handle(ActionEvent e) { // get bounds for image crop Bounds selectionBounds = rubberBandSelection.getBounds(); // show bounds info System.out.println( "Selected area: " + selectionBounds); // crop the image crop( selectionBounds); } }); contextMenu.getItems().add( cropMenuItem); // set context menu on image layer imageLayer.setOnMousePressed(new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if (event.isSecondaryButtonDown()) { contextMenu.show(imageLayer,event.getScreenX(),event.getScreenY()); } } }); primaryStage.setScene(new Scene(root,1024,768)); primaryStage.show(); } private void crop( Bounds bounds) { FileChooser fileChooser = new FileChooser(); fileChooser.setTitle("Save Image"); File file = fileChooser.showSaveDialog( primaryStage); if (file == null) return; int width = (int) bounds.getWidth(); int height = (int) bounds.getHeight(); SnapshotParameters parameters = new SnapshotParameters(); parameters.setFill(Color.TRANSPARENT); parameters.setViewport(new Rectangle2D( bounds.getMinX(),bounds.getMinY(),width,height)); WritableImage wi = new WritableImage( width,height); imageView.snapshot(parameters,wi); // save image // !!! has bug because of transparency (use approach below) !!! // -------------------------------- // try { // ImageIO.write(SwingFXUtils.fromFXImage( wi,null),"jpg",file); // } catch (IOException e) { // e.printStackTrace(); // } // save image (without alpha) // -------------------------------- BufferedImage bufImageARGB = SwingFXUtils.fromFXImage(wi,null); BufferedImage bufImageRGB = new BufferedImage(bufImageARGB.getWidth(),bufImageARGB.getHeight(),BufferedImage.OPAQUE); Graphics2D graphics = bufImageRGB.createGraphics(); graphics.drawImage(bufImageARGB,null); try { ImageIO.write(bufImageRGB,file); System.out.println( "Image saved to " + file.getAbsolutePath()); } catch (IOException e) { e.printStackTrace(); } graphics.dispose(); } /** * Drag rectangle with mouse cursor in order to get selection bounds */ public static class RubberBandSelection { final DragContext dragContext = new DragContext(); Rectangle rect = new Rectangle(); Group group; public Bounds getBounds() { return rect.getBoundsInParent(); } public RubberBandSelection( Group group) { this.group = group; rect = new Rectangle( 0,0); rect.setStroke(Color.BLUE); rect.setStrokeWidth(1); rect.setStrokeLineCap(StrokeLineCap.ROUND); rect.setFill(Color.LIGHTBLUE.deriveColor(0,1.2,1,0.6)); group.addEventHandler(MouseEvent.MOUSE_PRESSED,onMousePressedEventHandler); group.addEventHandler(MouseEvent.MOUSE_DRAGGED,onMouseDraggedEventHandler); group.addEventHandler(MouseEvent.MOUSE_RELEASED,onMouseReleasedEventHandler); } EventHandler<MouseEvent> onMousePressedEventHandler = new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if( event.isSecondaryButtonDown()) return; // remove old rect rect.setX(0); rect.setY(0); rect.setWidth(0); rect.setHeight(0); group.getChildren().remove( rect); // prepare new drag operation dragContext.mouseAnchorX = event.getX(); dragContext.mouseAnchorY = event.getY(); rect.setX(dragContext.mouseAnchorX); rect.setY(dragContext.mouseAnchorY); rect.setWidth(0); rect.setHeight(0); group.getChildren().add( rect); } }; EventHandler<MouseEvent> onMouseDraggedEventHandler = new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if( event.isSecondaryButtonDown()) return; double offsetX = event.getX() - dragContext.mouseAnchorX; double offsetY = event.getY() - dragContext.mouseAnchorY; if( offsetX > 0) rect.setWidth( offsetX); else { rect.setX(event.getX()); rect.setWidth(dragContext.mouseAnchorX - rect.getX()); } if( offsetY > 0) { rect.setHeight( offsetY); } else { rect.setY(event.getY()); rect.setHeight(dragContext.mouseAnchorY - rect.getY()); } } }; EventHandler<MouseEvent> onMouseReleasedEventHandler = new EventHandler<MouseEvent>() { @Override public void handle(MouseEvent event) { if( event.isSecondaryButtonDown()) return; // remove rectangle // note: we want to keep the ruuberband selection for the cropping => code is just commented out /* rect.setX(0); rect.setY(0); rect.setWidth(0); rect.setHeight(0); group.getChildren().remove( rect); */ } }; private static final class DragContext { public double mouseAnchorX; public double mouseAnchorY; } } } 截图: 裁剪后的图片: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |