You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

358 lines
9.3 KiB

9 months ago
package data
import (
"context"
"fm-upload/internal/biz"
"fm-upload/internal/data/model"
"fm-upload/utils"
"fmt"
"math"
"os"
"regexp"
"strconv"
"strings"
"github.com/go-kratos/kratos/v2/log"
)
type imageRepo struct {
storage biz.StorageRepo
log *log.Helper
}
// NewGreeterRepo .
func NewImageRepo(storage biz.StorageRepo, logger log.Logger) biz.ImageRepo {
return &imageRepo{
storage: storage,
log: log.NewHelper(logger),
}
}
func (r *imageRepo) ImageDeal(ctx context.Context, tmpfile string, width uint, height uint, x *model.ImageParams, ofmt, fileM, fileId, bucket string) (ret *model.MyPutRet, resUrl, errd string, code int, err error) {
var key string
bucket0 := bucket
tt := strings.Index(bucket, ":")
if tt >= 0 && tt < len(bucket)-1 {
t1 := strings.Index(bucket, ":")
key = bucket[t1+1:]
bucket0 = bucket[:t1]
} else if tt < 0 {
key = strings.ReplaceAll(x.ProcessImageName, " ", "") //指定
if key != "" {
re := regexp.MustCompile("[\u4e00-\u9fa5_\\-a-zA-Z0-9\\.]+")
t := re.FindAllString(key, -1)
key = fileM + strings.Join(t, "")
}
}
if key == "" && x.ProcessImageSuffix != "" {
key = fileId + x.ProcessImageSuffix
}
if tt == len(bucket)-1 {
bucket0 = bucket[:len(bucket)-1]
if key == "" {
bucket = bucket0
} else {
bucket += key
}
}
// width0 := width
// width0 := height
var dwidth, dheight, xx, yy uint
if x.Crop != nil {
xx = uint(math.Floor(x.Crop.X + 0.5))
yy = uint(math.Floor(x.Crop.Y + 0.5))
t1 := uint(math.Floor(x.Crop.W + 0.5))
t2 := uint(math.Floor(x.Crop.H + 0.5))
if xx+t1 > width {
width = width - xx
} else {
width = t1
}
if yy+t2 > height {
height = height - yy
} else {
height = t2
}
}
if x.Ratio > 0 {
dwidth = uint(float32(width) * x.Ratio)
dheight = uint(float32(height) * x.Ratio)
} else if x.Width > 0 || x.Height > 0 {
if x.Height == 0 {
dwidth = x.Width
dheight = uint(float32(height*dwidth) / float32(width))
} else if x.Width == 0 {
dheight = x.Height
dwidth = uint(float32(width*dheight) / float32(height))
} else {
dwidth = x.Width
dheight = x.Height
}
} else if x.MaxHeight > 0 {
if height > x.MaxHeight {
dheight = x.MaxHeight
dwidth = uint(float32(width*dheight) / float32(height))
}
} else if x.MaxWidth > 0 {
if width > x.MaxWidth {
dwidth = x.MaxWidth
dheight = uint(float32(height*dwidth) / float32(width))
}
} else if x.Reshape != "" {
t1 := strings.Split(x.Reshape, ":")
if len(t1) != 2 || t1[0] == "" || t1[1] == "" {
errd = "reshape参数错误"
code = 425
return
}
var t2 float64
t2, err = strconv.ParseFloat(t1[0], 32)
var t3 float64
if err == nil {
t3, err = strconv.ParseFloat(t1[1], 32)
}
if err != nil {
errd = "reshape参数错误"
code = 425
return
}
th := int(t2 / t3 * float64(width))
a := int(height) - th
if a > 0 {
height = uint(th)
yy += uint(a / 2)
} else if a < 0 {
tw := uint(t3 / t2 * float64(height))
xx += width - tw
width = tw
}
}
if key == "" {
if dwidth > 0 {
key = fileId + fmt.Sprintf("%s_%dx%d.%s", utils.GetUUID()[:4], dwidth, dheight, x.Format)
} else {
key = fileId + fmt.Sprintf("%s_%dx%d.%s", utils.GetUUID()[:4], width, height, x.Format)
}
}
re := regexp.MustCompile(`([0-9\.]+)(\w?)`)
t := re.FindStringSubmatch(strings.ToLower(x.ImageSize))
limitSize := int64(0)
if len(t) > 0 {
a, _ := strconv.ParseFloat(t[1], 32)
if a > 0 {
if t[2] == "k" {
a *= 1024
} else if t[2] == "m" {
a *= 1048576
}
limitSize = int64(a)
}
}
var out []byte
var cmdString string
var tmpfile2 string
x.Format = strings.ToLower(x.Format)
if x.Format == "webp" {
if x.Quality == 0 {
if x.ImageSize != "" {
if limitSize > 0 {
cmdString = fmt.Sprintf("cwebp -quiet -m 6 -size %d", limitSize)
}
}
if cmdString == "" {
cmdString = "cwebp -quiet -q 100 -m 6"
}
} else {
if x.Quality > 100 {
x.Quality = 100
}
cmdString = fmt.Sprintf("cwebp -quiet -q %d -alpha_q 1 -m 6", x.Quality)
}
if x.Crop != nil {
cmdString += fmt.Sprintf(" -crop %d %d %d %d", xx, yy, width, height)
}
if dwidth > 0 {
cmdString += fmt.Sprintf(" -resize %d %d", dwidth, dheight)
}
// cmdString += " -o - -- -"
cmdString += fmt.Sprintf(" -blend_alpha 0xffffff %s -o -", tmpfile)
out, err = utils.RunCommand(cmdString, nil, true)
if err == nil {
ret, err = r.storage.SaveToHw(ctx, out, key, bucket)
}
} else {
var tof string
if x.Format == "heic" {
tof = "HEIF"
} else if x.Format == "jpg" || x.Format == "jpeg" {
tof = "JPEG"
} else {
tof = strings.ToUpper(x.Format)
}
if tof == "JPEG" {
tmpfile2 = tmpfile + ".jpg"
defer func() {
_ = os.Remove(tmpfile2)
}()
// if ofmt != "JPEG" || dwidth > 0 || x.Crop != nil || x.Reshape != "" {
cmdString = fmt.Sprintf("convert %s -background white -alpha remove -alpha off -flatten -compress LOSSLESS", tmpfile)
if x.Crop != nil || x.Reshape != "" {
cmdString += fmt.Sprintf(" -crop %dx%d+%d+%d", width, height, xx, yy)
}
if dwidth > 0 {
cmdString += fmt.Sprintf(" -resize %dx%d", dwidth, dheight)
}
cmdString += fmt.Sprintf(" %s", tmpfile2)
_, err = utils.RunCommand(cmdString, nil, false)
// }
if err == nil {
q := uint(0)
if x.Quality > 0 {
q = x.Quality - 1
if q == 0 {
q = 1
}
}
cmdString := "jpegoptim -q"
if x.Progressive {
cmdString += " --all-progressive"
x.Progressive = false
}
if q > 0 {
cmdString += fmt.Sprintf(" -m %d", q)
}
if x.ImageSize != "" {
cmdString += fmt.Sprintf(" --size %s", x.ImageSize)
}
cmdString += fmt.Sprintf(" %s", tmpfile2)
_, err = utils.RunCommand(cmdString, nil, false)
}
if err != nil {
code = 425
errd = "image process error"
return
}
ret, err = r.storage.SaveFileToHw(ctx, tmpfile2, key, bucket)
} else if tof == "PNG" {
tmpfile0 := tmpfile
tmpfile2 = tmpfile + ".png"
tmpfile3 := tmpfile + "3.png"
defer func() {
_ = os.Remove(tmpfile2)
_ = os.Remove(tmpfile3)
}()
q := uint(0)
if x.Quality > 0 {
q = x.Quality - 1
if q == 0 {
q = 1
}
}
if ofmt != "PNG" || dwidth > 0 || x.Crop != nil || x.Reshape != "" {
cmdString = fmt.Sprintf("convert %s -compress LOSSLESS", tmpfile)
if x.Crop != nil || x.Reshape != "" {
cmdString += fmt.Sprintf(" -crop %dx%d+%d+%d", width, height, xx, yy)
}
if x.Progressive {
cmdString += " -interlace Plane"
}
if q > 0 {
cmdString += fmt.Sprintf(" -m %d", q)
}
if dwidth > 0 {
cmdString += fmt.Sprintf(" -resize %dx%d", dwidth, dheight)
}
cmdString += fmt.Sprintf(" %s", tmpfile2)
_, err = utils.RunCommand(cmdString, nil, false)
tmpfile0 = tmpfile2
// err = mw.ResizeImage(dwidth, dheight, imagick.FILTER_LANCZOS)
}
if err == nil {
cmdString := fmt.Sprintf("optipng -quiet %s -out %s", tmpfile0, tmpfile2)
_, err = utils.RunCommand(cmdString, nil, false)
}
if limitSize > 0 {
qs := []uint{90, 80, 70, 60, 40}
fi, _ := os.Stat(tmpfile2)
lastSize := fi.Size()
_, err = utils.RunCommand(fmt.Sprintf("cp %s %s", tmpfile2, tmpfile3), nil, false)
for i := 0; i < 5 && err == nil; i++ {
if qs[i] > q {
continue
}
cmdString := fmt.Sprintf("convert %s -m %d %s", tmpfile3, qs[i], tmpfile2)
_, err = utils.RunCommand(cmdString, nil, false)
if err != nil {
break
}
cmdString = fmt.Sprintf("optipng -quiet %s -out %s", tmpfile2, tmpfile2)
_, err = utils.RunCommand(cmdString, nil, false)
fi, _ := os.Stat(tmpfile2)
if fi.Size() <= limitSize || fi.Size() >= lastSize {
break
}
lastSize = fi.Size()
}
}
if err != nil {
code = 425
errd = "image process error"
return
}
ret, err = r.storage.SaveFileToHw(ctx, tmpfile2, key, bucket)
} else {
tmpfile2 := tmpfile + "." + x.Format
tmpfile3 := tmpfile + "3." + x.Format
defer func() {
_ = os.Remove(tmpfile2)
_ = os.Remove(tmpfile3)
}()
cmdString = "convert " + tmpfile + " -background white -alpha remove -alpha off -flatten"
if x.Crop != nil || x.Reshape != "" {
cmdString += fmt.Sprintf(" -crop %dx%d+%d+%d", width, height, xx, yy)
}
if x.Progressive {
cmdString += " -interlace Plane"
}
if x.Quality > 0 {
cmdString += fmt.Sprintf(" -quality %d", x.Quality-1)
} else {
cmdString += " -compress LOSSLESS"
}
if dwidth > 0 {
cmdString += fmt.Sprintf(" -resize %dx%d", dwidth, dheight)
}
cmdString += " " + tmpfile2
_, err = utils.RunCommand(cmdString, nil, false)
if err == nil && limitSize > 0 {
_, err = utils.RunCommand(fmt.Sprintf("cp %s %s", tmpfile2, tmpfile3), nil, false)
for i := 0; i < 2 && err == nil; i++ {
fi, _ := os.Stat(tmpfile2)
q := uint(float64(limitSize) / float64(fi.Size()) * 100)
if q >= 100 {
break
}
if q < 5 {
q = 5
}
cmdString += fmt.Sprintf("convert %s -m %d %s", tmpfile3, q, tmpfile2)
_, err = utils.RunCommand(cmdString, nil, false)
}
}
if err != nil {
code = 425
errd = "image process error"
return
}
ret, err = r.storage.SaveFileToHw(ctx, tmpfile2, key, bucket)
}
}
if err != nil {
code = 426
errd = "error upload to qiniuyun"
return
}
resUrl = ret.ReturnPrefix + key
return
}