【Go語言繪圖】gg 庫的基本使用

弗蘭克的貓發表於2020-11-29

最近接了個比較大的需求,需要做很多圖片處理的事情,比如圖片的旋轉裁截拼接,各種漸變處理,文字排列,一開始光是想想就頭疼。但沒有辦法,既然已經需求已經到手上了,那就得把它做好才行,於是便開始被迫營業,無證上崗了。

經過一番查詢,找到了一個Go語言圖片處理的庫,經過調研發現還挺強的,能滿足需求,於是決定寫點文章,記錄一下使用心得,以便日後不時之需。

gg 庫的安裝和簡單使用

使用之前,我們當然得先來安裝一下這個庫:

go get -u github.com/fogleman/gg

這個庫的一個好處是有很多測試程式碼,可以拿來跑跑看,就知道它大概能實現什麼樣的效果了。

這是它例子的大概效果圖,可以看到,能實現的圖形效果還是挺多的。

我們拿其中的一個程式碼來簡單體驗一下:

package main

import "github.com/fogleman/gg"

func main() {
    dc := gg.NewContext(1000, 1000)
    dc.DrawCircle(500, 500, 400)
    dc.SetRGB(0, 0, 0)
    dc.Fill()
    dc.SavePNG("out.png")
}

duang 的一下,一張黑不溜秋的圓形圖就生成了。

關於上面的程式碼,下面會進行逐一說明。

調整生成圖片的大小

dc := gg.NewContext(1000, 1000)

這是先初始化一個 Context 物件,使用庫之前都需要先初始化一個 Context 物件,後面的兩個 1000,分別對應著最終生成圖片的寬度和高度。我們可以修改一下高度為 500 看看效果。

dc := gg.NewContext(1000, 500)

可以看到圖片被腰斬了,高度矮了一半,同樣修改寬度引數也可以得到類似的效果,這裡就不演示了。

調整圓形引數

dc.DrawCircle(500, 500, 400)

這裡是畫一個圓心位置在 (500,500),半徑為 400 的圓形。需要說明的一點是,這裡的座標軸是以左上角為原點的,水平向右是橫軸正方向,豎直向下是縱軸正方向,所以(500,500)正是中心位置。我們可以調整一下引數值來看下效果。

dc := gg.NewContext(1000, 1000)
dc.DrawCircle(300, 300, 400)

可以看到,圓心往左上角移動了。還可以調整一下半徑引數試試:

dc := gg.NewContext(1000, 1000)
dc.DrawCircle(300, 300, 300)

這樣我們又得到了一個完整的圓。

調整顏色

dc.SetRGB(0, 0, 0)
dc.Fill()

這兩句的意思是先設定顏色值為 (0,0,0),也就是黑色,乍眼一看這三個值分別對應的是顏色的 R、G、B值,但實際上完全不是這麼回事,這裡需要注意的是,這三個值分別代表紅色、綠色、藍色的程度,所以如果分別設定為,會得到下面的三張圖。

那如果想要根據RGB值來設定顏色該怎麼處理呢?其實也很簡單,做一個壓縮對映即可,RGB值的範圍是0~255,表示的含義也是對應色值的程度,這裡不過將範圍變成了0~1,那我們將需要使用到的值除以255就可以得到對應的對映值了。具體的顏色RGB值跟顏色的對應關係可以在網上搜到。

https://tool.oschina.net/commons?type=3

下面我們用淡黃色做一個例子,對應的 RGB 值是 (255,222,173) ,我們新增一下對映轉換的程式碼即可:

var rbgConverter = func(r []float64) []float64 {
	result := make([]float64, 0)
	for i := 0; i < len(r); i++ {
		result = append(result, r[i] / 255)
	}
	return result
}

func main() {
	dc := gg.NewContext(1000, 1000)

	dc.DrawCircle(500, 500, 400)

	rgb := []float64{255,222,173}
	newRgb := rbgConverter(rgb)

	dc.SetRGB(newRgb[0], newRgb[1], newRgb[2])
	dc.Fill()
	dc.SavePNG("out.png")
}

這樣我們就得到了一張黃圖。

儲存圖片

dc.SavePNG("out.png")

SavePNG() 方法可以將當前圖形儲存成 PNG 格式檔案,路徑可以是相對路徑,也可以是絕對路徑。

SaveJPG() 方法可以將當前圖形儲存成 JPG 格式檔案。

當然,這裡的兩個方法其實也只是包裝了一下,點進程式碼可以看到,裡面並沒有什麼奇奇怪怪的邏輯。

// SavePNG encodes the image as a PNG and writes it to disk.
func (dc *Context) SavePNG(path string) error {
	return SavePNG(path, dc.im)
}

func SavePNG(path string, im image.Image) error {
	file, err := os.Create(path)
	if err != nil {
		return err
	}
	defer file.Close()
	return png.Encode(file, im)
}

所以,我們也可以根據自己的需要將圖片儲存成其它格式或者存到其它地方。

載入圖片

載入圖片有三個方法可以實現,LoadPNG() 用來載入 PNG 格式的圖片,LoadJPG() 用來載入 JPG 格式的圖片,如果不清楚該用什麼方法,可以直接使用 LoadImage() 方法來載入圖片。

載入圖片後,得到的是一個 image.Image 物件,可以通過該物件來獲取圖片的一些基本資訊,如:圖片的長和寬、圖片某一點的顏色RGB值。

載入圖片之後,可以使用 DrawImage() 方法來將圖片繪製出來,以便用於後續操作。

im, err := gg.LoadImage("/Users/bytedance/Desktop/test.jpg")
if err != nil {
    panic(err)
}
w := im.Bounds().Size().X
h := im.Bounds().Size().Y

dc := gg.NewContext(h, w)
dc.DrawImage(im, 0, 0)

裁剪

有一個經常使用到的方法叫 Clip() ,該方法可以將影像進行裁剪,裁剪的形狀取決於之前畫的圖形。

下面來舉個例子,這是我們要裁剪的圖,我們用一個圓形來對它進行裁剪。

func main() {
    // 載入圖片,這裡路徑換成自己的
	im, err := gg.LoadImage("test.jpg")
	if err != nil {
		panic(err)
	}

    // 獲取圖片的寬度和高度
	w := im.Bounds().Size().X
	h := im.Bounds().Size().Y

	dc := gg.NewContext(h, w)
    
    
    // 取寬度和高度的最小值作為直徑
	radius := math.Min(float64(w), float64(h)) / 2
    // 畫圓形
	dc.DrawCircle(float64(w/2), float64(h/2), radius)
    // 對畫布進行裁剪
	dc.Clip()
    // 載入圖片
	dc.DrawImage(im, 0, 0)
	dc.SavePNG("out.png")
}

這樣一來,頭像就做好了【手動狗頭】。

小結

Go 語言也可以實現對圖片進行很多型別的操作,今天主要介紹了圖片的載入、儲存、繪製圓形、調整大小和顏色以及裁剪。之後還會進一步介紹其它功能。

我覺得如果不是需要使用並沒有熟悉它的必要,但知道有這麼個東西,知道它能實現什麼樣的效果,可以讓你手上的牌又多了一張,以後有需要的時候便不至於捉襟見肘了。所以還在等什麼,趕緊點贊收藏加關注吧~

相關文章