github.com/cozy/cozy-stack@v0.0.0-20240603063001-31110fa4cae1/pkg/avatar/initials_convert.go (about) 1 package avatar 2 3 import ( 4 "bytes" 5 "fmt" 6 "os" 7 "os/exec" 8 9 "github.com/cozy/cozy-stack/pkg/logger" 10 ) 11 12 // PNGInitials create PNG avatars with initials in it. 13 // 14 // This implementation is based on the `convert` binary. 15 type PNGInitials struct { 16 cmd string 17 } 18 19 // NewPNGInitials instantiate a new [PNGInitials]. 20 func NewPNGInitials(cmd string) *PNGInitials { 21 if cmd == "" { 22 cmd = "convert" 23 } 24 return &PNGInitials{cmd} 25 } 26 27 // ContentType return the generated avatar content-type. 28 func (a *PNGInitials) ContentType() string { 29 return "image/png" 30 } 31 32 // Generate will create a new avatar with the given initials and color. 33 func (a *PNGInitials) Generate(initials, color string) ([]byte, error) { 34 tempDir, err := os.MkdirTemp("", "magick") 35 if err != nil { 36 return nil, fmt.Errorf("failed to create the tempdir: %w", err) 37 } 38 defer os.RemoveAll(tempDir) 39 envTempDir := fmt.Sprintf("MAGICK_TEMPORARY_PATH=%s", tempDir) 40 env := []string{envTempDir} 41 42 // convert -size 128x128 null: -fill blue -draw 'circle 64,64 0,64' -fill white -font Lato-Regular 43 // -pointsize 64 -gravity center -annotate "+0,+0" "AM" foo.png 44 args := []string{ 45 "-limit", "Memory", "1GB", 46 "-limit", "Map", "1GB", 47 // Use a transparent background 48 "-size", "128x128", 49 "null:", 50 // Add a cicle of color 51 "-fill", color, 52 "-draw", "circle 64,64 0,64", 53 // Add the initials 54 "-fill", "white", 55 "-font", "Lato-Regular", 56 "-pointsize", "64", 57 "-gravity", "center", 58 "-annotate", "+0,+0", 59 initials, 60 // Use the colorspace recommended for web, sRGB 61 "-colorspace", "sRGB", 62 // Send the output on stdout, in PNG format 63 "png:-", 64 } 65 66 var stdout, stderr bytes.Buffer 67 cmd := exec.Command(a.cmd, args...) 68 cmd.Env = env 69 cmd.Stdout = &stdout 70 cmd.Stderr = &stderr 71 if err := cmd.Run(); err != nil { 72 logger.WithNamespace("initials"). 73 WithField("stderr", stderr.String()). 74 WithField("initials", initials). 75 WithField("color", color). 76 Errorf("imagemagick failed: %s", err) 77 return nil, fmt.Errorf("failed to run the cmd %q: %w", a.cmd, err) 78 } 79 return stdout.Bytes(), nil 80 }