github.com/masterhung0112/hk_server/v5@v5.0.0-20220302090640-ec71aef15e1c/app/imaging/utils.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package imaging 5 6 import ( 7 "image" 8 "image/color" 9 10 "github.com/disintegration/imaging" 11 ) 12 13 type rawImg interface { 14 Set(x, y int, c color.Color) 15 Opaque() bool 16 } 17 18 func isFullyTransparent(c color.Color) bool { 19 // TODO: This can be optimized by checking the color type and 20 // only extract the needed alpha value. 21 _, _, _, a := c.RGBA() 22 return a == 0 23 } 24 25 // FillImageTransparency fills in-place all the fully transparent pixels of the 26 // input image with the given color. 27 func FillImageTransparency(img image.Image, c color.Color) { 28 var i rawImg 29 30 bounds := img.Bounds() 31 32 fillFunc := func() { 33 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 34 for x := bounds.Min.X; x < bounds.Max.X; x++ { 35 if isFullyTransparent(img.At(x, y)) { 36 i.Set(x, y, c) 37 } 38 } 39 } 40 } 41 42 switch raw := img.(type) { 43 case *image.Alpha: 44 i = raw 45 case *image.Alpha16: 46 i = raw 47 case *image.Gray: 48 i = raw 49 case *image.Gray16: 50 i = raw 51 case *image.NRGBA: 52 i = raw 53 col := color.NRGBAModel.Convert(c).(color.NRGBA) 54 fillFunc = func() { 55 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 56 for x := bounds.Min.X; x < bounds.Max.X; x++ { 57 i := raw.PixOffset(x, y) 58 if raw.Pix[i+3] == 0x00 { 59 raw.Pix[i] = col.R 60 raw.Pix[i+1] = col.G 61 raw.Pix[i+2] = col.B 62 raw.Pix[i+3] = col.A 63 } 64 } 65 } 66 } 67 case *image.NRGBA64: 68 i = raw 69 col := color.NRGBA64Model.Convert(c).(color.NRGBA64) 70 fillFunc = func() { 71 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 72 for x := bounds.Min.X; x < bounds.Max.X; x++ { 73 i := raw.PixOffset(x, y) 74 a := uint16(raw.Pix[i+6])<<8 | uint16(raw.Pix[i+7]) 75 if a == 0 { 76 raw.Pix[i] = uint8(col.R >> 8) 77 raw.Pix[i+1] = uint8(col.R) 78 raw.Pix[i+2] = uint8(col.G >> 8) 79 raw.Pix[i+3] = uint8(col.G) 80 raw.Pix[i+4] = uint8(col.B >> 8) 81 raw.Pix[i+5] = uint8(col.B) 82 raw.Pix[i+6] = uint8(col.A >> 8) 83 raw.Pix[i+7] = uint8(col.A) 84 } 85 } 86 } 87 } 88 case *image.Paletted: 89 i = raw 90 fillFunc = func() { 91 for i := range raw.Palette { 92 if isFullyTransparent(raw.Palette[i]) { 93 raw.Palette[i] = c 94 } 95 } 96 } 97 case *image.RGBA: 98 i = raw 99 col := color.RGBAModel.Convert(c).(color.RGBA) 100 fillFunc = func() { 101 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 102 for x := bounds.Min.X; x < bounds.Max.X; x++ { 103 i := raw.PixOffset(x, y) 104 if raw.Pix[i+3] == 0x00 { 105 raw.Pix[i] = col.R 106 raw.Pix[i+1] = col.G 107 raw.Pix[i+2] = col.B 108 raw.Pix[i+3] = col.A 109 } 110 } 111 } 112 } 113 case *image.RGBA64: 114 i = raw 115 col := color.RGBA64Model.Convert(c).(color.RGBA64) 116 fillFunc = func() { 117 for y := bounds.Min.Y; y < bounds.Max.Y; y++ { 118 for x := bounds.Min.X; x < bounds.Max.X; x++ { 119 i := raw.PixOffset(x, y) 120 a := uint16(raw.Pix[i+6])<<8 | uint16(raw.Pix[i+7]) 121 if a == 0 { 122 raw.Pix[i] = uint8(col.R >> 8) 123 raw.Pix[i+1] = uint8(col.R) 124 raw.Pix[i+2] = uint8(col.G >> 8) 125 raw.Pix[i+3] = uint8(col.G) 126 raw.Pix[i+4] = uint8(col.B >> 8) 127 raw.Pix[i+5] = uint8(col.B) 128 raw.Pix[i+6] = uint8(col.A >> 8) 129 raw.Pix[i+7] = uint8(col.A) 130 } 131 } 132 } 133 } 134 default: 135 return 136 } 137 138 if !i.Opaque() { 139 fillFunc() 140 } 141 } 142 143 // FillCenter creates an image with the specified dimensions and fills it with 144 // the centered and scaled source image. 145 func FillCenter(img image.Image, w, h int) *image.NRGBA { 146 return imaging.Fill(img, w, h, imaging.Center, imaging.Lanczos) 147 }