feat: 头像上传选区限制 3840×3840 + 客户端裁剪压缩
- 后端:3840×2160 限制改为 3840×3840(方形限制适应方形裁剪),并移到裁剪结果上检查而非原图 - 前端:原图短边超过 3840 时自动抬高最小缩放,确保选区永不超过 3840×3840 - 前端:裁剪确认后用 Canvas 预裁剪 + JPEG 压缩再上传,大幅节省带宽 - 前端:裁剪框标题栏新增实时像素尺寸提示 - 新增 .crop-info 样式
This commit is contained in:
@ -26,7 +26,7 @@ const (
|
||||
avatarMinWidth = 128 // 最小宽高,防止马赛克图被拉升
|
||||
avatarMinHeight = 128
|
||||
avatarMaxWidth = 3840
|
||||
avatarMaxHeight = 2160
|
||||
avatarMaxHeight = 3840
|
||||
avatarOutputSize = 512
|
||||
avatarTargetKB = 100
|
||||
avatarStorageDir = "storage/uploads/avatars"
|
||||
@ -98,9 +98,7 @@ func (s *AvatarService) ProcessImage(userID uint, file io.Reader, contentType st
|
||||
}
|
||||
bounds := img.Bounds()
|
||||
w, h := bounds.Dx(), bounds.Dy()
|
||||
if w > avatarMaxWidth || h > avatarMaxHeight {
|
||||
return "", fmt.Errorf("图片分辨率不能超过 3840x2160")
|
||||
}
|
||||
// 原图只检查最小尺寸,确保有足够像素供上采样
|
||||
if w < avatarMinWidth || h < avatarMinHeight {
|
||||
return "", fmt.Errorf("图片分辨率不能低于 128x128")
|
||||
}
|
||||
@ -114,6 +112,13 @@ func (s *AvatarService) ProcessImage(userID uint, file io.Reader, contentType st
|
||||
cropped = centerCrop(img)
|
||||
}
|
||||
|
||||
// 裁切后检查最大尺寸(用户实际选区不应超过此限制)
|
||||
cb := cropped.Bounds()
|
||||
cw, ch := cb.Dx(), cb.Dy()
|
||||
if cw > avatarMaxWidth || ch > avatarMaxHeight {
|
||||
return "", fmt.Errorf("裁切区域分辨率不能超过 3840x3840")
|
||||
}
|
||||
|
||||
// 5. 缩放至 512x512(CatmullRom 高质量)
|
||||
resized := image.NewNRGBA(image.Rect(0, 0, avatarOutputSize, avatarOutputSize))
|
||||
draw.CatmullRom.Scale(resized, resized.Bounds(), cropped, cropped.Bounds(), draw.Over, nil)
|
||||
|
||||
Reference in New Issue
Block a user