2014-03-23 14:13:23 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
2014-03-23 08:24:09 +04:00
package avatar
import (
2019-05-25 14:46:14 +03:00
"bytes"
2014-03-23 08:24:09 +04:00
"fmt"
2014-03-23 11:55:27 +04:00
"image"
2021-11-19 20:10:41 +03:00
"image/color"
2020-10-14 16:07:51 +03:00
2021-06-05 15:32:19 +03:00
_ "image/gif" // for processing gif images
_ "image/jpeg" // for processing jpeg images
_ "image/png" // for processing png images
2014-03-23 11:55:27 +04:00
2021-11-19 20:10:41 +03:00
"code.gitea.io/gitea/modules/avatar/identicon"
2019-05-25 14:46:14 +03:00
"code.gitea.io/gitea/modules/setting"
"github.com/nfnt/resize"
"github.com/oliamb/cutter"
2014-03-23 08:24:09 +04:00
)
2016-11-25 11:37:04 +03:00
// AvatarSize returns avatar's size
const AvatarSize = 290
2015-08-09 06:46:10 +03:00
2016-11-25 11:37:04 +03:00
// RandomImageSize generates and returns a random avatar image unique to input data
2016-02-21 01:10:05 +03:00
// in custom size (height and width).
2016-02-15 07:14:55 +03:00
func RandomImageSize ( size int , data [ ] byte ) ( image . Image , error ) {
2021-11-19 20:10:41 +03:00
// we use white as background, and use dark colors to draw blocks
imgMaker , err := identicon . New ( size , color . White , identicon . DarkColors ... )
2015-08-09 06:46:10 +03:00
if err != nil {
2016-02-15 07:14:55 +03:00
return nil , fmt . Errorf ( "identicon.New: %v" , err )
2015-08-09 06:46:10 +03:00
}
return imgMaker . Make ( data ) , nil
}
2016-02-21 01:10:05 +03:00
// RandomImage generates and returns a random avatar image unique to input data
// in default size (height and width).
2016-02-15 07:14:55 +03:00
func RandomImage ( data [ ] byte ) ( image . Image , error ) {
2016-11-25 11:37:04 +03:00
return RandomImageSize ( AvatarSize , data )
2014-03-23 08:24:09 +04:00
}
2019-05-25 14:46:14 +03:00
// Prepare accepts a byte slice as input, validates it contains an image of an
// acceptable format, and crops and resizes it appropriately.
func Prepare ( data [ ] byte ) ( * image . Image , error ) {
imgCfg , _ , err := image . DecodeConfig ( bytes . NewReader ( data ) )
if err != nil {
return nil , fmt . Errorf ( "DecodeConfig: %v" , err )
}
2020-10-14 16:07:51 +03:00
if imgCfg . Width > setting . Avatar . MaxWidth {
return nil , fmt . Errorf ( "Image width is too large: %d > %d" , imgCfg . Width , setting . Avatar . MaxWidth )
2019-05-25 14:46:14 +03:00
}
2020-10-14 16:07:51 +03:00
if imgCfg . Height > setting . Avatar . MaxHeight {
return nil , fmt . Errorf ( "Image height is too large: %d > %d" , imgCfg . Height , setting . Avatar . MaxHeight )
2019-05-25 14:46:14 +03:00
}
img , _ , err := image . Decode ( bytes . NewReader ( data ) )
if err != nil {
return nil , fmt . Errorf ( "Decode: %v" , err )
}
if imgCfg . Width != imgCfg . Height {
var newSize , ax , ay int
if imgCfg . Width > imgCfg . Height {
newSize = imgCfg . Height
ax = ( imgCfg . Width - imgCfg . Height ) / 2
} else {
newSize = imgCfg . Width
ay = ( imgCfg . Height - imgCfg . Width ) / 2
}
img , err = cutter . Crop ( img , cutter . Config {
Width : newSize ,
Height : newSize ,
Anchor : image . Point { ax , ay } ,
} )
if err != nil {
return nil , err
}
}
2020-09-06 22:53:33 +03:00
img = resize . Resize ( AvatarSize , AvatarSize , img , resize . Bilinear )
2019-05-25 14:46:14 +03:00
return & img , nil
}