Merge pull request #13 from celogeek/compute-aspect-ratio

Compute aspect ratio
This commit is contained in:
Celogeek 2023-05-04 19:28:47 +02:00 committed by GitHub
commit d7e311488f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 122 additions and 73 deletions

View File

@ -84,6 +84,12 @@ func (c *Converter) AddIntParam(p *int, name string, value int, usage string) {
c.order = append(c.order, converterOrderName{value: name})
}
// Add an float parameter
func (c *Converter) AddFloatParam(p *float64, name string, value float64, usage string) {
c.Cmd.Float64Var(p, name, value, usage)
c.order = append(c.order, converterOrderName{value: name})
}
// Add a boolean parameter
func (c *Converter) AddBoolParam(p *bool, name string, value bool, usage string) {
c.Cmd.BoolVar(p, name, value, usage)
@ -121,6 +127,7 @@ func (c *Converter) InitParse() {
c.AddStringParam(&c.Options.BackgroundColor, "background-color", c.Options.BackgroundColor, "Background color in hexa format RGB. Black=000, White=FFF, Light Gray=DDD, Dark Gray=777")
c.AddBoolParam(&c.Options.NoResize, "noresize", c.Options.NoResize, "Do not reduce image size if exceed device size")
c.AddStringParam(&c.Options.Format, "format", c.Options.Format, "Format of output images: jpeg (lossy), png (lossless)")
c.AddFloatParam(&c.Options.AspectRatio, "aspect-ratio", c.Options.AspectRatio, "Aspect ratio (height/width) of the output\n -1 = same as device\n 0 = same as source\n1.6 = amazon advice for kindle")
c.AddSection("Default config")
c.AddBoolParam(&c.Options.Show, "show", false, "Show your default parameters")
@ -351,6 +358,11 @@ func (c *Converter) Validate() error {
return errors.New("format should be jpeg or png")
}
// Aspect Ratio
if c.Options.AspectRatio < 0 && c.Options.AspectRatio != -1 {
return errors.New("aspect ratio should be: -1, 0, > 0")
}
return nil
}

View File

@ -43,6 +43,7 @@ type Options struct {
BackgroundColor string `yaml:"background_color"`
NoResize bool `yaml:"noresize"`
Format string `yaml:"format"`
AspectRatio float64 `yaml:"aspect_ratio"`
// Default Config
Show bool `yaml:"-"`
@ -94,6 +95,7 @@ func New() *Options {
BackgroundColor: "FFF",
NoResize: false,
Format: "jpeg",
AspectRatio: 0,
profiles: profiles.New(),
}
}
@ -145,7 +147,7 @@ func (o *Options) LoadConfig() error {
// Get current settings for fields that can be saved
func (o *Options) ShowConfig() string {
var profileDesc, viewDesc string
var profileDesc string
profile := o.GetProfile()
if profile != nil {
profileDesc = fmt.Sprintf(
@ -155,13 +157,6 @@ func (o *Options) ShowConfig() string {
profile.Width,
profile.Height,
)
perfectWidth, perfectHeight := profile.PerfectDim()
viewDesc = fmt.Sprintf(
"%dx%d",
perfectWidth,
perfectHeight,
)
}
sortpathmode := ""
@ -174,6 +169,13 @@ func (o *Options) ShowConfig() string {
sortpathmode = "path=alphanum, file=alphanum"
}
aspectRatio := "auto"
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))
}
var b strings.Builder
for _, v := range []struct {
Key string
@ -181,8 +183,6 @@ func (o *Options) ShowConfig() string {
Condition bool
}{
{"Profile", profileDesc, true},
{"ViewRatio", fmt.Sprintf("1:%s", strings.TrimRight(fmt.Sprintf("%f", profiles.PerfectRatio), "0")), true},
{"View", viewDesc, true},
{"Format", o.Format, true},
{"Quality", o.Quality, o.Format == "jpeg"},
{"Grayscale", o.Grayscale, true},
@ -201,6 +201,7 @@ func (o *Options) ShowConfig() string {
{"Foreground Color", fmt.Sprintf("#%s", o.ForegroundColor), true},
{"Background Color", fmt.Sprintf("#%s", o.BackgroundColor), true},
{"Resize", !o.NoResize, true},
{"Aspect Ratio", aspectRatio, true},
} {
if v.Condition {
b.WriteString(fmt.Sprintf("\n %-26s: %v", v.Key, v.Value))

View File

@ -15,21 +15,6 @@ type Profile struct {
Height int
}
// Recommended ratio of image for perfect rendering Portrait or Landscape.
const PerfectRatio = 1.6
// Compute best dimension based on device size
func (p Profile) PerfectDim() (int, int) {
width, height := float64(p.Width), float64(p.Height)
perfectWidth, perfectHeight := height/PerfectRatio, width*PerfectRatio
if perfectWidth > width {
perfectWidth = width
} else {
perfectHeight = height
}
return int(perfectWidth), int(perfectHeight)
}
type Profiles []Profile
// Initialize list of all supported profiles.

View File

@ -6,6 +6,7 @@ package epub
import (
"archive/zip"
"fmt"
"math"
"os"
"path/filepath"
"regexp"
@ -193,6 +194,52 @@ func (e *ePub) getTree(images []*epubimage.Image, skip_files bool) string {
return c.WriteString("")
}
func (e *ePub) computeAspectRatio(epubParts []*epubPart) float64 {
var (
bestAspectRatio float64
bestAspectRatioCount int
aspectRatio = map[float64]int{}
)
trunc := func(v float64) float64 {
return float64(math.Round(v*10000)) / 10000
}
for _, p := range epubParts {
aspectRatio[trunc(p.Cover.OriginalAspectRatio)]++
for _, i := range p.Images {
aspectRatio[trunc(i.OriginalAspectRatio)]++
}
}
for k, v := range aspectRatio {
if v > bestAspectRatioCount {
bestAspectRatio, bestAspectRatioCount = k, v
}
}
return bestAspectRatio
}
func (e *ePub) computeViewPort(epubParts []*epubPart) {
if e.Image.View.AspectRatio == -1 {
return //keep device size
}
// readjusting view port
bestAspectRatio := e.Image.View.AspectRatio
if bestAspectRatio == 0 {
bestAspectRatio = e.computeAspectRatio(epubParts)
}
viewWidth, viewHeight := int(float64(e.Image.View.Height)/bestAspectRatio), int(float64(e.Image.View.Width)*bestAspectRatio)
if viewWidth > e.Image.View.Width {
e.Image.View.Height = viewHeight
} else {
e.Image.View.Width = viewWidth
}
}
// create the zip
func (e *ePub) Write() error {
type zipContent struct {
@ -231,6 +278,7 @@ func (e *ePub) Write() error {
Quiet: e.Quiet,
})
e.computeViewPort(epubParts)
for i, part := range epubParts {
ext := filepath.Ext(e.Output)
suffix := ""

View File

@ -22,6 +22,7 @@ type Image struct {
Name string
Position string
Format string
OriginalAspectRatio float64
}
// key name of the blank plage after the image

View File

@ -96,6 +96,7 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) {
Path: input.Path,
Name: input.Name,
Format: e.Image.Format,
OriginalAspectRatio: float64(src.Bounds().Dy()) / float64(src.Bounds().Dx()),
}
if err = imgStorage.Add(img.EPUBImgPath(), dst, e.Image.Quality); err != nil {

View File

@ -16,6 +16,7 @@ type Color struct {
type View struct {
Width, Height int
AspectRatio float64
Color Color
}

View File

@ -99,7 +99,6 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s
fmt.Fprintln(os.Stderr, cmd.Options)
profile := cmd.Options.GetProfile()
perfectWidth, perfectHeight := profile.PerfectDim()
if err := epub.New(&epuboptions.Options{
Input: cmd.Options.Input,
@ -131,8 +130,9 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s
Manga: cmd.Options.Manga,
HasCover: cmd.Options.HasCover,
View: &epuboptions.View{
Width: perfectWidth,
Height: perfectHeight,
Width: profile.Width,
Height: profile.Height,
AspectRatio: cmd.Options.AspectRatio,
Color: epuboptions.Color{
Foreground: cmd.Options.ForegroundColor,
Background: cmd.Options.BackgroundColor,