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  }