mirror of
https://github.com/celogeek/go-comic-converter.git
synced 2025-07-06 19:59:57 +02:00
Compare commits
No commits in common. "003a91a07e73c4e143aaa1bda6f3971dc0966020" and "abf3b8facf7d3ce251e941ec4b405e0a925c7e4c" have entirely different histories.
003a91a07e
...
abf3b8facf
@ -84,12 +84,6 @@ func (c *Converter) AddIntParam(p *int, name string, value int, usage string) {
|
|||||||
c.order = append(c.order, converterOrderName{value: name})
|
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
|
// Add a boolean parameter
|
||||||
func (c *Converter) AddBoolParam(p *bool, name string, value bool, usage string) {
|
func (c *Converter) AddBoolParam(p *bool, name string, value bool, usage string) {
|
||||||
c.Cmd.BoolVar(p, name, value, usage)
|
c.Cmd.BoolVar(p, name, value, usage)
|
||||||
@ -127,8 +121,6 @@ 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.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.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.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.AddBoolParam(&c.Options.PortraitOnly, "portrait-only", c.Options.PortraitOnly, "Portrait only: force orientation to portrait only.")
|
|
||||||
|
|
||||||
c.AddSection("Default config")
|
c.AddSection("Default config")
|
||||||
c.AddBoolParam(&c.Options.Show, "show", false, "Show your default parameters")
|
c.AddBoolParam(&c.Options.Show, "show", false, "Show your default parameters")
|
||||||
@ -359,11 +351,6 @@ func (c *Converter) Validate() error {
|
|||||||
return errors.New("format should be jpeg or png")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,30 +21,28 @@ type Options struct {
|
|||||||
Title string `yaml:"-"`
|
Title string `yaml:"-"`
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
Profile string `yaml:"profile"`
|
Profile string `yaml:"profile"`
|
||||||
Quality int `yaml:"quality"`
|
Quality int `yaml:"quality"`
|
||||||
Grayscale bool `yaml:"grayscale"`
|
Grayscale bool `yaml:"grayscale"`
|
||||||
Crop bool `yaml:"crop"`
|
Crop bool `yaml:"crop"`
|
||||||
CropRatioLeft int `yaml:"crop_ratio_left"`
|
CropRatioLeft int `yaml:"crop_ratio_left"`
|
||||||
CropRatioUp int `yaml:"crop_ratio_up"`
|
CropRatioUp int `yaml:"crop_ratio_up"`
|
||||||
CropRatioRight int `yaml:"crop_ratio_right"`
|
CropRatioRight int `yaml:"crop_ratio_right"`
|
||||||
CropRatioBottom int `yaml:"crop_ratio_bottom"`
|
CropRatioBottom int `yaml:"crop_ratio_bottom"`
|
||||||
Brightness int `yaml:"brightness"`
|
Brightness int `yaml:"brightness"`
|
||||||
Contrast int `yaml:"contrast"`
|
Contrast int `yaml:"contrast"`
|
||||||
AutoRotate bool `yaml:"auto_rotate"`
|
AutoRotate bool `yaml:"auto_rotate"`
|
||||||
AutoSplitDoublePage bool `yaml:"auto_split_double_page"`
|
AutoSplitDoublePage bool `yaml:"auto_split_double_page"`
|
||||||
NoBlankImage bool `yaml:"no_blank_image"`
|
NoBlankImage bool `yaml:"no_blank_image"`
|
||||||
Manga bool `yaml:"manga"`
|
Manga bool `yaml:"manga"`
|
||||||
HasCover bool `yaml:"has_cover"`
|
HasCover bool `yaml:"has_cover"`
|
||||||
LimitMb int `yaml:"limit_mb"`
|
LimitMb int `yaml:"limit_mb"`
|
||||||
StripFirstDirectoryFromToc bool `yaml:"strip_first_directory_from_toc"`
|
StripFirstDirectoryFromToc bool `yaml:"strip_first_directory_from_toc"`
|
||||||
SortPathMode int `yaml:"sort_path_mode"`
|
SortPathMode int `yaml:"sort_path_mode"`
|
||||||
ForegroundColor string `yaml:"foreground_color"`
|
ForegroundColor string `yaml:"foreground_color"`
|
||||||
BackgroundColor string `yaml:"background_color"`
|
BackgroundColor string `yaml:"background_color"`
|
||||||
NoResize bool `yaml:"noresize"`
|
NoResize bool `yaml:"noresize"`
|
||||||
Format string `yaml:"format"`
|
Format string `yaml:"format"`
|
||||||
AspectRatio float64 `yaml:"aspect_ratio"`
|
|
||||||
PortraitOnly bool `yaml:"portrait_only"`
|
|
||||||
|
|
||||||
// Default Config
|
// Default Config
|
||||||
Show bool `yaml:"-"`
|
Show bool `yaml:"-"`
|
||||||
@ -74,20 +72,29 @@ type Options struct {
|
|||||||
// Initialize default options.
|
// Initialize default options.
|
||||||
func New() *Options {
|
func New() *Options {
|
||||||
return &Options{
|
return &Options{
|
||||||
Quality: 85,
|
Profile: "",
|
||||||
Grayscale: true,
|
Quality: 85,
|
||||||
Crop: true,
|
Grayscale: true,
|
||||||
CropRatioLeft: 1,
|
Crop: true,
|
||||||
CropRatioUp: 1,
|
CropRatioLeft: 1,
|
||||||
CropRatioRight: 1,
|
CropRatioUp: 1,
|
||||||
CropRatioBottom: 3,
|
CropRatioRight: 1,
|
||||||
NoBlankImage: true,
|
CropRatioBottom: 3,
|
||||||
HasCover: true,
|
Brightness: 0,
|
||||||
SortPathMode: 1,
|
Contrast: 0,
|
||||||
ForegroundColor: "000",
|
AutoRotate: false,
|
||||||
BackgroundColor: "FFF",
|
AutoSplitDoublePage: false,
|
||||||
Format: "jpeg",
|
NoBlankImage: true,
|
||||||
profiles: profiles.New(),
|
Manga: false,
|
||||||
|
HasCover: true,
|
||||||
|
LimitMb: 0,
|
||||||
|
StripFirstDirectoryFromToc: false,
|
||||||
|
SortPathMode: 1,
|
||||||
|
ForegroundColor: "000",
|
||||||
|
BackgroundColor: "FFF",
|
||||||
|
NoResize: false,
|
||||||
|
Format: "jpeg",
|
||||||
|
profiles: profiles.New(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +145,7 @@ func (o *Options) LoadConfig() error {
|
|||||||
|
|
||||||
// Get current settings for fields that can be saved
|
// Get current settings for fields that can be saved
|
||||||
func (o *Options) ShowConfig() string {
|
func (o *Options) ShowConfig() string {
|
||||||
var profileDesc string
|
var profileDesc, viewDesc string
|
||||||
profile := o.GetProfile()
|
profile := o.GetProfile()
|
||||||
if profile != nil {
|
if profile != nil {
|
||||||
profileDesc = fmt.Sprintf(
|
profileDesc = fmt.Sprintf(
|
||||||
@ -148,6 +155,13 @@ func (o *Options) ShowConfig() string {
|
|||||||
profile.Width,
|
profile.Width,
|
||||||
profile.Height,
|
profile.Height,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
perfectWidth, perfectHeight := profile.PerfectDim()
|
||||||
|
viewDesc = fmt.Sprintf(
|
||||||
|
"%dx%d",
|
||||||
|
perfectWidth,
|
||||||
|
perfectHeight,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
sortpathmode := ""
|
sortpathmode := ""
|
||||||
@ -160,13 +174,6 @@ func (o *Options) ShowConfig() string {
|
|||||||
sortpathmode = "path=alphanum, file=alphanum"
|
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
|
var b strings.Builder
|
||||||
for _, v := range []struct {
|
for _, v := range []struct {
|
||||||
Key string
|
Key string
|
||||||
@ -174,6 +181,8 @@ func (o *Options) ShowConfig() string {
|
|||||||
Condition bool
|
Condition bool
|
||||||
}{
|
}{
|
||||||
{"Profile", profileDesc, true},
|
{"Profile", profileDesc, true},
|
||||||
|
{"ViewRatio", fmt.Sprintf("1:%s", strings.TrimRight(fmt.Sprintf("%f", profiles.PerfectRatio), "0")), true},
|
||||||
|
{"View", viewDesc, true},
|
||||||
{"Format", o.Format, true},
|
{"Format", o.Format, true},
|
||||||
{"Quality", o.Quality, o.Format == "jpeg"},
|
{"Quality", o.Quality, o.Format == "jpeg"},
|
||||||
{"Grayscale", o.Grayscale, true},
|
{"Grayscale", o.Grayscale, true},
|
||||||
@ -192,8 +201,6 @@ func (o *Options) ShowConfig() string {
|
|||||||
{"Foreground Color", fmt.Sprintf("#%s", o.ForegroundColor), true},
|
{"Foreground Color", fmt.Sprintf("#%s", o.ForegroundColor), true},
|
||||||
{"Background Color", fmt.Sprintf("#%s", o.BackgroundColor), true},
|
{"Background Color", fmt.Sprintf("#%s", o.BackgroundColor), true},
|
||||||
{"Resize", !o.NoResize, true},
|
{"Resize", !o.NoResize, true},
|
||||||
{"Aspect Ratio", aspectRatio, true},
|
|
||||||
{"Portrait Only", o.PortraitOnly, true},
|
|
||||||
} {
|
} {
|
||||||
if v.Condition {
|
if v.Condition {
|
||||||
b.WriteString(fmt.Sprintf("\n %-26s: %v", v.Key, v.Value))
|
b.WriteString(fmt.Sprintf("\n %-26s: %v", v.Key, v.Value))
|
||||||
|
@ -15,6 +15,21 @@ type Profile struct {
|
|||||||
Height int
|
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
|
type Profiles []Profile
|
||||||
|
|
||||||
// Initialize list of all supported profiles.
|
// Initialize list of all supported profiles.
|
||||||
|
@ -6,7 +6,6 @@ package epub
|
|||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -194,52 +193,6 @@ func (e *ePub) getTree(images []*epubimage.Image, skip_files bool) string {
|
|||||||
return c.WriteString("")
|
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
|
// create the zip
|
||||||
func (e *ePub) Write() error {
|
func (e *ePub) Write() error {
|
||||||
type zipContent struct {
|
type zipContent struct {
|
||||||
@ -278,7 +231,6 @@ func (e *ePub) Write() error {
|
|||||||
Quiet: e.Quiet,
|
Quiet: e.Quiet,
|
||||||
})
|
})
|
||||||
|
|
||||||
e.computeViewPort(epubParts)
|
|
||||||
for i, part := range epubParts {
|
for i, part := range epubParts {
|
||||||
ext := filepath.Ext(e.Output)
|
ext := filepath.Ext(e.Output)
|
||||||
suffix := ""
|
suffix := ""
|
||||||
@ -299,12 +251,9 @@ func (e *ePub) Write() error {
|
|||||||
if totalParts > 1 {
|
if totalParts > 1 {
|
||||||
title = fmt.Sprintf("%s [%d/%d]", title, i+1, totalParts)
|
title = fmt.Sprintf("%s [%d/%d]", title, i+1, totalParts)
|
||||||
}
|
}
|
||||||
titleAlign := ""
|
titleAlign := "left:0"
|
||||||
if !e.Image.View.PortraitOnly {
|
if e.Image.Manga {
|
||||||
titleAlign = "left:0"
|
titleAlign = "right:0"
|
||||||
if e.Image.Manga {
|
|
||||||
titleAlign = "right:0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
content := []zipContent{
|
content := []zipContent{
|
||||||
@ -326,7 +275,10 @@ func (e *ePub) Write() error {
|
|||||||
{"OEBPS/Text/style.css", e.render(epubtemplates.Style, map[string]any{
|
{"OEBPS/Text/style.css", e.render(epubtemplates.Style, map[string]any{
|
||||||
"View": e.Image.View,
|
"View": e.Image.View,
|
||||||
})},
|
})},
|
||||||
|
{"OEBPS/Text/space_title.xhtml", e.render(epubtemplates.Blank, map[string]any{
|
||||||
|
"Title": "Blank Page Title",
|
||||||
|
"ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height),
|
||||||
|
})},
|
||||||
{"OEBPS/Text/title.xhtml", e.render(epubtemplates.Text, map[string]any{
|
{"OEBPS/Text/title.xhtml", e.render(epubtemplates.Text, map[string]any{
|
||||||
"Title": title,
|
"Title": title,
|
||||||
"ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height),
|
"ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height),
|
||||||
@ -334,14 +286,6 @@ func (e *ePub) Write() error {
|
|||||||
"ImageStyle": part.Cover.ImgStyle(e.Image.View.Width, e.Image.View.Height, titleAlign),
|
"ImageStyle": part.Cover.ImgStyle(e.Image.View.Width, e.Image.View.Height, titleAlign),
|
||||||
})},
|
})},
|
||||||
}
|
}
|
||||||
if !e.Image.View.PortraitOnly {
|
|
||||||
content = append(content, zipContent{
|
|
||||||
"OEBPS/Text/space_title.xhtml", e.render(epubtemplates.Blank, map[string]any{
|
|
||||||
"Title": "Blank Page Title",
|
|
||||||
"ViewPort": fmt.Sprintf("width=%d,height=%d", e.Image.View.Width, e.Image.View.Height),
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = wz.WriteMagic(); err != nil {
|
if err = wz.WriteMagic(); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -375,7 +319,7 @@ func (e *ePub) Write() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Double Page or Last Image that is not a double page
|
// Double Page or Last Image that is not a double page
|
||||||
if !e.Image.View.PortraitOnly && (img.DoublePage || (img.Part == 0 && img == lastImage)) {
|
if img.DoublePage || (img.Part == 0 && img == lastImage) {
|
||||||
if err := e.writeBlank(wz, img); err != nil {
|
if err := e.writeBlank(wz, img); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -10,19 +10,18 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Image struct {
|
type Image struct {
|
||||||
Id int
|
Id int
|
||||||
Part int
|
Part int
|
||||||
Raw image.Image
|
Raw image.Image
|
||||||
Width int
|
Width int
|
||||||
Height int
|
Height int
|
||||||
IsCover bool
|
IsCover bool
|
||||||
IsBlank bool
|
IsBlank bool
|
||||||
DoublePage bool
|
DoublePage bool
|
||||||
Path string
|
Path string
|
||||||
Name string
|
Name string
|
||||||
Position string
|
Position string
|
||||||
Format string
|
Format string
|
||||||
OriginalAspectRatio float64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// key name of the blank plage after the image
|
// key name of the blank plage after the image
|
||||||
|
@ -85,18 +85,17 @@ func (e *EPUBImageProcessor) Load() (images []*epubimage.Image, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
img := &epubimage.Image{
|
img := &epubimage.Image{
|
||||||
Id: input.Id,
|
Id: input.Id,
|
||||||
Part: part,
|
Part: part,
|
||||||
Raw: raw,
|
Raw: raw,
|
||||||
Width: dst.Bounds().Dx(),
|
Width: dst.Bounds().Dx(),
|
||||||
Height: dst.Bounds().Dy(),
|
Height: dst.Bounds().Dy(),
|
||||||
IsCover: input.Id == 0 && part == 0,
|
IsCover: input.Id == 0 && part == 0,
|
||||||
IsBlank: dst.Bounds().Dx() == 1 && dst.Bounds().Dy() == 1,
|
IsBlank: dst.Bounds().Dx() == 1 && dst.Bounds().Dy() == 1,
|
||||||
DoublePage: part == 0 && src.Bounds().Dx() > src.Bounds().Dy(),
|
DoublePage: part == 0 && src.Bounds().Dx() > src.Bounds().Dy(),
|
||||||
Path: input.Path,
|
Path: input.Path,
|
||||||
Name: input.Name,
|
Name: input.Name,
|
||||||
Format: e.Image.Format,
|
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 {
|
if err = imgStorage.Add(img.EPUBImgPath(), dst, e.Image.Quality); err != nil {
|
||||||
|
@ -16,8 +16,6 @@ type Color struct {
|
|||||||
|
|
||||||
type View struct {
|
type View struct {
|
||||||
Width, Height int
|
Width, Height int
|
||||||
AspectRatio float64
|
|
||||||
PortraitOnly bool
|
|
||||||
Color Color
|
Color Color
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +67,7 @@ func Content(o *ContentOptions) string {
|
|||||||
} else {
|
} else {
|
||||||
spine.CreateAttr("page-progression-direction", "ltr")
|
spine.CreateAttr("page-progression-direction", "ltr")
|
||||||
}
|
}
|
||||||
|
addToElement(spine, getSpine)
|
||||||
if o.ImageOptions.View.PortraitOnly {
|
|
||||||
addToElement(spine, getSpinePortrait)
|
|
||||||
} else {
|
|
||||||
addToElement(spine, getSpineAuto)
|
|
||||||
}
|
|
||||||
|
|
||||||
guide := pkg.CreateElement("guide")
|
guide := pkg.CreateElement("guide")
|
||||||
addToElement(guide, getGuide)
|
addToElement(guide, getGuide)
|
||||||
@ -87,6 +82,9 @@ func Content(o *ContentOptions) string {
|
|||||||
func getMeta(o *ContentOptions) []tag {
|
func getMeta(o *ContentOptions) []tag {
|
||||||
metas := []tag{
|
metas := []tag{
|
||||||
{"meta", tagAttrs{"property": "dcterms:modified"}, o.UpdatedAt},
|
{"meta", tagAttrs{"property": "dcterms:modified"}, o.UpdatedAt},
|
||||||
|
{"meta", tagAttrs{"property": "rendition:layout"}, "pre-paginated"},
|
||||||
|
{"meta", tagAttrs{"property": "rendition:spread"}, "auto"},
|
||||||
|
{"meta", tagAttrs{"property": "rendition:orientation"}, "auto"},
|
||||||
{"meta", tagAttrs{"property": "schema:accessMode"}, "visual"},
|
{"meta", tagAttrs{"property": "schema:accessMode"}, "visual"},
|
||||||
{"meta", tagAttrs{"property": "schema:accessModeSufficient"}, "visual"},
|
{"meta", tagAttrs{"property": "schema:accessModeSufficient"}, "visual"},
|
||||||
{"meta", tagAttrs{"property": "schema:accessibilityHazard"}, "noFlashingHazard"},
|
{"meta", tagAttrs{"property": "schema:accessibilityHazard"}, "noFlashingHazard"},
|
||||||
@ -104,20 +102,6 @@ func getMeta(o *ContentOptions) []tag {
|
|||||||
{"dc:date", tagAttrs{}, o.UpdatedAt},
|
{"dc:date", tagAttrs{}, o.UpdatedAt},
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.ImageOptions.View.PortraitOnly {
|
|
||||||
metas = append(metas, []tag{
|
|
||||||
{"meta", tagAttrs{"property": "rendition:layout"}, "pre-paginated"},
|
|
||||||
{"meta", tagAttrs{"property": "rendition:spread"}, "none"},
|
|
||||||
{"meta", tagAttrs{"property": "rendition:orientation"}, "portrait"},
|
|
||||||
}...)
|
|
||||||
} else {
|
|
||||||
metas = append(metas, []tag{
|
|
||||||
{"meta", tagAttrs{"property": "rendition:layout"}, "pre-paginated"},
|
|
||||||
{"meta", tagAttrs{"property": "rendition:spread"}, "auto"},
|
|
||||||
{"meta", tagAttrs{"property": "rendition:orientation"}, "auto"},
|
|
||||||
}...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.ImageOptions.Manga {
|
if o.ImageOptions.Manga {
|
||||||
metas = append(metas, tag{"meta", tagAttrs{"name": "primary-writing-mode", "content": "horizontal-rl"}, ""})
|
metas = append(metas, tag{"meta", tagAttrs{"name": "primary-writing-mode", "content": "horizontal-rl"}, ""})
|
||||||
} else {
|
} else {
|
||||||
@ -158,21 +142,18 @@ func getManifest(o *ContentOptions) []tag {
|
|||||||
items := []tag{
|
items := []tag{
|
||||||
{"item", tagAttrs{"id": "toc", "href": "toc.xhtml", "properties": "nav", "media-type": "application/xhtml+xml"}, ""},
|
{"item", tagAttrs{"id": "toc", "href": "toc.xhtml", "properties": "nav", "media-type": "application/xhtml+xml"}, ""},
|
||||||
{"item", tagAttrs{"id": "css", "href": "Text/style.css", "media-type": "text/css"}, ""},
|
{"item", tagAttrs{"id": "css", "href": "Text/style.css", "media-type": "text/css"}, ""},
|
||||||
|
{"item", tagAttrs{"id": "space_title", "href": "Text/space_title.xhtml", "media-type": "application/xhtml+xml"}, ""},
|
||||||
{"item", tagAttrs{"id": "page_title", "href": "Text/title.xhtml", "media-type": "application/xhtml+xml"}, ""},
|
{"item", tagAttrs{"id": "page_title", "href": "Text/title.xhtml", "media-type": "application/xhtml+xml"}, ""},
|
||||||
{"item", tagAttrs{"id": "img_title", "href": fmt.Sprintf("Images/title.%s", o.ImageOptions.Format), "media-type": fmt.Sprintf("image/%s", o.ImageOptions.Format)}, ""},
|
{"item", tagAttrs{"id": "img_title", "href": fmt.Sprintf("Images/title.%s", o.ImageOptions.Format), "media-type": fmt.Sprintf("image/%s", o.ImageOptions.Format)}, ""},
|
||||||
}
|
}
|
||||||
|
|
||||||
if !o.ImageOptions.View.PortraitOnly {
|
|
||||||
items = append(items, tag{"item", tagAttrs{"id": "space_title", "href": "Text/space_title.xhtml", "media-type": "application/xhtml+xml"}, ""})
|
|
||||||
}
|
|
||||||
|
|
||||||
if o.ImageOptions.HasCover || o.Current > 1 {
|
if o.ImageOptions.HasCover || o.Current > 1 {
|
||||||
addTag(o.Cover, false)
|
addTag(o.Cover, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
lastImage := o.Images[len(o.Images)-1]
|
lastImage := o.Images[len(o.Images)-1]
|
||||||
for _, img := range o.Images {
|
for _, img := range o.Images {
|
||||||
addTag(img, !o.ImageOptions.View.PortraitOnly && (img.DoublePage || (img.Part == 0 && img == lastImage)))
|
addTag(img, img.DoublePage || (img.Part == 0 && img == lastImage))
|
||||||
}
|
}
|
||||||
|
|
||||||
items = append(items, imageTags...)
|
items = append(items, imageTags...)
|
||||||
@ -183,7 +164,7 @@ func getManifest(o *ContentOptions) []tag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// spine part of the content
|
// spine part of the content
|
||||||
func getSpineAuto(o *ContentOptions) []tag {
|
func getSpine(o *ContentOptions) []tag {
|
||||||
isOnTheRight := !o.ImageOptions.Manga
|
isOnTheRight := !o.ImageOptions.Manga
|
||||||
getSpread := func(isDoublePage bool) string {
|
getSpread := func(isDoublePage bool) string {
|
||||||
isOnTheRight = !isOnTheRight
|
isOnTheRight = !isOnTheRight
|
||||||
@ -233,20 +214,6 @@ func getSpineAuto(o *ContentOptions) []tag {
|
|||||||
return spine
|
return spine
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSpinePortrait(o *ContentOptions) []tag {
|
|
||||||
spine := []tag{
|
|
||||||
{"itemref", tagAttrs{"idref": "page_title"}, ""},
|
|
||||||
}
|
|
||||||
for _, img := range o.Images {
|
|
||||||
spine = append(spine, tag{
|
|
||||||
"itemref",
|
|
||||||
tagAttrs{"idref": img.PageKey()},
|
|
||||||
"",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return spine
|
|
||||||
}
|
|
||||||
|
|
||||||
// guide part of the content
|
// guide part of the content
|
||||||
func getGuide(o *ContentOptions) []tag {
|
func getGuide(o *ContentOptions) []tag {
|
||||||
guide := []tag{}
|
guide := []tag{}
|
||||||
|
7
main.go
7
main.go
@ -99,6 +99,7 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s
|
|||||||
fmt.Fprintln(os.Stderr, cmd.Options)
|
fmt.Fprintln(os.Stderr, cmd.Options)
|
||||||
|
|
||||||
profile := cmd.Options.GetProfile()
|
profile := cmd.Options.GetProfile()
|
||||||
|
perfectWidth, perfectHeight := profile.PerfectDim()
|
||||||
|
|
||||||
if err := epub.New(&epuboptions.Options{
|
if err := epub.New(&epuboptions.Options{
|
||||||
Input: cmd.Options.Input,
|
Input: cmd.Options.Input,
|
||||||
@ -130,10 +131,8 @@ $ go install github.com/celogeek/go-comic-converter/v%d@%s
|
|||||||
Manga: cmd.Options.Manga,
|
Manga: cmd.Options.Manga,
|
||||||
HasCover: cmd.Options.HasCover,
|
HasCover: cmd.Options.HasCover,
|
||||||
View: &epuboptions.View{
|
View: &epuboptions.View{
|
||||||
Width: profile.Width,
|
Width: perfectWidth,
|
||||||
Height: profile.Height,
|
Height: perfectHeight,
|
||||||
AspectRatio: cmd.Options.AspectRatio,
|
|
||||||
PortraitOnly: cmd.Options.PortraitOnly,
|
|
||||||
Color: epuboptions.Color{
|
Color: epuboptions.Color{
|
||||||
Foreground: cmd.Options.ForegroundColor,
|
Foreground: cmd.Options.ForegroundColor,
|
||||||
Background: cmd.Options.BackgroundColor,
|
Background: cmd.Options.BackgroundColor,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user