Some bugfixes around profile picture cropping

face-detect
Noah Petherbridge 2023-07-22 11:51:58 -07:00
parent 12dcc10ff3
commit 356f94698f
3 changed files with 52 additions and 15 deletions

View File

@ -143,7 +143,7 @@ func Upload() http.HandlerFunc {
}
// Are we uploading a profile pic? If so, set the user's pic now.
if vars["Intent"] == "profile_pic" {
if vars["Intent"] == "profile_pic" && cropFilename != "" {
log.Info("User %s is setting their profile picture", user.Username)
user.ProfilePhoto = *p
user.Save()

View File

@ -40,12 +40,9 @@ func UploadPhoto(cfg UploadConfig) (string, string, error) {
dbExtension = extension
)
switch extension {
case ".jpg":
fallthrough
case ".jpe":
fallthrough
case ".jpeg":
case ".jpg", ".jpe", ".jpeg":
extension = ".jpg"
dbExtension = ".jpg"
case ".png":
extension = ".png"
dbExtension = ".jpg"
@ -114,12 +111,18 @@ func UploadPhoto(cfg UploadConfig) (string, string, error) {
w = cfg.Crop[2]
h = cfg.Crop[3]
)
croppedImg := Crop(origImage, x, y, w, h)
croppedImg, err := Crop(origImage, x, y, w, h)
if err != nil {
// Error during the crop: return it and just the original image filename
log.Error("Couldn't crop new profile photo: %s", err)
return filename, "", nil
}
// Write that to disk, too.
log.Debug("Writing cropped image to disk: %s", cropFilename)
if err := ToDisk(cropFilename, extension, croppedImg, &cfg); err != nil {
return filename, "", err
log.Error("Couldn't write cropped photo to disk: %s", err)
return filename, "", nil
}
// Return both filenames!
@ -148,11 +151,35 @@ func Scale(src image.Image, rect image.Rectangle, scale draw.Scaler) image.Image
// Crop an image, returning the new image. Example:
//
// cropped := Crop()
func Crop(src image.Image, x, y, w, h int) image.Image {
func Crop(src image.Image, x, y, w, h int) (image.Image, error) {
// Sanity check the crop constraints, e.g. sometimes the front-end might send "203 -1 738 738" with a negative x/y value
if x < 0 {
log.Debug("Crop(%d, %d, %d, %d): x value %d too low, cap to zero", x, y, w, h, x)
x = 0
}
if y < 0 {
log.Debug("Crop(%d, %d, %d, %d): y value %d too low, cap to zero", x, y, w, h, y)
y = 0
}
if x+w > src.Bounds().Dx() {
log.Debug("Crop(%d, %d, %d, %d): width is too wide", x, y, w, h)
w = src.Bounds().Dx() - x
}
if y+h > src.Bounds().Dy() {
log.Debug("Crop(%d, %d, %d, %d): height is too tall", x, y, w, h)
h = src.Bounds().Dy() - y
}
// If they are trying to crop a 0x0 image, return an error.
if w == 0 || h == 0 {
return nil, errors.New("can't crop to a 0x0 resolution image")
}
log.Debug("Crop(): running draw.Copy with dimensions %d, %d, %d, %d", x, y, w, h)
dst := image.NewRGBA(image.Rect(0, 0, w, h))
srcrect := image.Rect(x, y, x+w, y+h)
draw.Copy(dst, image.ZP, src, srcrect, draw.Over, nil)
return dst
draw.Copy(dst, image.Point{}, src, srcrect, draw.Over, nil)
return dst, nil
}
// ReCrop an image, loading the original image from disk. Returns the newly created filename.
@ -170,7 +197,8 @@ func ReCrop(filename string, x, y, w, h int) (string, error) {
// Decode the image.
var img image.Image
switch ext {
case ".jpg":
case ".jpg", ".jpeg", ".jpe":
// NOTE: new uploads enforce .jpg extension, some legacy pics may have slipped thru
img, err = jpeg.Decode(fh)
if err != nil {
return "", err
@ -185,7 +213,10 @@ func ReCrop(filename string, x, y, w, h int) (string, error) {
}
// Crop it.
croppedImg := Crop(img, x, y, w, h)
croppedImg, err := Crop(img, x, y, w, h)
if err != nil {
return "", err
}
// Write it.
err = ToDisk(cropFilename, ext, croppedImg, nil)
@ -209,6 +240,11 @@ func ParseCropCoords(coords string) []int {
}
}
}
// If either the width or height would be zero, the coords aren't valid.
if coords[2] == 0 || coords[3] == 0 {
return nil
}
return crop
}
@ -237,7 +273,8 @@ func ToDisk(filename string, extension string, img image.Image, cfg *UploadConfi
defer fh.Close()
switch extension {
case ".jpg", ".png":
case ".jpg", ".jpe", ".jpeg", ".png":
// NOTE: new uploads enforce .jpg extension always, some legacy pics (.png too) may have slipped thru
jpeg.Encode(fh, img, &jpeg.Options{
Quality: config.JpegQuality,
})

View File

@ -45,7 +45,7 @@
{{if or (not .LoggedIn) .IsPrivate}}
<h2 class="subtitle">is on {{PrettyTitle}}, a social network for nudists &amp; exhibitionists.</h2>
<p>
{{PrettyTitle}} is a new social network for <strong>real</strong> nudists and exhibionists.
{{PrettyTitle}} is a new social network for <strong>real</strong> nudists and exhibitionists.
Join <strong>{{.User.Username}}</strong> and the others on this site by
<a href="/signup"><ins>creating an account</ins></a> and sending them a friend request! Please
see <a href="/"><ins>the home page</ins></a> for all the details.