tdewolff / canvas

Cairo in Go: vector to raster, SVG, PDF, EPS, WASM, OpenGL, Gio, etc.
MIT License
1.51k stars 103 forks source link

[Question] Can we transform an element itself instead transform canvas? #284

Closed p1usign closed 4 months ago

p1usign commented 7 months ago

To describe it more clearly, let me give an example. Now I have an image, its width and height are 100px. I want rotate this image around its center, it might be something like:

img.offset = (50, 50) // set the center point of the image as origin point
img.Rotate(90) // it will rotate around the center point

After rotate, We want to put it on canvas upper left corner:

ctx.DrawImage(img, 50, 50) // this position is the image center point's position

In the end, we get a image, which is completely in the canvas upper left corner, after being rotated 90 degrees. image

How can we simply achieve this effect? I look forward to discussing it with you

tdewolff commented 7 months ago

Thanks for reaching out! You can't rotate an image in-place before drawing it, you need to adjust the view to draw it correctly. There are other libraries that can help you rotate an image 90°, 180°, 270° before hand, but if you want to just use canvas here is an example to achieve what you want:

package main

import (
    "image/png"
    "os"

    "github.com/tdewolff/canvas"
    "github.com/tdewolff/canvas/renderers"
)

func main() {
    // load image
    f, err := os.Open("lenna.png")
    if err != nil {
        panic(err)
    }
    lenna, err := png.Decode(f)
    if err != nil {
        panic(err)
    }

    // setup canvas
    c := canvas.New(200, 200)
    ctx := canvas.NewContext(c)

    // set coordinate system with origin in top-left
    ctx.SetCoordSystem(canvas.CartesianIV)

    // rotate the view at the center of the image
    ctx.RotateAbout(-90.0, 50.0, 50.0)                   // negative is counter-clockwise in CartesianIV
    ctx.DrawImage(0, 0, lenna, canvas.DPMM(512.0/100.0)) // image is 512x512 px drawn as 100x100 mm
    ctx.ResetView()

    // output as 200x200px
    renderers.Write("out.png", c, canvas.DPMM(1.0))
}

Let me know if that works or if you have any other questions!

p1usign commented 4 months ago

get! thanks for your reply!