2

I am playing with JavaFX and in the class start(Stage theStage) I have the following code:

/*... Scene, stage, canvas ...*/
GraphicsContext gc = canvas.getGraphicsContext2D();
Image imgage = new Image("gfx/image.png");
gc.drawImage(image, 256, 256);

How I draw it rotated without rotating the axis? I've found and tried this:

gc.save(); // saves the current state on stack, including the current transform
gc.rotate(45);
gc.drawImage(image);
gc.restore();

However it also transforms the axis and when I move image using changing position x & y .. it goes wrong, because it makes axis rotate too. I've been thinking about recalculating movement using sin and cos functions, but I am sure there is such an easier solution.

It may works with BufferedImage, but they draws it by using different Graphics class and I dont know how to make it work together.

EDIT: okey, how to rotate Image only without roatiting the whole GraphicsContext?

SOLVED: Thanks all for a help :)) I have solved it by using this >>

ImageView iv = new ImageView(new Image( "gfx/earth.png"));
iv.setRotate(40);
SnapshotParameters params = new SnapshotParameters();
params.setFill(Color.TRANSPARENT);
Image rotatedImage = iv.snapshot(params, null);
gc.drawImage(rotatedImage, 0, 0);
qwerty
  • 810
  • 1
  • 9
  • 26
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • Why are you drawing an image on the `Canvas`? Could you use an `ImageView` instead? – hotzst Nov 09 '15 at 17:32
  • I don't really understand what "rotating the axis" means in your question. What axis? Is it some visible rendering of an axis which you are displaying in other code not provided? – jewelsea Nov 09 '15 at 19:25
  • Likely, this question is a duplicate of [How to draw image rotated on JavaFX Canvas?](http://stackoverflow.com/questions/18260421/how-to-draw-image-rotated-on-javafx-canvas), but it is hard for me to determine that for sure. – jewelsea Nov 09 '15 at 19:26
  • @jewelsea I have tried the solution from your link .. but that causes the coordinate system problem. – Nikolas Charalambidis Nov 09 '15 at 19:32
  • I think my question is easilty understandable – Nikolas Charalambidis Nov 09 '15 at 20:16
  • There is no need to [edit your question to place the solution in the question](http://meta.stackoverflow.com/questions/307553/is-it-better-to-answer-or-edit-your-question-to-post-solution). Instead you can [accept an answer](http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). – jewelsea Nov 09 '15 at 21:53

3 Answers3

4

Let's see if I was able to understand your question...

how to rotate Image only without rotating the whole GraphicsContext?

You can't do that using just a GraphicsContext. You need to rotate the GraphicsContext to get a rotated image rendered onto it using the drawImage API. To prevent the rotation operation impacting other Canvas drawing operations, you can save and restore the GraphicsContext before and after performing the rotation (as it appears you are already doing from the code in your question).

However, one way to accomplish what you wish without rotating the GraphicsContext is to use a SceneGraph in combination with a Canvas. Place the Image in a ImageView, apply a rotate transform to the image, snapshot it to get a rotated image, then draw the rotated image into your Canvas.

ImageView iv = new ImageView(image);
iv.setRotate(40);
SnapshotParameters params = new SnapshotParameters();
params.setFill(Color.TRANSPARENT);
Image rotatedImage = iv.snapshot(params, null);
gc.drawImage(rotatedImage, 0, 0);

Sample code:

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

/** Rotates and places it in a canvas */
public class RotatedImageInCanvas extends Application {
    @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();

        ImageView iv = new ImageView(image);
        iv.setRotate(40);
        SnapshotParameters params = new SnapshotParameters();
        params.setFill(Color.TRANSPARENT);
        Image rotatedImage = iv.snapshot(params, null);
        gc.drawImage(rotatedImage, 0, 0);

        // 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); }
}

Normally, I would not recommend mixing scene graph and canvas APIs as done in the above sample, but instead just code to only the scene graph API or only the canvas API.

For a sample of a canvas only solution, see the answer to:

In general, for most operations, I find working with the Scene Graph API simpler than coding to the Canvas API and recommend using the Scene Graph API rather than the Canvas API for most tasks.

Community
  • 1
  • 1
jewelsea
  • 150,031
  • 14
  • 366
  • 406
2

A rather quick-and-dirty method that also works is to translate and rotate the entire GraphicsContext and then draw the image relative to 0 (in this case, the rotation is from the middle of the image). Then, after the image is drawn, reverse the action.

For example, if you have an image (img), a GraphicsContext (gc) and a position for the image (xp, yp), then:

// Translate and rotate.
gc.translate(xp, yp);
gc.rotate(degrees);

// Note how the image is drawn relative to 0.  Since the image needs to be
// rotated around the image center, the center is simply half of the image
// dimension.
gc.drawImage( image, -image.getWidth/2.0, -image.getImageHeight/2.0);

// Reverse the translation and rotation once drawn.
gc.rotate(-degrees);
gc.translate(-xp, -yp);
Jaco Van Niekerk
  • 4,180
  • 2
  • 21
  • 48
1

According to the other comment you should add setViewport and setTransform like I did in my rotateImage function if you want to rotate the image around a point and don't want to change the center of the image.

public Image rotateImage(Image image, int rotation) {
    ImageView iv = new ImageView(image);
    SnapshotParameters params = new SnapshotParameters();
    params.setFill(Color.TRANSPARENT);
    params.setTransform(new Rotate(rotation, image.getHeight() / 2, image.getWidth() / 2));
    params.setViewport(new Rectangle2D(0, 0, image.getHeight(), image.getWidth()));
    return iv.snapshot(params, null);
}
Leonardo
  • 13
  • 3