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 }