From ee466f287273654c2ebe28a08e0352b67d29006e Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sat, 27 Apr 2024 17:55:58 +0200 Subject: [PATCH 01/11] update deps --- go.mod | 8 ++++---- go.sum | 14 ++++++++------ 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index c758477..893f94f 100644 --- a/go.mod +++ b/go.mod @@ -22,8 +22,8 @@ require ( github.com/hashicorp/go-version v1.6.0 // indirect github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect github.com/rivo/uniseg v0.4.7 // indirect - github.com/stretchr/testify v1.8.4 // indirect - golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.17.0 // indirect - golang.org/x/term v0.17.0 // indirect + github.com/stretchr/testify v1.9.0 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/term v0.19.0 // indirect ) diff --git a/go.sum b/go.sum index d2e2dde..e443d1d 100644 --- a/go.sum +++ b/go.sum @@ -35,19 +35,21 @@ github.com/schollz/progressbar/v3 v3.14.2 h1:EducH6uNLIWsr560zSV1KrTeUb/wZGAHqyM github.com/schollz/progressbar/v3 v3.14.2/go.mod h1:aQAZQnhF4JGFtRJiw/eobaXpsqpVQAftEQ+hLGXaRc4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e h1:IWllFTiDjjLIf2oeKxpIUmtiDV5sn71VgeQgg6vcE7k= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e/go.mod h1:d7u6HkTYKSv5m6MCKkOQlHwaShTMl3HjqSGW3XtVhXM= golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8= golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= +golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q= +golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= From c75c58dede4ee90a41be818159a0af644e1017c5 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sat, 27 Apr 2024 17:57:49 +0200 Subject: [PATCH 02/11] add crop limit option --- internal/converter/converter.go | 1 + .../converter/options/converter_options.go | 7 ++- .../epub_image_filters_autocrop.go | 14 +++--- .../imageprocessor/epub_image_processor.go | 4 +- internal/epub/options/epub_options.go | 1 + main.go | 43 +++++++++++++------ 6 files changed, 47 insertions(+), 23 deletions(-) diff --git a/internal/converter/converter.go b/internal/converter/converter.go index 83c0b07..c45d791 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -113,6 +113,7 @@ func (c *Converter) InitParse() { c.AddIntParam(&c.Options.CropRatioUp, "crop-ratio-up", c.Options.CropRatioUp, "Crop ratio up: ratio of pixels allow to be non blank while cutting on the top.") c.AddIntParam(&c.Options.CropRatioRight, "crop-ratio-right", c.Options.CropRatioRight, "Crop ratio right: ratio of pixels allow to be non blank while cutting on the right.") c.AddIntParam(&c.Options.CropRatioBottom, "crop-ratio-bottom", c.Options.CropRatioBottom, "Crop ratio bottom: ratio of pixels allow to be non blank while cutting on the bottom.") + c.AddIntParam(&c.Options.CropLimit, "crop-limit", c.Options.CropLimit, "Crop limit: maximum number of pixel to crop on all side. 0 mean unlimited.") c.AddIntParam(&c.Options.Brightness, "brightness", c.Options.Brightness, "Brightness readjustment: between -100 and 100, > 0 lighter, < 0 darker") c.AddIntParam(&c.Options.Contrast, "contrast", c.Options.Contrast, "Contrast readjustment: between -100 and 100, > 0 more contrast, < 0 less contrast") c.AddBoolParam(&c.Options.AutoContrast, "autocontrast", c.Options.AutoContrast, "Improve contrast automatically") diff --git a/internal/converter/options/converter_options.go b/internal/converter/options/converter_options.go index fc7daaf..9e18f17 100644 --- a/internal/converter/options/converter_options.go +++ b/internal/converter/options/converter_options.go @@ -8,8 +8,9 @@ import ( "path/filepath" "strings" - "github.com/celogeek/go-comic-converter/v2/internal/converter/profiles" "gopkg.in/yaml.v3" + + "github.com/celogeek/go-comic-converter/v2/internal/converter/profiles" ) type Options struct { @@ -29,6 +30,7 @@ type Options struct { CropRatioUp int `yaml:"crop_ratio_up"` CropRatioRight int `yaml:"crop_ratio_right"` CropRatioBottom int `yaml:"crop_ratio_bottom"` + CropLimit int `yaml:"crop_limit"` Brightness int `yaml:"brightness"` Contrast int `yaml:"contrast"` AutoContrast bool `yaml:"auto_contrast"` @@ -161,6 +163,7 @@ func (o *Options) MarshalJSON() ([]byte, error) { "up": o.CropRatioUp, "bottom": o.CropRatioBottom, } + out["crop_limit"] = o.CropLimit } if o.Brightness != 0 { out["brightness"] = o.Brightness @@ -265,7 +268,7 @@ func (o *Options) ShowConfig() string { {"Grayscale", o.Grayscale, true}, {"Grayscale mode", grayscaleMode, o.Grayscale}, {"Crop", o.Crop, true}, - {"Crop ratio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom), o.Crop}, + {"Crop ratio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom - %d Limit", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom, o.CropLimit), o.Crop}, {"Brightness", o.Brightness, o.Brightness != 0}, {"Contrast", o.Contrast, o.Contrast != 0}, {"Auto contrast", o.AutoContrast, true}, diff --git a/internal/epub/imagefilters/epub_image_filters_autocrop.go b/internal/epub/imagefilters/epub_image_filters_autocrop.go index e3929fb..8d48de2 100644 --- a/internal/epub/imagefilters/epub_image_filters_autocrop.go +++ b/internal/epub/imagefilters/epub_image_filters_autocrop.go @@ -8,9 +8,9 @@ import ( ) // AutoCrop Lookup for margin and crop -func AutoCrop(img image.Image, bounds image.Rectangle, cutRatioLeft, cutRatioUp, cutRatioRight, cutRatioBottom int) gift.Filter { +func AutoCrop(img image.Image, bounds image.Rectangle, cutRatioLeft, cutRatioUp, cutRatioRight, cutRatioBottom int, limit int) gift.Filter { return gift.Crop( - findMargin(img, bounds, cutRatioOptions{cutRatioLeft, cutRatioUp, cutRatioRight, cutRatioBottom}), + findMargin(img, bounds, cutRatioOptions{cutRatioLeft, cutRatioUp, cutRatioRight, cutRatioBottom}, limit), ) } @@ -25,11 +25,11 @@ type cutRatioOptions struct { Left, Up, Right, Bottom int } -func findMargin(img image.Image, bounds image.Rectangle, cutRatio cutRatioOptions) image.Rectangle { +func findMargin(img image.Image, bounds image.Rectangle, cutRatio cutRatioOptions, limit int) image.Rectangle { imgArea := bounds LEFT: - for x := imgArea.Min.X; x < imgArea.Max.X; x++ { + for x, maxCut := imgArea.Min.X, limit; x < imgArea.Max.X && (limit == 0 || maxCut > 0); x, maxCut = x+1, maxCut-1 { allowNonBlank := imgArea.Dy() * cutRatio.Left / 100 for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ { if !colorIsBlank(img.At(x, y)) { @@ -43,7 +43,7 @@ LEFT: } UP: - for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ { + for y, maxCut := imgArea.Min.Y, limit; y < imgArea.Max.Y && (limit == 0 || maxCut > 0); y, maxCut = y+1, maxCut-1 { allowNonBlank := imgArea.Dx() * cutRatio.Up / 100 for x := imgArea.Min.X; x < imgArea.Max.X; x++ { if !colorIsBlank(img.At(x, y)) { @@ -57,7 +57,7 @@ UP: } RIGHT: - for x := imgArea.Max.X - 1; x >= imgArea.Min.X; x-- { + for x, maxCut := imgArea.Max.X-1, limit; x >= imgArea.Min.X && (limit == 0 || maxCut > 0); x, maxCut = x-1, maxCut-1 { allowNonBlank := imgArea.Dy() * cutRatio.Right / 100 for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ { if !colorIsBlank(img.At(x, y)) { @@ -71,7 +71,7 @@ RIGHT: } BOTTOM: - for y := imgArea.Max.Y - 1; y >= imgArea.Min.Y; y-- { + for y, maxCut := imgArea.Max.Y-1, limit; y >= imgArea.Min.Y && (limit == 0 || maxCut > 0); y, maxCut = y-1, maxCut-1 { allowNonBlank := imgArea.Dx() * cutRatio.Bottom / 100 for x := imgArea.Min.X; x < imgArea.Max.X; x++ { if !colorIsBlank(img.At(x, y)) { diff --git a/internal/epub/imageprocessor/epub_image_processor.go b/internal/epub/imageprocessor/epub_image_processor.go index cfa2385..30db08e 100644 --- a/internal/epub/imageprocessor/epub_image_processor.go +++ b/internal/epub/imageprocessor/epub_image_processor.go @@ -9,12 +9,13 @@ import ( "os" "sync" + "github.com/disintegration/gift" + epubimage "github.com/celogeek/go-comic-converter/v2/internal/epub/image" epubimagefilters "github.com/celogeek/go-comic-converter/v2/internal/epub/imagefilters" epuboptions "github.com/celogeek/go-comic-converter/v2/internal/epub/options" epubprogress "github.com/celogeek/go-comic-converter/v2/internal/epub/progress" epubzip "github.com/celogeek/go-comic-converter/v2/internal/epub/zip" - "github.com/disintegration/gift" ) type EPUBImageProcessor struct { @@ -189,6 +190,7 @@ func (e *EPUBImageProcessor) transformImage(input *task, part int, right bool) * e.Image.Crop.Up, e.Image.Crop.Right, e.Image.Crop.Bottom, + e.Image.Crop.Limit, ) // detect if blank image diff --git a/internal/epub/options/epub_options.go b/internal/epub/options/epub_options.go index 17665dc..041ae43 100644 --- a/internal/epub/options/epub_options.go +++ b/internal/epub/options/epub_options.go @@ -6,6 +6,7 @@ import "fmt" type Crop struct { Enabled bool Left, Up, Right, Bottom int + Limit int } type Color struct { diff --git a/main.go b/main.go index 7ae381d..8be2cd6 100644 --- a/main.go +++ b/main.go @@ -13,10 +13,11 @@ import ( "os" "runtime/debug" + "github.com/tcnksm/go-latest" + "github.com/celogeek/go-comic-converter/v2/internal/converter" "github.com/celogeek/go-comic-converter/v2/internal/epub" epuboptions "github.com/celogeek/go-comic-converter/v2/internal/epub/options" - "github.com/tcnksm/go-latest" ) func main() { @@ -122,18 +123,34 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s Quiet: cmd.Options.Quiet, Json: cmd.Options.Json, Image: &epuboptions.Image{ - Crop: &epuboptions.Crop{Enabled: cmd.Options.Crop, Left: cmd.Options.CropRatioLeft, Up: cmd.Options.CropRatioUp, Right: cmd.Options.CropRatioRight, Bottom: cmd.Options.CropRatioBottom}, - Quality: cmd.Options.Quality, - Brightness: cmd.Options.Brightness, - Contrast: cmd.Options.Contrast, - AutoContrast: cmd.Options.AutoContrast, - AutoRotate: cmd.Options.AutoRotate, - AutoSplitDoublePage: cmd.Options.AutoSplitDoublePage, - KeepDoublePageIfSplit: cmd.Options.KeepDoublePageIfSplit, - NoBlankImage: cmd.Options.NoBlankImage, - Manga: cmd.Options.Manga, - HasCover: cmd.Options.HasCover, - View: &epuboptions.View{Width: profile.Width, Height: profile.Height, AspectRatio: cmd.Options.AspectRatio, PortraitOnly: cmd.Options.PortraitOnly, Color: epuboptions.Color{Foreground: cmd.Options.ForegroundColor, Background: cmd.Options.BackgroundColor}}, + Crop: &epuboptions.Crop{ + Enabled: cmd.Options.Crop, + Left: cmd.Options.CropRatioLeft, + Up: cmd.Options.CropRatioUp, + Right: cmd.Options.CropRatioRight, + Bottom: cmd.Options.CropRatioBottom, + Limit: cmd.Options.CropLimit, + }, + Quality: cmd.Options.Quality, + Brightness: cmd.Options.Brightness, + Contrast: cmd.Options.Contrast, + AutoContrast: cmd.Options.AutoContrast, + AutoRotate: cmd.Options.AutoRotate, + AutoSplitDoublePage: cmd.Options.AutoSplitDoublePage, + KeepDoublePageIfSplit: cmd.Options.KeepDoublePageIfSplit, + NoBlankImage: cmd.Options.NoBlankImage, + Manga: cmd.Options.Manga, + HasCover: cmd.Options.HasCover, + View: &epuboptions.View{ + Width: profile.Width, + Height: profile.Height, + AspectRatio: cmd.Options.AspectRatio, + PortraitOnly: cmd.Options.PortraitOnly, + Color: epuboptions.Color{ + Foreground: cmd.Options.ForegroundColor, + Background: cmd.Options.BackgroundColor, + }, + }, GrayScale: cmd.Options.Grayscale, GrayScaleMode: cmd.Options.GrayscaleMode, Resize: !cmd.Options.NoResize, From 9133493e60afffaf81cef66017c4c69547c6c773 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sun, 28 Apr 2024 17:40:37 +0200 Subject: [PATCH 03/11] use percentage for cropping --- internal/converter/converter.go | 2 +- internal/converter/options/converter_options.go | 2 +- .../epub/imagefilters/epub_image_filters_autocrop.go | 10 ++++++---- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/internal/converter/converter.go b/internal/converter/converter.go index c45d791..0a2be5f 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -113,7 +113,7 @@ func (c *Converter) InitParse() { c.AddIntParam(&c.Options.CropRatioUp, "crop-ratio-up", c.Options.CropRatioUp, "Crop ratio up: ratio of pixels allow to be non blank while cutting on the top.") c.AddIntParam(&c.Options.CropRatioRight, "crop-ratio-right", c.Options.CropRatioRight, "Crop ratio right: ratio of pixels allow to be non blank while cutting on the right.") c.AddIntParam(&c.Options.CropRatioBottom, "crop-ratio-bottom", c.Options.CropRatioBottom, "Crop ratio bottom: ratio of pixels allow to be non blank while cutting on the bottom.") - c.AddIntParam(&c.Options.CropLimit, "crop-limit", c.Options.CropLimit, "Crop limit: maximum number of pixel to crop on all side. 0 mean unlimited.") + c.AddIntParam(&c.Options.CropLimit, "crop-limit", c.Options.CropLimit, "Crop limit: maximum number of cropping in percentage allowed. 0 mean unlimited.") c.AddIntParam(&c.Options.Brightness, "brightness", c.Options.Brightness, "Brightness readjustment: between -100 and 100, > 0 lighter, < 0 darker") c.AddIntParam(&c.Options.Contrast, "contrast", c.Options.Contrast, "Contrast readjustment: between -100 and 100, > 0 more contrast, < 0 less contrast") c.AddBoolParam(&c.Options.AutoContrast, "autocontrast", c.Options.AutoContrast, "Improve contrast automatically") diff --git a/internal/converter/options/converter_options.go b/internal/converter/options/converter_options.go index 9e18f17..e4d8772 100644 --- a/internal/converter/options/converter_options.go +++ b/internal/converter/options/converter_options.go @@ -268,7 +268,7 @@ func (o *Options) ShowConfig() string { {"Grayscale", o.Grayscale, true}, {"Grayscale mode", grayscaleMode, o.Grayscale}, {"Crop", o.Crop, true}, - {"Crop ratio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom - %d Limit", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom, o.CropLimit), o.Crop}, + {"Crop ratio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom - %d%% Limit", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom, o.CropLimit), o.Crop}, {"Brightness", o.Brightness, o.Brightness != 0}, {"Contrast", o.Contrast, o.Contrast != 0}, {"Auto contrast", o.AutoContrast, true}, diff --git a/internal/epub/imagefilters/epub_image_filters_autocrop.go b/internal/epub/imagefilters/epub_image_filters_autocrop.go index 8d48de2..53abf0a 100644 --- a/internal/epub/imagefilters/epub_image_filters_autocrop.go +++ b/internal/epub/imagefilters/epub_image_filters_autocrop.go @@ -28,8 +28,10 @@ type cutRatioOptions struct { func findMargin(img image.Image, bounds image.Rectangle, cutRatio cutRatioOptions, limit int) image.Rectangle { imgArea := bounds + maxCutX, maxCutY := imgArea.Dx()*limit/100, imgArea.Dy()*limit/100 + LEFT: - for x, maxCut := imgArea.Min.X, limit; x < imgArea.Max.X && (limit == 0 || maxCut > 0); x, maxCut = x+1, maxCut-1 { + for x, maxCut := imgArea.Min.X, maxCutX; x < imgArea.Max.X && (maxCutX == 0 || maxCut > 0); x, maxCut = x+1, maxCut-1 { allowNonBlank := imgArea.Dy() * cutRatio.Left / 100 for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ { if !colorIsBlank(img.At(x, y)) { @@ -43,7 +45,7 @@ LEFT: } UP: - for y, maxCut := imgArea.Min.Y, limit; y < imgArea.Max.Y && (limit == 0 || maxCut > 0); y, maxCut = y+1, maxCut-1 { + for y, maxCut := imgArea.Min.Y, maxCutY; y < imgArea.Max.Y && (maxCutY == 0 || maxCut > 0); y, maxCut = y+1, maxCut-1 { allowNonBlank := imgArea.Dx() * cutRatio.Up / 100 for x := imgArea.Min.X; x < imgArea.Max.X; x++ { if !colorIsBlank(img.At(x, y)) { @@ -57,7 +59,7 @@ UP: } RIGHT: - for x, maxCut := imgArea.Max.X-1, limit; x >= imgArea.Min.X && (limit == 0 || maxCut > 0); x, maxCut = x-1, maxCut-1 { + for x, maxCut := imgArea.Max.X-1, maxCutX; x >= imgArea.Min.X && (maxCutX == 0 || maxCut > 0); x, maxCut = x-1, maxCut-1 { allowNonBlank := imgArea.Dy() * cutRatio.Right / 100 for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ { if !colorIsBlank(img.At(x, y)) { @@ -71,7 +73,7 @@ RIGHT: } BOTTOM: - for y, maxCut := imgArea.Max.Y-1, limit; y >= imgArea.Min.Y && (limit == 0 || maxCut > 0); y, maxCut = y-1, maxCut-1 { + for y, maxCut := imgArea.Max.Y-1, maxCutY; y >= imgArea.Min.Y && (maxCutY == 0 || maxCut > 0); y, maxCut = y-1, maxCut-1 { allowNonBlank := imgArea.Dx() * cutRatio.Bottom / 100 for x := imgArea.Min.X; x < imgArea.Max.X; x++ { if !colorIsBlank(img.At(x, y)) { From c500755a4e77f365efca8a957ab96312854b3884 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sun, 28 Apr 2024 17:45:02 +0200 Subject: [PATCH 04/11] add limit to crop limit --- internal/converter/converter.go | 5 +++++ internal/converter/options/converter_options.go | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/converter/converter.go b/internal/converter/converter.go index 0a2be5f..39f6730 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -389,6 +389,11 @@ func (c *Converter) Validate() error { return errors.New("grayscale mode should be 0, 1 or 2") } + // crop + if c.Options.CropLimit < 0 || c.Options.CropLimit > 100 { + return errors.New("crop limit should be between 0 and 100") + } + return nil } diff --git a/internal/converter/options/converter_options.go b/internal/converter/options/converter_options.go index e4d8772..432033b 100644 --- a/internal/converter/options/converter_options.go +++ b/internal/converter/options/converter_options.go @@ -268,7 +268,7 @@ func (o *Options) ShowConfig() string { {"Grayscale", o.Grayscale, true}, {"Grayscale mode", grayscaleMode, o.Grayscale}, {"Crop", o.Crop, true}, - {"Crop ratio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom - %d%% Limit", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom, o.CropLimit), o.Crop}, + {"Crop ratio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom - Limit %d%%", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom, o.CropLimit), o.Crop}, {"Brightness", o.Brightness, o.Brightness != 0}, {"Contrast", o.Contrast, o.Contrast != 0}, {"Auto contrast", o.AutoContrast, true}, From 0dde6e02a48123a194b4d8a84ad17a9a63bc7045 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:28:35 +0200 Subject: [PATCH 05/11] add skip crop if limit reached --- internal/converter/converter.go | 1 + .../converter/options/converter_options.go | 40 ++++++++++--------- .../epub_image_filters_autocrop.go | 28 +++++++++---- .../imageprocessor/epub_image_processor.go | 1 + internal/epub/options/epub_options.go | 1 + main.go | 13 +++--- 6 files changed, 52 insertions(+), 32 deletions(-) diff --git a/internal/converter/converter.go b/internal/converter/converter.go index 39f6730..69db9e0 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -114,6 +114,7 @@ func (c *Converter) InitParse() { c.AddIntParam(&c.Options.CropRatioRight, "crop-ratio-right", c.Options.CropRatioRight, "Crop ratio right: ratio of pixels allow to be non blank while cutting on the right.") c.AddIntParam(&c.Options.CropRatioBottom, "crop-ratio-bottom", c.Options.CropRatioBottom, "Crop ratio bottom: ratio of pixels allow to be non blank while cutting on the bottom.") c.AddIntParam(&c.Options.CropLimit, "crop-limit", c.Options.CropLimit, "Crop limit: maximum number of cropping in percentage allowed. 0 mean unlimited.") + c.AddBoolParam(&c.Options.CropSkipIfLimitReached, "crop-skip-if-limit-reached", c.Options.CropSkipIfLimitReached, "Crop skip if limit reached.") c.AddIntParam(&c.Options.Brightness, "brightness", c.Options.Brightness, "Brightness readjustment: between -100 and 100, > 0 lighter, < 0 darker") c.AddIntParam(&c.Options.Contrast, "contrast", c.Options.Contrast, "Contrast readjustment: between -100 and 100, > 0 more contrast, < 0 less contrast") c.AddBoolParam(&c.Options.AutoContrast, "autocontrast", c.Options.AutoContrast, "Improve contrast automatically") diff --git a/internal/converter/options/converter_options.go b/internal/converter/options/converter_options.go index 432033b..cfd89ec 100644 --- a/internal/converter/options/converter_options.go +++ b/internal/converter/options/converter_options.go @@ -31,6 +31,7 @@ type Options struct { CropRatioRight int `yaml:"crop_ratio_right"` CropRatioBottom int `yaml:"crop_ratio_bottom"` CropLimit int `yaml:"crop_limit"` + CropSkipIfLimitReached bool `yaml:"crop_skip_if_limit_reached"` Brightness int `yaml:"brightness"` Contrast int `yaml:"contrast"` AutoContrast bool `yaml:"auto_contrast"` @@ -81,23 +82,25 @@ type Options struct { // New Initialize default options. func New() *Options { return &Options{ - Profile: "SR", - Quality: 85, - Grayscale: true, - Crop: true, - CropRatioLeft: 1, - CropRatioUp: 1, - CropRatioRight: 1, - CropRatioBottom: 3, - NoBlankImage: true, - HasCover: true, - KeepDoublePageIfSplit: true, - SortPathMode: 1, - ForegroundColor: "000", - BackgroundColor: "FFF", - Format: "jpeg", - TitlePage: 1, - profiles: profiles.New(), + Profile: "SR", + Quality: 85, + Grayscale: true, + Crop: true, + CropRatioLeft: 1, + CropRatioUp: 1, + CropRatioRight: 1, + CropRatioBottom: 3, + CropLimit: 10, + CropSkipIfLimitReached: true, + NoBlankImage: true, + HasCover: true, + KeepDoublePageIfSplit: true, + SortPathMode: 1, + ForegroundColor: "000", + BackgroundColor: "FFF", + Format: "jpeg", + TitlePage: 1, + profiles: profiles.New(), } } @@ -164,6 +167,7 @@ func (o *Options) MarshalJSON() ([]byte, error) { "bottom": o.CropRatioBottom, } out["crop_limit"] = o.CropLimit + out["crop_skip_if_limit_reached"] = o.CropSkipIfLimitReached } if o.Brightness != 0 { out["brightness"] = o.Brightness @@ -268,7 +272,7 @@ func (o *Options) ShowConfig() string { {"Grayscale", o.Grayscale, true}, {"Grayscale mode", grayscaleMode, o.Grayscale}, {"Crop", o.Crop, true}, - {"Crop ratio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom - Limit %d%%", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom, o.CropLimit), o.Crop}, + {"Crop ratio", fmt.Sprintf("%d Left - %d Up - %d Right - %d Bottom - Limit %d%% - Skip %v", o.CropRatioLeft, o.CropRatioUp, o.CropRatioRight, o.CropRatioBottom, o.CropLimit, o.CropSkipIfLimitReached), o.Crop}, {"Brightness", o.Brightness, o.Brightness != 0}, {"Contrast", o.Contrast, o.Contrast != 0}, {"Auto contrast", o.AutoContrast, true}, diff --git a/internal/epub/imagefilters/epub_image_filters_autocrop.go b/internal/epub/imagefilters/epub_image_filters_autocrop.go index 53abf0a..aa51b85 100644 --- a/internal/epub/imagefilters/epub_image_filters_autocrop.go +++ b/internal/epub/imagefilters/epub_image_filters_autocrop.go @@ -8,9 +8,9 @@ import ( ) // AutoCrop Lookup for margin and crop -func AutoCrop(img image.Image, bounds image.Rectangle, cutRatioLeft, cutRatioUp, cutRatioRight, cutRatioBottom int, limit int) gift.Filter { +func AutoCrop(img image.Image, bounds image.Rectangle, cutRatioLeft, cutRatioUp, cutRatioRight, cutRatioBottom int, limit int, skipIfLimitReached bool) gift.Filter { return gift.Crop( - findMargin(img, bounds, cutRatioOptions{cutRatioLeft, cutRatioUp, cutRatioRight, cutRatioBottom}, limit), + findMargin(img, bounds, cutRatioOptions{cutRatioLeft, cutRatioUp, cutRatioRight, cutRatioBottom}, limit, skipIfLimitReached), ) } @@ -25,13 +25,13 @@ type cutRatioOptions struct { Left, Up, Right, Bottom int } -func findMargin(img image.Image, bounds image.Rectangle, cutRatio cutRatioOptions, limit int) image.Rectangle { +func findMargin(img image.Image, bounds image.Rectangle, cutRatio cutRatioOptions, limit int, skipIfLimitReached bool) image.Rectangle { imgArea := bounds - maxCutX, maxCutY := imgArea.Dx()*limit/100, imgArea.Dy()*limit/100 + maxCropX, maxCropY := imgArea.Dx()*limit/100, imgArea.Dy()*limit/100 LEFT: - for x, maxCut := imgArea.Min.X, maxCutX; x < imgArea.Max.X && (maxCutX == 0 || maxCut > 0); x, maxCut = x+1, maxCut-1 { + for x, maxCrop := imgArea.Min.X, maxCropX; x < imgArea.Max.X && (limit == 0 || maxCrop > 0); x, maxCrop = x+1, maxCrop-1 { allowNonBlank := imgArea.Dy() * cutRatio.Left / 100 for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ { if !colorIsBlank(img.At(x, y)) { @@ -42,10 +42,13 @@ LEFT: } } imgArea.Min.X++ + if limit > 0 && maxCrop == 1 && skipIfLimitReached { + return bounds + } } UP: - for y, maxCut := imgArea.Min.Y, maxCutY; y < imgArea.Max.Y && (maxCutY == 0 || maxCut > 0); y, maxCut = y+1, maxCut-1 { + for y, maxCrop := imgArea.Min.Y, maxCropY; y < imgArea.Max.Y && (limit == 0 || maxCrop > 0); y, maxCrop = y+1, maxCrop-1 { allowNonBlank := imgArea.Dx() * cutRatio.Up / 100 for x := imgArea.Min.X; x < imgArea.Max.X; x++ { if !colorIsBlank(img.At(x, y)) { @@ -56,10 +59,13 @@ UP: } } imgArea.Min.Y++ + if limit > 0 && maxCrop == 1 && skipIfLimitReached { + return bounds + } } RIGHT: - for x, maxCut := imgArea.Max.X-1, maxCutX; x >= imgArea.Min.X && (maxCutX == 0 || maxCut > 0); x, maxCut = x-1, maxCut-1 { + for x, maxCrop := imgArea.Max.X-1, maxCropX; x >= imgArea.Min.X && (limit == 0 || maxCrop > 0); x, maxCrop = x-1, maxCrop-1 { allowNonBlank := imgArea.Dy() * cutRatio.Right / 100 for y := imgArea.Min.Y; y < imgArea.Max.Y; y++ { if !colorIsBlank(img.At(x, y)) { @@ -70,10 +76,13 @@ RIGHT: } } imgArea.Max.X-- + if limit > 0 && maxCrop == 1 && skipIfLimitReached { + return bounds + } } BOTTOM: - for y, maxCut := imgArea.Max.Y-1, maxCutY; y >= imgArea.Min.Y && (maxCutY == 0 || maxCut > 0); y, maxCut = y-1, maxCut-1 { + for y, maxCrop := imgArea.Max.Y-1, maxCropY; y >= imgArea.Min.Y && (limit == 0 || maxCrop > 0); y, maxCrop = y-1, maxCrop-1 { allowNonBlank := imgArea.Dx() * cutRatio.Bottom / 100 for x := imgArea.Min.X; x < imgArea.Max.X; x++ { if !colorIsBlank(img.At(x, y)) { @@ -84,6 +93,9 @@ BOTTOM: } } imgArea.Max.Y-- + if limit > 0 && maxCrop == 1 && skipIfLimitReached { + return bounds + } } return imgArea diff --git a/internal/epub/imageprocessor/epub_image_processor.go b/internal/epub/imageprocessor/epub_image_processor.go index 30db08e..a152c2b 100644 --- a/internal/epub/imageprocessor/epub_image_processor.go +++ b/internal/epub/imageprocessor/epub_image_processor.go @@ -191,6 +191,7 @@ func (e *EPUBImageProcessor) transformImage(input *task, part int, right bool) * e.Image.Crop.Right, e.Image.Crop.Bottom, e.Image.Crop.Limit, + e.Image.Crop.SkipIfLimitReached, ) // detect if blank image diff --git a/internal/epub/options/epub_options.go b/internal/epub/options/epub_options.go index 041ae43..6715ee8 100644 --- a/internal/epub/options/epub_options.go +++ b/internal/epub/options/epub_options.go @@ -7,6 +7,7 @@ type Crop struct { Enabled bool Left, Up, Right, Bottom int Limit int + SkipIfLimitReached bool } type Color struct { diff --git a/main.go b/main.go index 8be2cd6..ea6cab9 100644 --- a/main.go +++ b/main.go @@ -124,12 +124,13 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s Json: cmd.Options.Json, Image: &epuboptions.Image{ Crop: &epuboptions.Crop{ - Enabled: cmd.Options.Crop, - Left: cmd.Options.CropRatioLeft, - Up: cmd.Options.CropRatioUp, - Right: cmd.Options.CropRatioRight, - Bottom: cmd.Options.CropRatioBottom, - Limit: cmd.Options.CropLimit, + Enabled: cmd.Options.Crop, + Left: cmd.Options.CropRatioLeft, + Up: cmd.Options.CropRatioUp, + Right: cmd.Options.CropRatioRight, + Bottom: cmd.Options.CropRatioBottom, + Limit: cmd.Options.CropLimit, + SkipIfLimitReached: cmd.Options.CropSkipIfLimitReached, }, Quality: cmd.Options.Quality, Brightness: cmd.Options.Brightness, From f4501753c54792fd76ce88437537f6a0c11ca025 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sun, 28 Apr 2024 19:36:49 +0200 Subject: [PATCH 06/11] factor stderr printing --- internal/converter/converter.go | 14 ++++++------- internal/epub/epub.go | 19 +++++++++--------- .../imageprocessor/epub_image_processor.go | 5 +++-- .../epub_image_processor_loader.go | 10 ++++++---- internal/epub/progress/epub_progress.go | 4 +++- internal/utils/utils.go | 14 +++++++++++++ main.go | 20 +++++++++---------- 7 files changed, 52 insertions(+), 34 deletions(-) create mode 100644 internal/utils/utils.go diff --git a/internal/converter/converter.go b/internal/converter/converter.go index 69db9e0..2c2aac5 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -19,6 +19,7 @@ import ( "time" "github.com/celogeek/go-comic-converter/v2/internal/converter/options" + "github.com/celogeek/go-comic-converter/v2/internal/utils" ) type Converter struct { @@ -44,17 +45,17 @@ func New() *Converter { var cmdOutput strings.Builder cmd.SetOutput(&cmdOutput) cmd.Usage = func() { - fmt.Fprintf(os.Stderr, "Usage of %s:\n", filepath.Base(os.Args[0])) + utils.Printf("Usage of %s:\n", filepath.Base(os.Args[0])) for _, o := range conv.order { switch v := o.(type) { case converterOrderSection: - fmt.Fprintf(os.Stderr, "\n%s:\n", o.Value()) + utils.Printf("\n%s:\n", o.Value()) case converterOrderName: - fmt.Fprintln(os.Stderr, conv.Usage(v.isString, cmd.Lookup(v.Value()))) + utils.Println(conv.Usage(v.isString, cmd.Lookup(v.Value()))) } } if cmdOutput.Len() > 0 { - fmt.Fprintf(os.Stderr, "\nError: %s", cmdOutput.String()) + utils.Printf("\nError: %s", cmdOutput.String()) } } @@ -401,7 +402,7 @@ func (c *Converter) Validate() error { // Fatal Helper to show usage, err and exit 1 func (c *Converter) Fatal(err error) { c.Cmd.Usage() - fmt.Fprintf(os.Stderr, "\nError: %s\n", err) + utils.Printf("\nError: %s\n", err) os.Exit(1) } @@ -420,8 +421,7 @@ func (c *Converter) Stats() { }, }) } else { - fmt.Fprintf( - os.Stderr, + utils.Printf( "Completed in %s, Memory usage %d Mb\n", elapse, mem.Sys/1024/1024, diff --git a/internal/epub/epub.go b/internal/epub/epub.go index ff91ba9..b047476 100644 --- a/internal/epub/epub.go +++ b/internal/epub/epub.go @@ -5,7 +5,6 @@ import ( "archive/zip" "fmt" "math" - "os" "path/filepath" "regexp" "sort" @@ -13,6 +12,8 @@ import ( "text/template" "time" + "github.com/gofrs/uuid" + epubimage "github.com/celogeek/go-comic-converter/v2/internal/epub/image" epubimageprocessor "github.com/celogeek/go-comic-converter/v2/internal/epub/imageprocessor" epuboptions "github.com/celogeek/go-comic-converter/v2/internal/epub/options" @@ -20,7 +21,7 @@ import ( epubtemplates "github.com/celogeek/go-comic-converter/v2/internal/epub/templates" epubtree "github.com/celogeek/go-comic-converter/v2/internal/epub/tree" epubzip "github.com/celogeek/go-comic-converter/v2/internal/epub/zip" - "github.com/gofrs/uuid" + "github.com/celogeek/go-comic-converter/v2/internal/utils" ) type EPub struct { @@ -418,12 +419,12 @@ func (e *EPub) Write() error { if e.Dry { p := epubParts[0] - fmt.Fprintf(os.Stderr, "TOC:\n - %s\n%s\n", e.Title, e.getTree(p.Images, true)) + utils.Printf("TOC:\n - %s\n%s\n", e.Title, e.getTree(p.Images, true)) if e.DryVerbose { if e.Image.HasCover { - fmt.Fprintf(os.Stderr, "Cover:\n%s\n", e.getTree([]*epubimage.Image{p.Cover}, false)) + utils.Printf("Cover:\n%s\n", e.getTree([]*epubimage.Image{p.Cover}, false)) } - fmt.Fprintf(os.Stderr, "Files:\n%s\n", e.getTree(p.Images, false)) + utils.Printf("Files:\n%s\n", e.getTree(p.Images, false)) } return nil } @@ -469,7 +470,7 @@ func (e *EPub) Write() error { } bar.Close() if !e.Json { - fmt.Fprintln(os.Stderr) + utils.Println() } // display corrupted images @@ -477,17 +478,17 @@ func (e *EPub) Write() error { for pId, part := range epubParts { if pId == 0 && e.Image.HasCover && part.Cover.Error != nil { hasError = true - fmt.Fprintf(os.Stderr, "Error on image %s: %v\n", filepath.Join(part.Cover.Path, part.Cover.Name), part.Cover.Error) + utils.Printf("Error on image %s: %v\n", filepath.Join(part.Cover.Path, part.Cover.Name), part.Cover.Error) } for _, img := range part.Images { if img.Part == 0 && img.Error != nil { hasError = true - fmt.Fprintf(os.Stderr, "Error on image %s: %v\n", filepath.Join(img.Path, img.Name), img.Error) + utils.Printf("Error on image %s: %v\n", filepath.Join(img.Path, img.Name), img.Error) } } } if hasError { - fmt.Fprintln(os.Stderr) + utils.Println() } return nil diff --git a/internal/epub/imageprocessor/epub_image_processor.go b/internal/epub/imageprocessor/epub_image_processor.go index a152c2b..2a60eb0 100644 --- a/internal/epub/imageprocessor/epub_image_processor.go +++ b/internal/epub/imageprocessor/epub_image_processor.go @@ -16,6 +16,7 @@ import ( epuboptions "github.com/celogeek/go-comic-converter/v2/internal/epub/options" epubprogress "github.com/celogeek/go-comic-converter/v2/internal/epub/progress" epubzip "github.com/celogeek/go-comic-converter/v2/internal/epub/zip" + "github.com/celogeek/go-comic-converter/v2/internal/utils" ) type EPUBImageProcessor struct { @@ -84,7 +85,7 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) { e.Options.Image.AutoSplitDoublePage && !e.Options.Image.KeepDoublePageIfSplit) { if err = imgStorage.Add(img.EPUBImgPath(), img.Raw, e.Image.Quality); err != nil { bar.Close() - fmt.Fprintf(os.Stderr, "error with %s: %s", input.Name, err) + utils.Printf("error with %s: %s", input.Name, err) os.Exit(1) } // do not keep raw image except for cover @@ -105,7 +106,7 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) { img = e.transformImage(input, i+1, b) if err = imgStorage.Add(img.EPUBImgPath(), img.Raw, e.Image.Quality); err != nil { bar.Close() - fmt.Fprintf(os.Stderr, "error with %s: %s", input.Name, err) + utils.Printf("error with %s: %s", input.Name, err) os.Exit(1) } img.Raw = nil diff --git a/internal/epub/imageprocessor/epub_image_processor_loader.go b/internal/epub/imageprocessor/epub_image_processor_loader.go index c3bc4a0..50a08df 100644 --- a/internal/epub/imageprocessor/epub_image_processor_loader.go +++ b/internal/epub/imageprocessor/epub_image_processor_loader.go @@ -20,12 +20,14 @@ import ( "golang.org/x/image/font/gofont/gomonobold" _ "golang.org/x/image/webp" - "github.com/celogeek/go-comic-converter/v2/internal/sortpath" "github.com/fogleman/gg" "github.com/golang/freetype/truetype" "github.com/nwaples/rardecode/v2" pdfimage "github.com/raff/pdfreader/image" "github.com/raff/pdfreader/pdfread" + + "github.com/celogeek/go-comic-converter/v2/internal/sortpath" + "github.com/celogeek/go-comic-converter/v2/internal/utils" ) type task struct { @@ -315,7 +317,7 @@ func (e *EPUBImageProcessor) loadCbr() (totalImages int, output chan *task, err if isSolid && !e.Dry { r, rerr := rardecode.OpenReader(e.Input) if rerr != nil { - fmt.Fprintf(os.Stderr, "\nerror processing image %s: %s\n", e.Input, rerr) + utils.Printf("\nerror processing image %s: %s\n", e.Input, rerr) os.Exit(1) } defer r.Close() @@ -325,14 +327,14 @@ func (e *EPUBImageProcessor) loadCbr() (totalImages int, output chan *task, err if rerr == io.EOF { break } - fmt.Fprintf(os.Stderr, "\nerror processing image %s: %s\n", f.Name, rerr) + utils.Printf("\nerror processing image %s: %s\n", f.Name, rerr) os.Exit(1) } if i, ok := indexedNames[f.Name]; ok { var b bytes.Buffer _, rerr = io.Copy(&b, r) if rerr != nil { - fmt.Fprintf(os.Stderr, "\nerror processing image %s: %s\n", f.Name, rerr) + utils.Printf("\nerror processing image %s: %s\n", f.Name, rerr) os.Exit(1) } jobs <- &job{i, f.Name, func() (io.ReadCloser, error) { diff --git a/internal/epub/progress/epub_progress.go b/internal/epub/progress/epub_progress.go index 84d5f5c..ab3d2f8 100644 --- a/internal/epub/progress/epub_progress.go +++ b/internal/epub/progress/epub_progress.go @@ -7,6 +7,8 @@ import ( "time" "github.com/schollz/progressbar/v3" + + "github.com/celogeek/go-comic-converter/v2/internal/utils" ) type Options struct { @@ -38,7 +40,7 @@ func New(o Options) EpubProgress { progressbar.OptionSetWriter(os.Stderr), progressbar.OptionThrottle(65*time.Millisecond), progressbar.OptionOnCompletion(func() { - fmt.Fprint(os.Stderr, "\n") + utils.Println() }), progressbar.OptionSetDescription(fmt.Sprintf(fmtDesc, o.CurrentJob, o.TotalJob, o.Description)), progressbar.OptionSetWidth(60), diff --git a/internal/utils/utils.go b/internal/utils/utils.go new file mode 100644 index 0000000..5a55a37 --- /dev/null +++ b/internal/utils/utils.go @@ -0,0 +1,14 @@ +package utils + +import ( + "fmt" + "os" +) + +func Printf(format string, a ...interface{}) { + _, _ = fmt.Fprintf(os.Stderr, format, a...) +} + +func Println(a ...interface{}) { + _, _ = fmt.Fprintln(os.Stderr, a...) +} diff --git a/main.go b/main.go index ea6cab9..346fd8e 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,6 @@ package main import ( "encoding/json" - "fmt" "os" "runtime/debug" @@ -18,6 +17,7 @@ import ( "github.com/celogeek/go-comic-converter/v2/internal/converter" "github.com/celogeek/go-comic-converter/v2/internal/epub" epuboptions "github.com/celogeek/go-comic-converter/v2/internal/epub/options" + "github.com/celogeek/go-comic-converter/v2/internal/utils" ) func main() { @@ -31,7 +31,7 @@ func main() { if cmd.Options.Version { bi, ok := debug.ReadBuildInfo() if !ok { - fmt.Fprintln(os.Stderr, "failed to fetch current version") + utils.Println("failed to fetch current version") os.Exit(1) } @@ -41,12 +41,12 @@ func main() { } v, err := githubTag.Fetch() if err != nil || len(v.Versions) < 1 { - fmt.Fprintln(os.Stderr, "failed to fetch the latest version") + utils.Println("failed to fetch the latest version") os.Exit(1) } latestVersion := v.Versions[0] - fmt.Fprintf(os.Stderr, `go-comic-converter + utils.Printf(`go-comic-converter Path : %s Sum : %s Version : %s @@ -67,8 +67,7 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s if cmd.Options.Save { cmd.Options.SaveConfig() - fmt.Fprintf( - os.Stderr, + utils.Printf( "%s%s\n\nSaving to %s\n", cmd.Options.Header(), cmd.Options.ShowConfig(), @@ -78,14 +77,13 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s } if cmd.Options.Show { - fmt.Fprintln(os.Stderr, cmd.Options.Header(), cmd.Options.ShowConfig()) + utils.Println(cmd.Options.Header(), cmd.Options.ShowConfig()) return } if cmd.Options.Reset { cmd.Options.ResetConfig() - fmt.Fprintf( - os.Stderr, + utils.Printf( "%s%s\n\nReset default to %s\n", cmd.Options.Header(), cmd.Options.ShowConfig(), @@ -103,7 +101,7 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s "type": "options", "data": cmd.Options, }) } else { - fmt.Fprintln(os.Stderr, cmd.Options) + utils.Println(cmd.Options) } profile := cmd.Options.GetProfile() @@ -159,7 +157,7 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s AppleBookCompatibility: cmd.Options.AppleBookCompatibility, }, }).Write(); err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) + utils.Printf("Error: %v\n", err) os.Exit(1) } if !cmd.Options.Dry { From 8233d067eff7aa72edf86d563c6f2dbe4eeced70 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:35:36 +0200 Subject: [PATCH 07/11] handle errors --- internal/converter/converter.go | 4 ++-- internal/converter/options/converter_options.go | 12 +++++++++--- internal/epub/epub.go | 12 +++++++----- .../imagefilters/epub_image_filters_cover_title.go | 2 +- .../epub/imageprocessor/epub_image_processor.go | 12 ++++++------ .../imageprocessor/epub_image_processor_loader.go | 14 ++++++++------ internal/epub/zip/epub_zip_storage_image.go | 2 +- main.go | 10 +++++++--- 8 files changed, 41 insertions(+), 27 deletions(-) diff --git a/internal/converter/converter.go b/internal/converter/converter.go index 2c2aac5..3909416 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -228,7 +228,7 @@ func (c *Converter) isZeroValue(f *flag.Flag, value string) (ok bool, err error) // Parse all parameters func (c *Converter) Parse() { - c.Cmd.Parse(os.Args[1:]) + _ = c.Cmd.Parse(os.Args[1:]) if c.Options.Help { c.Cmd.Usage() os.Exit(0) @@ -413,7 +413,7 @@ func (c *Converter) Stats() { runtime.ReadMemStats(&mem) if c.Options.Json { - json.NewEncoder(os.Stdout).Encode(map[string]any{ + _ = json.NewEncoder(os.Stdout).Encode(map[string]any{ "type": "stats", "data": map[string]any{ "elapse_ms": elapse.Milliseconds(), diff --git a/internal/converter/options/converter_options.go b/internal/converter/options/converter_options.go index cfd89ec..d67a6bd 100644 --- a/internal/converter/options/converter_options.go +++ b/internal/converter/options/converter_options.go @@ -202,7 +202,9 @@ func (o *Options) LoadConfig() error { if err != nil { return nil } - defer f.Close() + defer func(f *os.File) { + _ = f.Close() + }(f) err = yaml.NewDecoder(f).Decode(o) if err != nil && err.Error() != "EOF" { return err @@ -302,7 +304,9 @@ func (o *Options) ShowConfig() string { // ResetConfig reset all settings to default value func (o *Options) ResetConfig() error { - New().SaveConfig() + if err := New().SaveConfig(); err != nil { + return err + } return o.LoadConfig() } @@ -312,7 +316,9 @@ func (o *Options) SaveConfig() error { if err != nil { return err } - defer f.Close() + defer func(f *os.File) { + _ = f.Close() + }(f) return yaml.NewEncoder(f).Encode(o) } diff --git a/internal/epub/epub.go b/internal/epub/epub.go index b047476..2d2ef14 100644 --- a/internal/epub/epub.go +++ b/internal/epub/epub.go @@ -339,7 +339,9 @@ func (e *EPub) writePart(path string, currentPart, totalParts int, part *epubPar if err != nil { return err } - defer wz.Close() + defer func(wz *epubzip.EPUBZip) { + _ = wz.Close() + }(wz) title := e.Title if totalParts > 1 { @@ -429,8 +431,8 @@ func (e *EPub) Write() error { return nil } defer func() { - imgStorage.Close() - imgStorage.Remove() + _ = imgStorage.Close() + _ = imgStorage.Remove() }() totalParts := len(epubParts) @@ -466,9 +468,9 @@ func (e *EPub) Write() error { return err } - bar.Add(1) + _ = bar.Add(1) } - bar.Close() + _ = bar.Close() if !e.Json { utils.Println() } diff --git a/internal/epub/imagefilters/epub_image_filters_cover_title.go b/internal/epub/imagefilters/epub_image_filters_cover_title.go index 678b8e0..7692e91 100644 --- a/internal/epub/imagefilters/epub_image_filters_cover_title.go +++ b/internal/epub/imagefilters/epub_image_filters_cover_title.go @@ -94,5 +94,5 @@ func (p *coverTitle) Draw(dst draw.Image, src image.Image, _ *gift.Options) { textLeft = textArea.Min.X } textTop := textArea.Min.Y + textArea.Dy()/2 + textHeight/4 - c.DrawString(p.title, freetype.Pt(textLeft, textTop)) + _, _ = c.DrawString(p.title, freetype.Pt(textLeft, textTop)) } diff --git a/internal/epub/imageprocessor/epub_image_processor.go b/internal/epub/imageprocessor/epub_image_processor.go index 2a60eb0..12c4943 100644 --- a/internal/epub/imageprocessor/epub_image_processor.go +++ b/internal/epub/imageprocessor/epub_image_processor.go @@ -64,7 +64,7 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) { imgStorage, err := epubzip.NewStorageImageWriter(e.ImgStorage(), e.Image.Format) if err != nil { - bar.Close() + _ = bar.Close() return nil, err } @@ -84,7 +84,7 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) { if !(img.DoublePage && input.Id > 0 && e.Options.Image.AutoSplitDoublePage && !e.Options.Image.KeepDoublePageIfSplit) { if err = imgStorage.Add(img.EPUBImgPath(), img.Raw, e.Image.Quality); err != nil { - bar.Close() + _ = bar.Close() utils.Printf("error with %s: %s", input.Name, err) os.Exit(1) } @@ -105,7 +105,7 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) { for i, b := range []bool{e.Image.Manga, !e.Image.Manga} { img = e.transformImage(input, i+1, b) if err = imgStorage.Add(img.EPUBImgPath(), img.Raw, e.Image.Quality); err != nil { - bar.Close() + _ = bar.Close() utils.Printf("error with %s: %s", input.Name, err) os.Exit(1) } @@ -118,20 +118,20 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) { go func() { wg.Wait() - imgStorage.Close() + _ = imgStorage.Close() close(imageOutput) }() for img := range imageOutput { if img.Part == 0 { - bar.Add(1) + _ = bar.Add(1) } if e.Image.NoBlankImage && img.IsBlank { continue } images = append(images, img) } - bar.Close() + _ = bar.Close() if len(images) == 0 { return nil, errNoImagesFound diff --git a/internal/epub/imageprocessor/epub_image_processor_loader.go b/internal/epub/imageprocessor/epub_image_processor_loader.go index 50a08df..da610f0 100644 --- a/internal/epub/imageprocessor/epub_image_processor_loader.go +++ b/internal/epub/imageprocessor/epub_image_processor_loader.go @@ -155,7 +155,7 @@ func (e *EPUBImageProcessor) loadDir() (totalImages int, output chan *task, err f, err = os.Open(job.Path) if err == nil { img, _, err = image.Decode(f) - f.Close() + _ = f.Close() } } @@ -205,7 +205,7 @@ func (e *EPUBImageProcessor) loadCbz() (totalImages int, output chan *task, err totalImages = len(images) if totalImages == 0 { - r.Close() + _ = r.Close() err = errNoImagesFound return } @@ -248,7 +248,7 @@ func (e *EPUBImageProcessor) loadCbz() (totalImages int, output chan *task, err if err == nil { img, _, err = image.Decode(f) } - f.Close() + _ = f.Close() } p, fn := filepath.Split(filepath.Clean(job.F.Name)) @@ -269,7 +269,7 @@ func (e *EPUBImageProcessor) loadCbz() (totalImages int, output chan *task, err go func() { wg.Wait() close(output) - r.Close() + _ = r.Close() }() return } @@ -320,7 +320,9 @@ func (e *EPUBImageProcessor) loadCbr() (totalImages int, output chan *task, err utils.Printf("\nerror processing image %s: %s\n", e.Input, rerr) os.Exit(1) } - defer r.Close() + defer func(r *rardecode.ReadCloser) { + _ = r.Close() + }(r) for { f, rerr := r.Next() if rerr != nil { @@ -367,7 +369,7 @@ func (e *EPUBImageProcessor) loadCbr() (totalImages int, output chan *task, err if err == nil { img, _, err = image.Decode(f) } - f.Close() + _ = f.Close() } p, fn := filepath.Split(filepath.Clean(job.Name)) diff --git a/internal/epub/zip/epub_zip_storage_image.go b/internal/epub/zip/epub_zip_storage_image.go index 50c3c7f..dd918cd 100644 --- a/internal/epub/zip/epub_zip_storage_image.go +++ b/internal/epub/zip/epub_zip_storage_image.go @@ -25,7 +25,7 @@ func NewStorageImageWriter(filename string, format string) (*StorageImageWriter, func (e *StorageImageWriter) Close() error { if err := e.fz.Close(); err != nil { - e.fh.Close() + _ = e.fh.Close() return err } return e.fh.Close() diff --git a/main.go b/main.go index 346fd8e..0181f87 100644 --- a/main.go +++ b/main.go @@ -66,7 +66,9 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s } if cmd.Options.Save { - cmd.Options.SaveConfig() + if err := cmd.Options.SaveConfig(); err != nil { + cmd.Fatal(err) + } utils.Printf( "%s%s\n\nSaving to %s\n", cmd.Options.Header(), @@ -82,7 +84,9 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s } if cmd.Options.Reset { - cmd.Options.ResetConfig() + if err := cmd.Options.ResetConfig(); err != nil { + cmd.Fatal(err) + } utils.Printf( "%s%s\n\nReset default to %s\n", cmd.Options.Header(), @@ -97,7 +101,7 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s } if cmd.Options.Json { - json.NewEncoder(os.Stdout).Encode(map[string]any{ + _ = json.NewEncoder(os.Stdout).Encode(map[string]any{ "type": "options", "data": cmd.Options, }) } else { From 79e20ca622ccdc78c4268ca2eb17e108425f264d Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:35:48 +0200 Subject: [PATCH 08/11] skip deprecated --- internal/epub/zip/epub_zip.go | 1 + internal/epub/zip/epub_zip_image.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/epub/zip/epub_zip.go b/internal/epub/zip/epub_zip.go index 28e0890..5c32b33 100644 --- a/internal/epub/zip/epub_zip.go +++ b/internal/epub/zip/epub_zip.go @@ -39,6 +39,7 @@ func (e *EPUBZip) Close() error { // This will be valid with epubcheck tools. func (e *EPUBZip) WriteMagic() error { t := time.Now().UTC() + //goland:noinspection GoDeprecation fh := &zip.FileHeader{ Name: "mimetype", Method: zip.Store, diff --git a/internal/epub/zip/epub_zip_image.go b/internal/epub/zip/epub_zip_image.go index ad1f0b4..060cb86 100644 --- a/internal/epub/zip/epub_zip_image.go +++ b/internal/epub/zip/epub_zip_image.go @@ -52,6 +52,7 @@ func CompressImage(filename string, format string, img image.Image, quality int) } t := time.Now() + //goland:noinspection GoDeprecation return &ZipImage{ &zip.FileHeader{ Name: filename, From 5968cbdd0983d096d50293a0a4d877b9204d1d22 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:36:08 +0200 Subject: [PATCH 09/11] sort import --- internal/epub/templates/epub_templates_content.go | 1 + internal/epub/templates/epub_templates_toc.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/epub/templates/epub_templates_content.go b/internal/epub/templates/epub_templates_content.go index 861bf7d..7b3a662 100644 --- a/internal/epub/templates/epub_templates_content.go +++ b/internal/epub/templates/epub_templates_content.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/beevik/etree" + epubimage "github.com/celogeek/go-comic-converter/v2/internal/epub/image" epuboptions "github.com/celogeek/go-comic-converter/v2/internal/epub/options" ) diff --git a/internal/epub/templates/epub_templates_toc.go b/internal/epub/templates/epub_templates_toc.go index f751fca..9df2766 100644 --- a/internal/epub/templates/epub_templates_toc.go +++ b/internal/epub/templates/epub_templates_toc.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/beevik/etree" + epubimage "github.com/celogeek/go-comic-converter/v2/internal/epub/image" ) From cc7a97ad6f5b6fee2a03a4bfa070b3a22463bc29 Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:36:26 +0200 Subject: [PATCH 10/11] handle missing profile --- internal/converter/options/converter_options.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/internal/converter/options/converter_options.go b/internal/converter/options/converter_options.go index d67a6bd..934159c 100644 --- a/internal/converter/options/converter_options.go +++ b/internal/converter/options/converter_options.go @@ -241,7 +241,11 @@ func (o *Options) ShowConfig() string { if o.AspectRatio > 0 { aspectRatio = fmt.Sprintf("1:%.02f", o.AspectRatio) } else if o.AspectRatio < 0 { - aspectRatio = fmt.Sprintf("1:%0.2f (device)", float64(profile.Height)/float64(profile.Width)) + if profile != nil { + aspectRatio = fmt.Sprintf("1:%0.2f (device)", float64(profile.Height)/float64(profile.Width)) + } else { + aspectRatio = "1:?? (device)" + } } titlePage := "" From 7b304149fd03d318c4fcf93ac876ecec1917695c Mon Sep 17 00:00:00 2001 From: celogeek <65178+celogeek@users.noreply.github.com> Date: Sun, 28 Apr 2024 21:36:40 +0200 Subject: [PATCH 11/11] write string directly --- internal/converter/converter.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/converter/converter.go b/internal/converter/converter.go index 3909416..29fd6a0 100644 --- a/internal/converter/converter.go +++ b/internal/converter/converter.go @@ -165,7 +165,7 @@ func (c *Converter) InitParse() { // Usage Customize version of FlagSet.PrintDefaults func (c *Converter) Usage(isString bool, f *flag.Flag) string { var b strings.Builder - fmt.Fprintf(&b, " -%s", f.Name) // Two spaces before -; see next two comments. + b.WriteString(" -" + f.Name) name, usage := flag.UnquoteUsage(f) if len(name) > 0 { b.WriteString(" ") @@ -177,9 +177,9 @@ func (c *Converter) Usage(isString bool, f *flag.Flag) string { c.isZeroValueErrs = append(c.isZeroValueErrs, err) } else if !isZero { if isString { - fmt.Fprintf(&b, " (default %q)", f.DefValue) + b.WriteString(fmt.Sprintf(" (default %q)", f.DefValue)) } else { - fmt.Fprintf(&b, " (default %v)", f.DefValue) + b.WriteString(fmt.Sprintf(" (default %v)", f.DefValue)) } }