Extract background color to continue image

This commit is contained in:
nemunaire 2024-03-18 11:26:01 +01:00
parent 35d07c1aa4
commit 26c282138e
23 changed files with 218 additions and 115 deletions

View file

@ -397,6 +397,8 @@ func SyncExercice(i Importer, theme *fic.Theme, epath string, dmap *map[int64]*f
e.Image = strings.TrimPrefix(filePath, fic.FilesDir)
e.BackgroundColor, _ = getBackgroundColor(filePath)
// If the theme has no image yet, use the first exercice's image found
theme.Image = e.Image
_, err := theme.Update()

View file

@ -13,6 +13,7 @@ import (
"strings"
"unicode"
"github.com/cenkalti/dominantcolor"
"github.com/gin-gonic/gin"
"github.com/yuin/goldmark"
"go.uber.org/multierr"
@ -86,6 +87,49 @@ func resizePicture(importedPath string, rect image.Rectangle) error {
return nil
}
type SubImager interface {
SubImage(r image.Rectangle) image.Image
}
// getBackgroundColor retrieves the most dominant color in the bottom of the image.
func getBackgroundColor(importedPath string) (uint32, error) {
fl, err := os.Open(strings.TrimSuffix(importedPath, ".jpg") + ".thumb.jpg")
if err != nil {
return 0, err
}
src, _, err := image.Decode(fl)
if err != nil {
fl.Close()
return 0, err
}
bounds := src.Bounds()
// Test if the right and left corner have the same color
bottomLeft := src.(SubImager).SubImage(image.Rect(0, bounds.Dy()-10, 40, bounds.Dy()))
bottomRight := src.(SubImager).SubImage(image.Rect(bounds.Dx()-40, bounds.Dy()-10, bounds.Dx(), bounds.Dy()))
colorLeft := dominantcolor.Find(bottomLeft)
colorRight := dominantcolor.Find(bottomRight)
if uint32(colorLeft.R>>5)<<16+uint32(colorLeft.G>>5)<<8+uint32(colorLeft.B>>5) == uint32(colorRight.R>>5)<<16+uint32(colorRight.G>>5)<<8+uint32(colorRight.B>>5) {
return uint32(colorLeft.R)<<16 + uint32(colorLeft.G)<<8 + uint32(colorLeft.B), nil
}
// Only keep the darkest color of the bottom of the image
bottomFull := src.(SubImager).SubImage(image.Rect(0, bounds.Dy()-5, bounds.Dx(), bounds.Dy()))
colors := dominantcolor.FindN(bottomFull, 4)
color := colors[0]
for _, c := range colors {
if uint32(color.R<<2)+uint32(color.G<<2)+uint32(color.B<<2) > uint32(c.R<<2)+uint32(c.G<<2)+uint32(c.B<<2) {
color = c
}
}
return uint32(color.R)<<16 + uint32(color.G)<<8 + uint32(color.B), nil
}
// getAuthors parses the AUTHORS file.
func getAuthors(i Importer, tname string) ([]string, error) {
if authors, err := GetFileContent(i, path.Join(tname, "AUTHORS.txt")); err != nil {
@ -258,6 +302,7 @@ func SyncThemes(i Importer) (exceptions map[string]*CheckExceptions, errs error)
}
btheme.Image = strings.TrimPrefix(filePath, fic.FilesDir)
btheme.BackgroundColor, _ = getBackgroundColor(filePath)
return nil, nil
}); err != nil {
errs = multierr.Append(errs, NewThemeError(btheme, fmt.Errorf("unable to import heading image: %w", err)))