使用Golang對圖像進行透明度處理

Befor(Opacity:None):

After(Opacity:50%):

直接上代碼:

1、讀取圖像:

//至於爲啥用RGBA64,因爲任性

//輸入圖像文件路徑,返回 *image.RGBA64 結果
func OpenFileIntoImage(fileName string)  (*image.RGBA64, error){
	f, err := os.Open(fileName)
	if err != nil {
		return nil, err
	}
	defer func() {
		_ = f.Close()
	}()
	//自作聰明檢查文件類型
	split := strings.Split(fileName, ".")
	if len(split) <= 1 {
		return nil, fmt.Errorf("i don't think selected file is not a normal png or jpeg image: %s", fileName)
	}
	imageType := split[len(split)-1]
	var imgRes *image.RGBA64
	switch imageType {
	case "jpg", "jpeg":
		img, err := jpeg.Decode(f)
		if err != nil {
			return nil, err
		}
		imgRes = ImageTypeToRGBA64(&img)
	case "png":
		img, err := png.Decode(f)
		if err != nil {
			return nil, err
		}
		imgRes = ImageTypeToRGBA64(&img)
	default:
		return nil, fmt.Errorf("this image format is unknown or not supported yet: %v", imageType)
	}
	return imgRes, nil
}

//Image轉換爲image.RGBA64
func ImageTypeToRGBA64(m *image.Image) *image.RGBA64 {
	bounds := (*m).Bounds()
	dx := bounds.Dx()
	dy := bounds.Dy()
	newRgba := image.NewRGBA64(bounds)
	for i := 0; i < dx; i++ {
		for j := 0; j < dy; j++ {
			colorRgb := (*m).At(i, j)
			r, g, b, a := colorRgb.RGBA()
			nR := uint16(r)
			nG := uint16(g)
			nB := uint16(b)
			alpha := uint16(a)
			newRgba.SetRGBA64(i, j, color.RGBA64{R: nR, G: nG, B: nB, A: alpha})
		}
	}
	return newRgba
}

2、改變透明度:

//將輸入圖像m的透明度變爲原來的倍數。若原來爲完成全不透明,則percentage = 0.5將變爲半透明
func OpacityAdjust(m *image.RGBA64, percentage float64) *image.RGBA64 {
	bounds := m.Bounds()
	dx := bounds.Dx()
	dy := bounds.Dy()
	newRgba := image.NewRGBA64(bounds)
	for i := 0; i < dx; i++ {
		for j := 0; j < dy; j++ {
			colorRgb := m.At(i, j)
			r, g, b, a := colorRgb.RGBA()
			opacity := uint16(float64(a)*percentage)
			//顏色模型轉換,至關重要!
			v := newRgba.ColorModel().Convert(color.NRGBA64{R: uint16(r), G: uint16(g), B: uint16(b), A: opacity})
			//Alpha = 0: Full transparent
			rr, gg, bb, aa := v.RGBA()
			newRgba.SetRGBA64(i, j, color.RGBA64{R: uint16(rr), G: uint16(gg), B: uint16(bb), A: uint16(aa)})
		}
	}
	return newRgba
}

3、補充:

//保存image.RGBA64爲png文件
func SaveImage(fileName string, m *image.RGBA64) {
	f, err := os.Create(fileName)
	if err != nil {
		panic(err)
	}
	defer func() {
		_ = f.Close()
	}()

	err = png.Encode(f, m)
	if err != nil {
		panic(err)
	}
}

4、測試

imgPath := `./panda.png`
img, err := OpenFileIntoImage(imgPath)
if err != nil {
	panic(err)
}

SaveImage("./src.png", img)

img2 := OpacityAdjust(img, 0.5)

SaveImage(p+"opacity50Percent.png", img2)

5、小字部分

    總結一下,最大的坑就是要知道“預乘透明度(Premultiplied Alpha)”這個概念。知道這個,相信大家不出一會兒就能完美實現這個我花了一晚上才搞定的功能。。。

    因爲趕時間,所以沒有詳細地分享探索官方庫image.Color相關包的整個過程。後續有空了我會將自己在探究本文主題過程中的心得體會補充上來,與大家交流。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章