func CenterCrop(img *io.Reader, width, height int) ([]byte, error) { m, _, err := image.Decode(*img) if err != nil { return nil, err } // TODO: I probably can switch to using imaging.Thumbnail here. imgW := float64(m.Bounds().Max.X - m.Bounds().Min.X) imgH := float64(m.Bounds().Max.Y - m.Bounds().Min.Y) targetW := float64(width) targetH := float64(height) var scale float64 if imgW*targetH > targetW*imgH { scale = targetH / imgH } else { scale = targetW / imgW } m = imaging.Resize(m, int(imgW*scale), int(imgH*scale), imaging.Lanczos) m = imaging.CropCenter(m, width, height) buf := new(bytes.Buffer) jpeg.Encode(buf, m, &jpeg.Options{Quality: 95}) return buf.Bytes(), nil }
/* resize when there is no height constraint, otherwise crop */ func (result *imageInfo) resizeOrCrop(img image.Image, width int, height int) image.Image { var imgdata image.Image if height == 0 { imgdata = imaging.Resize(img, width, height, imaging.Lanczos) } else { imgdata = imaging.CropCenter(img, width, height) } result.width = imgdata.Bounds().Max.X result.height = imgdata.Bounds().Max.Y return imgdata }
func (m *User) ValidateAndSetAvatar(avatarFile io.Reader, filename string) error { var img image.Image var err error var ext string var tmpFile *os.File if tmpFile, err = ioutil.TempFile(setting.TmpPath, "uploaded-avatar-"); err != nil { return err } defer os.Remove(tmpFile.Name()) defer tmpFile.Close() if _, err = io.Copy(tmpFile, avatarFile); err != nil { return err } tmpFile.Seek(0, 0) if filename != "" { ext = strings.ToLower(filepath.Ext(filename)) } else { ext = utils.GetImageFormat(tmpFile) tmpFile.Seek(0, 0) } if ext != ".jpg" && ext != ".jpeg" && ext != ".png" && ext != ".gif" { return errors.New("只允许jpg, png, gif类型的图片") } switch ext { case ".jpg", ".jpeg": img, err = jpeg.Decode(tmpFile) if err != nil { return errors.New("无法识别此jpg文件") } case ".png": img, err = png.Decode(tmpFile) if err != nil { return errors.New("无法识别此png文件") } case ".gif": img, err = gif.Decode(tmpFile) if err != nil { return errors.New("无法识别此gif文件") } } //crop正方形 bound := img.Bounds() if w, h := bound.Dx(), bound.Dy(); w > h { img = imaging.CropCenter(img, h, h) } else if w < h { img = imaging.CropCenter(img, w, w) } //制作缩略图 imgL := imaging.Resize(img, 220, 220, imaging.Lanczos) imgM := imaging.Resize(img, 48, 48, imaging.Lanczos) imgS := imaging.Resize(img, 24, 24, imaging.Lanczos) uuid := strings.Replace(uuid.New(), "-", "", -1) imgLName, imgMName, imgSName := setting.TmpPath+uuid+"-l.png", setting.TmpPath+uuid+"-m.png", setting.TmpPath+uuid+"-s.png" errL, errM, errS := imaging.Save(imgL, imgLName), imaging.Save(imgM, imgMName), imaging.Save(imgS, imgSName) if errL != nil || errM != nil || errS != nil { return errors.New("无法保存头像临时文件") } defer os.Remove(imgLName) defer os.Remove(imgMName) defer os.Remove(imgSName) _, errL = setting.AvatarFSM.PutFile(imgLName, string(uuid[0])+"/"+string(uuid[1])+"/"+uuid+"-l.png") _, errM = setting.AvatarFSM.PutFile(imgMName, string(uuid[0])+"/"+string(uuid[1])+"/"+uuid+"-m.png") _, errS = setting.AvatarFSM.PutFile(imgSName, string(uuid[0])+"/"+string(uuid[1])+"/"+uuid+"-s.png") if errL != nil || errM != nil || errS != nil { return errors.New("无法保存头像") } if m.Avatar != "" { errL = setting.AvatarFSM.Delete(m.Avatar + "-l.png") errM = setting.AvatarFSM.Delete(m.Avatar + "-m.png") errS = setting.AvatarFSM.Delete(m.Avatar + "-s.png") } m.Avatar = uuid //errL, errM, errS = setting.AvatarFSM.Delete return nil }