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相關包的整個過程。後續有空了我會將自己在探究本文主題過程中的心得體會補充上來,與大家交流。