github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/imgutils/imgutils.go (about)

     1  package imgutils
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/nfnt/resize"
     7  	"github.com/pkg/errors"
     8  	"github.com/unionj-cloud/go-doudou/v2/toolkit/caller"
     9  	"github.com/unionj-cloud/go-doudou/v2/toolkit/stringutils"
    10  	"image"
    11  	"image/draw"
    12  	"image/gif"
    13  	"image/jpeg"
    14  	"image/png"
    15  	"io"
    16  	"os"
    17  	"path/filepath"
    18  )
    19  
    20  func ResizeKeepAspectRatio(input io.Reader, multiplier float64, output string) (string, error) {
    21  	by, err := io.ReadAll(input)
    22  	if err != nil {
    23  		return "", errors.Wrap(err, caller.NewCaller().String())
    24  	}
    25  	imgConf, imgType, err := image.DecodeConfig(bytes.NewReader(by))
    26  	if err != nil {
    27  		return "", errors.Wrap(err, caller.NewCaller().String())
    28  	}
    29  	switch imgType {
    30  	case "jpeg":
    31  		img, err := jpeg.Decode(bytes.NewReader(by))
    32  		if err != nil {
    33  			return "", errors.Wrap(err, caller.NewCaller().String())
    34  		}
    35  		m := resize.Resize(uint(float64(imgConf.Width)*multiplier), 0, img, resize.Lanczos3)
    36  		if stringutils.IsEmpty(filepath.Ext(output)) {
    37  			output += fmt.Sprintf(".%s", imgType)
    38  		}
    39  		out, err := os.Create(output)
    40  		if err != nil {
    41  			return "", errors.Wrap(err, caller.NewCaller().String())
    42  		}
    43  		defer out.Close()
    44  		jpeg.Encode(out, m, nil)
    45  	case "png":
    46  		img, err := png.Decode(bytes.NewReader(by))
    47  		if err != nil {
    48  			return "", errors.Wrap(err, caller.NewCaller().String())
    49  		}
    50  		m := resize.Resize(uint(float64(imgConf.Width)*multiplier), 0, img, resize.Lanczos3)
    51  		if stringutils.IsEmpty(filepath.Ext(output)) {
    52  			output += fmt.Sprintf(".%s", imgType)
    53  		}
    54  		out, err := os.Create(output)
    55  		if err != nil {
    56  			return "", errors.Wrap(err, caller.NewCaller().String())
    57  		}
    58  		defer out.Close()
    59  		png.Encode(out, m)
    60  	case "gif":
    61  		img, err := gif.DecodeAll(bytes.NewReader(by))
    62  		if err != nil {
    63  			return "", errors.Wrap(err, caller.NewCaller().String())
    64  		}
    65  		if multiplier != 1 {
    66  			for i, item := range img.Image {
    67  				resized := resize.Resize(uint(float64(imgConf.Width)*multiplier), 0, item, resize.Lanczos3)
    68  				rgba64 := resized.(*image.RGBA64)
    69  				palettedImage := image.NewPaletted(rgba64.Bounds(), getSubPalette(rgba64))
    70  				draw.Draw(palettedImage, palettedImage.Rect, rgba64, rgba64.Bounds().Min, draw.Src)
    71  				img.Image[i] = palettedImage
    72  			}
    73  		}
    74  		if stringutils.IsEmpty(filepath.Ext(output)) {
    75  			output += fmt.Sprintf(".%s", imgType)
    76  		}
    77  		out, err := os.Create(output)
    78  		if err != nil {
    79  			return "", errors.Wrap(err, caller.NewCaller().String())
    80  		}
    81  		defer out.Close()
    82  		gif.EncodeAll(out, img)
    83  	}
    84  	return output, nil
    85  }