java - 您好,我创建了一个 javafx 应用程序,其中特定图像应裁剪为特定大小

标签 java image

在javafx中,我需要一个从给定图像中剪切某些内容的类,例如图像必须以类似于上传Facebook个人资料图片的方式裁剪为1500x1000px和800x600,以便您可以自由地从中拖动图片要切割的部分

最佳答案

您可以使用鼠标拖动事件来设置 ImageView 上的viewPort, ImageView 中的viewPort告诉ImageView使用2D矩形来渲染图像的哪一部分。

在此示例中,我创建了一个类(将其命名为 ImageCropper),它将在构造函数中接收目标尺寸,以创建一个 ImageView 来表示裁剪后的图像,并处理鼠标事件以重新定位 viewPort(背景图像)和边框是为了视觉美化,是可选的)

enter image description here

import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.scene.effect.ColorAdjust;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.StrokeType;

public class ImageCropper extends StackPane {
    private double initX, initY;
    private double initOffX, initOffY;
    private double offX, offY;

    private ImageView view;

    public ImageCropper(Image image, double targetWidth, double targetHeight) {
        setMaxSize(targetWidth, targetHeight);
        setMinSize(targetWidth, targetHeight);
        setAlignment(Pos.TOP_LEFT);

        Rectangle border = new Rectangle(targetWidth, targetHeight);
        border.setFill(Color.TRANSPARENT);
        border.setStrokeWidth(6);
        border.setStroke(Color.BLACK);
        border.setStrokeType(StrokeType.INSIDE);
        border.setStrokeDashOffset(20);
        border.getStrokeDashArray().setAll(40.0, targetHeight - 40, 40.0, targetWidth - 40);
        border.setMouseTransparent(true);

        ImageView backgroundImageView = new ImageView(image);
        ColorAdjust effect = new ColorAdjust();
        effect.setBrightness(-.5);
        backgroundImageView.setEffect(effect);

        view = new ImageView(image);
        view.setFitWidth(targetWidth);
        view.setFitHeight(targetHeight);

        offX = image.getWidth() / 2 - (targetWidth / 2);
        offY = image.getHeight() / 2 - (targetHeight / 2);
        view.setViewport(new Rectangle2D(offX, offY, targetWidth, targetHeight));

        backgroundImageView.setTranslateX(-offX);
        backgroundImageView.setTranslateY(-offY);

        view.setOnMousePressed(e -> {
            initX = e.getSceneX();
            initY = e.getSceneY();
            initOffX = offX;
            initOffY = offY;
        });

        view.setOnMouseDragged(e -> {
            offX = Math.min(image.getWidth() - targetWidth, Math.max(0, initOffX + (initX - e.getSceneX())));
            offY = Math.min(image.getHeight() - targetHeight, Math.max(0, initOffY + (initY - e.getSceneY())));

            view.setViewport(new Rectangle2D(offX, offY, targetWidth, targetHeight));

            backgroundImageView.setTranslateX(-offX);
            backgroundImageView.setTranslateY(-offY);
        });

        getChildren().addAll(backgroundImageView, view, border);
    }

    public Image getCroppedImage() {
        return view.snapshot(null, null);
    }
}
<小时/>

在您的应用中使用它需要使用图像和要裁剪的目标尺寸调用构造函数

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class Test extends Application {

    @Override
    public void start(Stage ps) {
        VBox root = new VBox(20);
        root.setAlignment(Pos.CENTER);
        root.setPadding(new Insets(20));

        Image image = new Image(Test.class.getClassLoader().getResourceAsStream("test.png"));
        ImageCropper cropper = new ImageCropper(image, 800, 600);

        Button crop = new Button("Crop");

        crop.setOnAction(e-> {
            Stage disp = new Stage();

            disp.setScene(new Scene(new StackPane(new ImageView(cropper.getCroppedImage()))));

            disp.show();
        });

        root.getChildren().setAll(cropper, crop);

        ps.setScene(new Scene(root));
        ps.show();
    }
}

(注1:我不知道是否有更好的方法来获取裁剪后的图像,在这个例子中,我正在拍摄 ImageView 的快照,它工作得很好,但我觉得这样做不舒服,如果你了解更好的方法)

(注 2:如果传递给 ImageCropper 的图像小于目标尺寸,则此方法可能会失败,修复此问题需要在保留其比例的同时缩小目标尺寸,或者将图像放大为大于目标尺寸)

关于java - 您好,我创建了一个 javafx 应用程序,其中特定图像应裁剪为特定大小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62289085/

相关文章:

java - 用于 ASCII 符号的 Hibernate @Pattern 正则表达式 validator

java - jar 文件和图像有问题

javascript - 使用 JavaScript 在新窗口中预览上传的图像

html - 6 张图像居中,但 3 张相邻

java - CDI 是否适用于常规 Java 应用程序?

java - 有没有办法在类型删除后查看我的代码的样子?

html - 垂直图像大于父 div

image - 尝试在空对象引用上调用接口(interface)方法 java.lang.String com.facebook.react.bridge.ReadableMap 等

java - 读取最后一个控制台输出并将其保存到变量/字符串中

java - 如何在运行时从类类型实例化一个类?