JavaFX: Deformation with offscreen image

As stated in my last article, I tried to render the writing part off screen to create an image off of it and then deform that.

That’s what I did with this result:

JavaFX_twolines_offscreenimageTurn’s out that this is almost the same result as when applying the lines to a group with a transparent background and then transform it:

 

 

 

 

JavaFX_two_line_deformed

However for completeness sake here is the code for the off screen example. It seams that the margins at the left and top look a bit better:

package ch.sahits.javafx.test.stretch;

import ch.sahits.javafx.test.ResizeableCanvas;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.LabelBuilder;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.effect.PerspectiveTransformBuilder;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.image.WritableImage;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.stage.Stage;

public class OffScreenImageGeneration extends Application {

    @Override
    public void start(Stage primaryStage) {
        try {
            Group root = new Group();
            Image img = new Image(getClass().getResource("PaperScroll.png").openStream());
            final double width = img.getWidth();
            final double height = img.getHeight();
            Scene scene = new Scene(root, width, height);
            ImageView imageView = new ImageView(img);
            WritableImage image = createOffScreenImage();

            PerspectiveTransform perspectiveTransform = PerspectiveTransformBuilder.create()
                    .ulx(200).uly(0)
                    .urx(544).ury(19)
                    .llx(0).lly(403)
                    .lrx(559).lry(502)
                    .build();

            ImageView imageView2 = new ImageView(image);
            imageView2.setTranslateX(366);
            imageView2.setTranslateY(29);
            imageView2.setEffect(perspectiveTransform);

            root.getChildren().addAll(imageView, imageView2);     
            primaryStage.setTitle("Perspective Transform");
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (IOException ex) {
            Logger.getLogger(ResizeableCanvas.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }

    private WritableImage createOffScreenImage() {
        Group offScreenRoot = new Group();
        Scene offScreen = new Scene(offScreenRoot, 559, 502);
        RectangleBuilder rectBuilder = RectangleBuilder.create()
                .opacity(0.5)
                .fill(Color.RED)
                .width(559)
                .height(502);
        Rectangle untransformed = rectBuilder.build();
        Label line1 = LabelBuilder.create()
                .text("First Line")
                .style("-fx-font-size: 24px")
                .translateX(10)
                .translateY(20)
                //.effect(perspectiveTransform)
                .build();
        Label line2 = LabelBuilder.create()
                .text("Second Line")
                .style("-fx-font-size: 24px")
                .translateX(10)
                .translateY(50)
                //.effect(perspectiveTransform)
                .build();
        offScreenRoot.getChildren().addAll(untransformed, line1, line2);
        WritableImage image = new WritableImage((int)offScreen.getWidth(), (int)offScreen.getHeight());
        offScreen.snapshot(image);
        return image;
    }
}

All the heavy work is done by the createOffScreenImage method, where a second scene is created with a group of the exact measures of the rectangle to be deformed.

And here the other code:

package ch.sahits.javafx.test.stretch;

import ch.sahits.javafx.test.ResizeableCanvas;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.scene.Group;
import javafx.scene.GroupBuilder;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.control.LabelBuilder;
import javafx.scene.effect.PerspectiveTransform;
import javafx.scene.effect.PerspectiveTransformBuilder;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.shape.RectangleBuilder;
import javafx.stage.Stage;

public class PerpectiveTransformEffectTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        try {
            Group root = new Group();
            Image img = new Image(getClass().getResource("PaperScroll.png").openStream());
            final double width = img.getWidth();
            final double height = img.getHeight();
            Scene scene = new Scene(root, width, height);
            ImageView imageView = new ImageView(img);

            RectangleBuilder rectBuilder = RectangleBuilder.create()
                    .translateX(366)
                    .translateY(29)
                    .opacity(0.5)
                    .fill(Color.RED)
                    .width(559)
                    .height(502);

            PerspectiveTransform perspectiveTransform = PerspectiveTransformBuilder.create()
                    .ulx(200).uly(0)
                    .urx(544).ury(19)
                    .llx(0).lly(403)
                    .lrx(559).lry(502)
                    .build();

            Label line1 = LabelBuilder.create()
                    .text("First Line")
                    .style("-fx-font-size: 24px")
                    .translateX(20)
                    .translateY(40)
                    .build();

            Label line2 = LabelBuilder.create()
                    .text("Second Line")
                    .style("-fx-font-size: 24px")
                    .translateX(20)
                    .translateY(70)
                    .build();

            Rectangle transparent = rectBuilder.build();
            transparent.setOpacity(0);

            Group text = GroupBuilder.create()
                    .translateX(366)
                    .translateY(29)
                    .children(transparent, line1, line2)
                    .effect(perspectiveTransform)
                    .build();

            root.getChildren().addAll(imageView, text);     
            primaryStage.setTitle("Perspective Transform");
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch (IOException ex) {
            Logger.getLogger(ResizeableCanvas.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Which of the two are better is hard to say, however I would guess that the one with the off screen image would be better when thinking about scaling the scene.

Schreibe einen Kommentar