Eeliya
Eeliya

Reputation: 1574

How to draw image rotated on JavaFX Canvas?

I want to draw image on canvas rotated. with drawImage(image, 0, 0) I can draw image but how can I rotate that image for example 45 degrees and draw it, then draw another image with -50 degrees rotation on the same canvas?

graphicContext2D does not work for me because it rotate all canvas content.

Upvotes: 5

Views: 23126

Answers (4)

Thorsten
Thorsten

Reputation: 325

I was running into similar problems with ImageViews, after rotating and scaling an image it was not sized correctly by the layout managers of parent containers.

According to the ideas presented here I created an ImageCanvas that reflects the dimension of the rendered image whether it is rotated or scaled.

See https://github.com/treimers/JfxImageCanvas

Enjoy Thorsten

Upvotes: 0

Shantanu Chandra
Shantanu Chandra

Reputation: 87

The above issue can also be solved by creating different layers of canvas.

private void createLayers(){
        // Layers 1&2 are the same size
        layer1 = new Canvas(300,250);
        layer2 = new Canvas(300,250);

        // Obtain Graphics Contexts
        gc1 = layer1.getGraphicsContext2D();
        gc1.setFill(Color.GREEN);
        gc1.fillOval(50,50,20,20);
        gc1.getCanvas().setRotate(45);
        gc2 = layer2.getGraphicsContext2D();
        gc2.setFill(Color.BLUE);
        gc2.fillOval(100,100,20,20);
        gc.getCanvas().setRotate(135);
    }
        ...

 private void addLayers(){
        // Add Layers
        borderPane.setTop(cb);        
        Pane pane = new Pane();
        pane.getChildren().add(layer1);
        pane.getChildren().add(layer2);
        layer1.toFront();
        borderPane.setCenter(pane);    
        root.getChildren().add(borderPane);
    }

Upvotes: 3

jewelsea
jewelsea

Reputation: 159291

Here is a sample, following similar principles to Katona's answer, only difference is that it rotates images about arbitrary pivot points by applying a custom transform.

rotatedimages

import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.canvas.*;
import javafx.scene.image.Image;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.transform.Rotate;
import javafx.stage.Stage;

/** Rotates images round pivot points and places them in a canvas */
public class RotatedImageInCanvas extends Application {
    /**
     * Sets the transform for the GraphicsContext to rotate around a pivot point.
     *
     * @param gc the graphics context the transform to applied to.
     * @param angle the angle of rotation.
     * @param px the x pivot co-ordinate for the rotation (in canvas co-ordinates).
     * @param py the y pivot co-ordinate for the rotation (in canvas co-ordinates).
     */
    private void rotate(GraphicsContext gc, double angle, double px, double py) {
        Rotate r = new Rotate(angle, px, py);
        gc.setTransform(r.getMxx(), r.getMyx(), r.getMxy(), r.getMyy(), r.getTx(), r.getTy());
    }

    /**
     * Draws an image on a graphics context.
     *
     * The image is drawn at (tlpx, tlpy) rotated by angle pivoted around the point:
     *   (tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2)
     *
     * @param gc the graphics context the image is to be drawn on.
     * @param angle the angle of rotation.
     * @param tlpx the top left x co-ordinate where the image will be plotted (in canvas co-ordinates).
     * @param tlpy the top left y co-ordinate where the image will be plotted (in canvas co-ordinates).
     */
    private void drawRotatedImage(GraphicsContext gc, Image image, double angle, double tlpx, double tlpy) {
        gc.save(); // saves the current state on stack, including the current transform
        rotate(gc, angle, tlpx + image.getWidth() / 2, tlpy + image.getHeight() / 2);
        gc.drawImage(image, tlpx, tlpy);
        gc.restore(); // back to original state (before rotation)
    }

    @Override public void start(Stage stage) {
        Image image = new Image(
            "http://worldpress.org/images/maps/world_600w.jpg", 350, 0, true, true
        );

        // creates a canvas on which rotated images are rendered.
        Canvas canvas = new Canvas(600, 400);
        GraphicsContext gc = canvas.getGraphicsContext2D();

        drawRotatedImage(gc, image,  40,   0,   0);
        drawRotatedImage(gc, image, -50, 400, 200);

        // supplies a tiled background image on which the canvas is drawn.
        StackPane stack = new StackPane();
        stack.setMaxSize(canvas.getWidth(), canvas.getHeight());
        stack.setStyle("-fx-background-image: url('http://1.bp.blogspot.com/_wV5JMD1OISg/TDYTYxuxR4I/AAAAAAAAvSo/a0zT8nwPV8U/s400/louis-vuitton-nice-beautiful.jpg');");
        stack.getChildren().add(
                canvas
        );

        // places a resizable padded frame around the canvas.
        StackPane frame = new StackPane();
        frame.setPadding(new Insets(20));
        frame.getChildren().add(stack);

        stage.setScene(new Scene(frame, Color.BURLYWOOD));
        stage.show();
    }

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

Upvotes: 19

Katona
Katona

Reputation: 4901

Well I have never used JavaFX, but browsing it's API documentation, I came up with this solution (I have not actually tried it so it may be wrong):

Canvas canvas = ...
Image img = ...
GraphicsContext gc = canvas.getGraphicsContext2D();

gc.save(); // saves the current state on stack, including the current transform
gc.rotate(45);
gc.drawImage(img);
gc.restore(); // back to original state (before rotation)

gc.save();
gc.rotate(-50);
gc.drawImage(img);
gc.restore();

I don't know if it works here, but the idea (transformation stack) is borrowed from other drawing API (like OpenGL).

Upvotes: 4

Related Questions