mirror of
				https://gitcode.com/gitea/gitea.git
				synced 2025-11-01 01:36:12 +08:00 
			
		
		
		
	 a8fd76557b
			
		
	
	a8fd76557b
	
	
	
		
			
			This PR fixes the builtin avatar generator. 1. The random background color makes some images very dirty. So now we only use white background for avatars. 2. We use left-right mirror avatars to satisfy #14799 3. Fix a small padding error in the algorithm
		
			
				
	
	
		
			86 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			86 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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.
 | |
| 
 | |
| package avatar
 | |
| 
 | |
| import (
 | |
| 	"bytes"
 | |
| 	"fmt"
 | |
| 	"image"
 | |
| 	"image/color"
 | |
| 
 | |
| 	_ "image/gif"  // for processing gif images
 | |
| 	_ "image/jpeg" // for processing jpeg images
 | |
| 	_ "image/png"  // for processing png images
 | |
| 
 | |
| 	"code.gitea.io/gitea/modules/avatar/identicon"
 | |
| 	"code.gitea.io/gitea/modules/setting"
 | |
| 
 | |
| 	"github.com/nfnt/resize"
 | |
| 	"github.com/oliamb/cutter"
 | |
| )
 | |
| 
 | |
| // AvatarSize returns avatar's size
 | |
| const AvatarSize = 290
 | |
| 
 | |
| // RandomImageSize generates and returns a random avatar image unique to input data
 | |
| // in custom size (height and width).
 | |
| func RandomImageSize(size int, data []byte) (image.Image, error) {
 | |
| 	// we use white as background, and use dark colors to draw blocks
 | |
| 	imgMaker, err := identicon.New(size, color.White, identicon.DarkColors...)
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("identicon.New: %v", err)
 | |
| 	}
 | |
| 	return imgMaker.Make(data), nil
 | |
| }
 | |
| 
 | |
| // RandomImage generates and returns a random avatar image unique to input data
 | |
| // in default size (height and width).
 | |
| func RandomImage(data []byte) (image.Image, error) {
 | |
| 	return RandomImageSize(AvatarSize, data)
 | |
| }
 | |
| 
 | |
| // 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)
 | |
| 	}
 | |
| 	if imgCfg.Width > setting.Avatar.MaxWidth {
 | |
| 		return nil, fmt.Errorf("Image width is too large: %d > %d", imgCfg.Width, setting.Avatar.MaxWidth)
 | |
| 	}
 | |
| 	if imgCfg.Height > setting.Avatar.MaxHeight {
 | |
| 		return nil, fmt.Errorf("Image height is too large: %d > %d", imgCfg.Height, setting.Avatar.MaxHeight)
 | |
| 	}
 | |
| 
 | |
| 	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
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	img = resize.Resize(AvatarSize, AvatarSize, img, resize.Bilinear)
 | |
| 	return &img, nil
 | |
| }
 |