Reputation: 1574
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
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
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
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.
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
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