【Go語言繪圖】圖片的旋轉

弗蘭克的貓發表於2020-12-16

在上一篇中,我們瞭解了gg庫的基本使用,包括調整大小、調整圓形引數、設定顏色、儲存圖片、載入圖片和裁剪。這一篇我們來學習一下圖片的旋轉。

載入圖片

首先,我們先來一張黃圖。

func TestRotateImage(t *testing.T) {
	width := 1000
	height := 1000

	dc := gg.NewContext(width, height)
	dc.DrawRectangle(0, 0, float64(width), float64(width))
	dc.SetRGB255(255, 255, 0)
	dc.Fill()
	dc.SavePNG("test.png")
}

然後載入好我們要旋轉的圖片,用的仍舊是我們上一篇中使用的圖。

func TestRotateImage(t *testing.T) {
	im, err := gg.LoadImage("/Users/bytedance/Desktop/test.png")
	if err != nil {
		panic(err)
	}
	w := im.Bounds().Size().X
	h := im.Bounds().Size().Y

	width := 2 * w
	height := 2 * h

	dc := gg.NewContext(width, height)
	dc.DrawRectangle(0, 0, float64(width), float64(width))
	dc.SetRGB255(255, 255, 0)
	dc.Fill()

	dc.DrawImage(im, width/4, height/4)
	dc.SavePNG("test.png")
}

這裡為了更好的看到旋轉的效果,對之前的程式碼做了一些調整。把畫布大小設定為2倍圖片的長寬。

width := 2 * w
height := 2 * h

dc := gg.NewContext(width, height)

然後繪製了一個矩形,並且將它的顏色填充為黃色(因為圖片比較白,用黑色背景更容易看到邊界)。

dc.DrawRectangle(0, 0, float64(2*h), float64(2*w))
dc.SetRGB255(255, 255, 0)
dc.Fill()

順便糾正一下上一篇中的遺漏的點,使用 setRGB() 方法來設定顏色確實需要使用轉換函式來將RGB值進行對映,但還有另一個方法 SetRGB255() 可以直接設定RGB值,就不需要先進行一次轉換了。

然後我們將圖片載入到了正中心的位置,(w/4,h/4) 對應圖片左上角在畫布上的位置。

dc.DrawImage(im, width/4, height/4)

輸出的圖片如下:

旋轉圖片

圖片載入好了,下面我們開始新增一個旋轉操作。

func TestRotateImage(t *testing.T) {
	im, err := gg.LoadImage("/Users/bytedance/Desktop/test.png")
	if err != nil {
		panic(err)
	}
	w := im.Bounds().Size().X
	h := im.Bounds().Size().Y

	width := 2 * w
	height := 2 * h

	dc := gg.NewContext(width, height)
	dc.DrawRectangle(0, 0, float64(width), float64(width))
	dc.SetRGB255(255, 255, 0)
	dc.Fill()

	dc.Rotate(45)
	dc.DrawImage(im, width/4, height/4)
	dc.SavePNG("test.png")
}

其實只新增了一行程式碼,就是在載入圖片前先呼叫了 Rotate() 方法。想象之中,我們會把圖片旋轉45度,但實際上是這樣的:

好像不太符合預期,實際上,仔細研究一下就會發現,這裡的旋轉是圍繞原點也就是整個畫布的左上角進行旋轉的,那我想要它圍繞中心點旋轉該怎麼辦呢?別慌,換一個方法就可以了。RotateAbout() 方法可以指定圖片的旋轉中心點,換這個來試試看:

func TestRotateImage(t *testing.T) {
	im, err := gg.LoadImage("/Users/bytedance/Desktop/test.png")
	if err != nil {
		panic(err)
	}
	w := im.Bounds().Size().X
	h := im.Bounds().Size().Y

	width := 2 * w
	height := 2 * h

	dc := gg.NewContext(width, height)
	dc.DrawRectangle(0, 0, float64(width), float64(width))
	dc.SetRGB255(255, 255, 0)
	dc.Fill()

	dc.RotateAbout(45, float64(width/2), float64(height/2))
	dc.DrawImage(im, width/4, height/4)
	dc.SavePNG("test.png")
}

這下圖片確實繞中心點旋轉了,但轉45度好像不應該是這樣的,再來看看這個方法的說明:

// RotateAbout updates the current matrix with a clockwise rotation.
// Rotation occurs about the specified point. Angle is specified in radians.

可以看到,第一個引數的意思其實代表的是弧度,而不是角度,所以想要旋轉45度當然不能這麼傳,我們換一個姿勢再試試。

func TestRotateImage(t *testing.T) {
	im, err := gg.LoadImage("/Users/bytedance/Desktop/test.png")
	if err != nil {
		panic(err)
	}
	w := im.Bounds().Size().X
	h := im.Bounds().Size().Y

	width := 2 * w
	height := 2 * h

	dc := gg.NewContext(width, height)
	dc.DrawRectangle(0, 0, float64(width), float64(width))
	dc.SetRGB255(255, 255, 0)
	dc.Fill()

	dc.RotateAbout(gg.Radians(45), float64(width/2), float64(height/2))
	dc.DrawImage(im, width/4, height/4)
	dc.SavePNG("test.png")
}

這下終於得到了我們想要的圖。

總結

圖片旋轉其實很簡單,只需要在繪製前呼叫 Rotate()RotateAbout() 方法即可。但需要注意幾點:

  1. 旋轉是順時針旋轉
  2. Rotate 方法是繞左上角旋轉
  3. 第一個引數都代表的是弧度而不是角度

這樣旋轉我們也能掌握了,圖片處理功能又進了一步。喜歡本文的朋友歡迎點贊收藏加關注~

相關文章