From 96c7d761eeeb93336845b881cde5b784e62f6f33 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Fri, 30 Dec 2022 18:20:38 +0100 Subject: [PATCH] add algo for RGB to GrayScale --- README.md | 2 ++ internal/epub/core.go | 1 + internal/epub/image_processing.go | 1 + internal/image-converter/core.go | 49 +++++++++++++++++++++++++++---- main.go | 17 +++++++++++ 5 files changed, 64 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index b8a6faf..f051139 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,8 @@ The ePub include as a first page: # go-comic-converter -h Usage of go-comic-converter: + -algo string + Algo for RGB to Grayscale: luster, default, mean, luma (default "default") -author string Author of the epub (default "GO Comic Converter") -input string diff --git a/internal/epub/core.go b/internal/epub/core.go index 4ae536d..b743997 100644 --- a/internal/epub/core.go +++ b/internal/epub/core.go @@ -15,6 +15,7 @@ type ImageOptions struct { ViewWidth int ViewHeight int Quality int + Algo string } type EpubOptions struct { diff --git a/internal/epub/image_processing.go b/internal/epub/image_processing.go index 1ba839e..acdf2be 100644 --- a/internal/epub/image_processing.go +++ b/internal/epub/image_processing.go @@ -80,6 +80,7 @@ func LoadImages(path string, options *ImageOptions) ([]*Image, error) { options.ViewWidth, options.ViewHeight, options.Quality, + options.Algo, ) name := fmt.Sprintf("OEBPS/Images/%d.jpg", img.Id) if img.Id == 0 { diff --git a/internal/image-converter/core.go b/internal/image-converter/core.go index 1f29388..453172b 100644 --- a/internal/image-converter/core.go +++ b/internal/image-converter/core.go @@ -6,11 +6,50 @@ import ( "image/color" "image/jpeg" "io" + "sort" "golang.org/x/image/draw" ) -func Load(reader io.ReadCloser) *image.Gray { +var AlgoGray = map[string]func(color.Color) color.Color{ + "default": func(c color.Color) color.Color { + return color.GrayModel.Convert(c) + }, + "mean": func(c color.Color) color.Color { + r, g, b, _ := c.RGBA() + y := float64(r+g+b) / 3 * (255.0 / 65535) + return color.Gray{uint8(y)} + }, + "luma": func(c color.Color) color.Color { + r, g, b, _ := c.RGBA() + y := (0.2126*float64(r) + 0.7152*float64(g) + 0.0722*float64(b)) * (255.0 / 65535) + return color.Gray{uint8(y)} + }, + "luster": func(c color.Color) color.Color { + r, g, b, _ := c.RGBA() + arr := []float64{float64(r), float64(g), float64(b)} + sort.Float64s(arr) + y := (arr[0] + arr[2]) / 2 * (255.0 / 65535) + return color.Gray{uint8(y)} + }, +} + +func toGray(img image.Image, algo string) *image.Gray { + grayImg := image.NewGray(img.Bounds()) + algoConv, ok := AlgoGray[algo] + if !ok { + panic("wrong gray algo") + } + + for y := img.Bounds().Min.Y; y < img.Bounds().Max.Y; y++ { + for x := img.Bounds().Min.X; x < img.Bounds().Max.X; x++ { + grayImg.Set(x, y, algoConv(img.At(x, y))) + } + } + return grayImg +} + +func Load(reader io.ReadCloser, algo string) *image.Gray { defer reader.Close() img, _, err := image.Decode(reader) if err != nil { @@ -21,9 +60,7 @@ func Load(reader io.ReadCloser) *image.Gray { case *image.Gray: return imgt default: - newImg := image.NewGray(img.Bounds()) - draw.Draw(newImg, newImg.Bounds(), img, image.Point{}, draw.Src) - return newImg + return toGray(img, algo) } } @@ -120,8 +157,8 @@ func Get(img *image.Gray, quality int) []byte { return b.Bytes() } -func Convert(reader io.ReadCloser, crop bool, w, h int, quality int) ([]byte, int, int) { - img := Load(reader) +func Convert(reader io.ReadCloser, crop bool, w, h int, quality int, algo string) ([]byte, int, int) { + img := Load(reader, algo) if crop { img = CropMarging(img) } diff --git a/main.go b/main.go index 92abbcd..dbd3ceb 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,8 @@ import ( "path/filepath" "strings" + imageconverter "github.com/celogeek/go-comic-converter/internal/image-converter" + "github.com/celogeek/go-comic-converter/internal/epub" ) @@ -61,6 +63,7 @@ type Option struct { Title string Quality int NoCrop bool + Algo string LimitMb int } @@ -88,6 +91,7 @@ Options: Title : %s Quality : %d Crop : %v + AlgoGray: %s LimitMb : %s `, o.Input, @@ -100,6 +104,7 @@ Options: o.Title, o.Quality, !o.NoCrop, + o.Algo, limitmb, ) } @@ -114,6 +119,10 @@ func main() { p.Description, )) } + availableAlgo := make([]string, 0) + for a := range imageconverter.AlgoGray { + availableAlgo = append(availableAlgo, a) + } opt := &Option{} flag.StringVar(&opt.Input, "input", "", "Source of comic to convert: directory, cbz, zip, cbr, rar, pdf") @@ -123,6 +132,7 @@ func main() { flag.StringVar(&opt.Title, "title", "", "Title of the epub") flag.IntVar(&opt.Quality, "quality", 85, "Quality of the image") flag.BoolVar(&opt.NoCrop, "nocrop", false, "Disable cropping") + flag.StringVar(&opt.Algo, "algo", "default", fmt.Sprintf("Algo for RGB to Grayscale: %s", strings.Join(availableAlgo, ", "))) flag.IntVar(&opt.LimitMb, "limitmb", 0, "Limit size of the ePub: Default nolimit (0), Minimum 20") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage of %s:\n", filepath.Base(os.Args[0])) @@ -192,6 +202,12 @@ func main() { opt.Title = filepath.Base(defaultOutput[0 : len(defaultOutput)-len(ext)]) } + if _, ok := imageconverter.AlgoGray[opt.Algo]; !ok { + fmt.Fprintln(os.Stderr, "algo doesn't exists") + flag.Usage() + os.Exit(1) + } + fmt.Fprintln(os.Stderr, opt) if err := epub.NewEpub(&epub.EpubOptions{ @@ -205,6 +221,7 @@ func main() { ViewHeight: profile.Height, Quality: opt.Quality, Crop: !opt.NoCrop, + Algo: opt.Algo, }, }).Write(); err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err)