photomator/convert.go
2024-06-10 22:19:30 +02:00

107 lines
2.3 KiB
Go

package main
import (
"bufio"
"fmt"
"image"
"io/fs"
"os"
"slices"
"strings"
"sync"
"fyne.io/fyne/v2/data/binding"
"github.com/disintegration/imaging"
"github.com/pixiv/go-libwebp/webp"
"github.com/rwcarlsen/goexif/tiff"
"golang.org/x/image/draw"
)
func convertRange(inputPath, outputPath string, files []fs.DirEntry, threads, mod int, progress binding.Float, unconverted binding.StringList, wg *sync.WaitGroup) {
defer wg.Done()
for i, file := range files {
if i%threads == mod {
if err := convert(inputPath, outputPath, file); err != nil {
unconverted.Append(file.Name())
}
p, _ := progress.Get()
progress.Set((p*float64(len(files)) + 1) / float64(len(files)))
}
}
}
func convert(inputPath, outputPath string, file fs.DirEntry) error {
name := file.Name()
parts := strings.Split(name, ".")
ext := strings.ToLower(parts[len(parts)-1])
if !file.Type().IsRegular() || !slices.Contains(supported, ext) {
return fmt.Errorf("file type %s is not supported", ext)
}
img, orientation, err := ReadIMG(fmt.Sprintf("%s/%s", inputPath, name))
if err != nil {
return err
}
dest, err := rotate(scale(img), orientation)
if err != nil {
return err
}
io, err := os.Create(fmt.Sprintf("%s/%swebp", outputPath, strings.TrimSuffix(name, ext)))
if err != nil {
return err
}
wr := bufio.NewWriter(io)
defer func() {
wr.Flush()
io.Close()
}()
config, err := webp.ConfigPreset(webp.PresetDefault, 75)
if err != nil {
return err
}
config.SetAlphaQuality(100)
config.SetMethod(4)
config.SetSegments(4)
config.SetSNSStrength(50)
config.SetFilterStrength(60)
config.SetFilterSharpness(0)
err = webp.EncodeRGBA(wr, dest, config)
if err != nil {
return err
}
return nil
}
func scale(img image.Image) (dest *image.NRGBA) {
b := img.Bounds()
factor := float32(b.Max.X) / float32(b.Max.Y)
dest = image.NewNRGBA(image.Rect(0, 0, int(factor*1440), 1440))
draw.ApproxBiLinear.Scale(dest, dest.Rect, img, b, draw.Over, nil)
return dest
}
func rotate(img image.Image, orientation *tiff.Tag) (dest *image.NRGBA, err error) {
rotate, err := orientation.Int(0)
if err != nil {
return nil, err
}
switch rotate {
case 3:
dest = imaging.Rotate180(img)
case 6:
dest = imaging.Rotate270(img)
case 8:
dest = imaging.Rotate90(img)
}
return dest, nil
}