mirror of
https://github.com/celogeek/go-comic-converter.git
synced 2025-05-25 16:22:37 +02:00
support comic without cover
This commit is contained in:
parent
ef8e88c56b
commit
6f74f959fd
@ -96,6 +96,8 @@ Usage of go-comic-converter:
|
|||||||
Manga mode (right to left)
|
Manga mode (right to left)
|
||||||
-noblankpage
|
-noblankpage
|
||||||
Remove blank pages
|
Remove blank pages
|
||||||
|
-nocover
|
||||||
|
Indicate if your comic doesn't have a cover. The first page will be used as a cover and include after the title.
|
||||||
-nocrop
|
-nocrop
|
||||||
Disable cropping
|
Disable cropping
|
||||||
-output string
|
-output string
|
||||||
|
@ -25,6 +25,7 @@ type ImageOptions struct {
|
|||||||
AutoSplitDoublePage bool
|
AutoSplitDoublePage bool
|
||||||
NoBlankPage bool
|
NoBlankPage bool
|
||||||
Manga bool
|
Manga bool
|
||||||
|
HasCover bool
|
||||||
Workers int
|
Workers int
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,7 +114,9 @@ func (e *ePub) getParts() ([]*epubPart, error) {
|
|||||||
|
|
||||||
parts := make([]*epubPart, 0)
|
parts := make([]*epubPart, 0)
|
||||||
cover := images[0]
|
cover := images[0]
|
||||||
images = images[1:]
|
if e.HasCover {
|
||||||
|
images = images[1:]
|
||||||
|
}
|
||||||
if e.LimitMb == 0 {
|
if e.LimitMb == 0 {
|
||||||
parts = append(parts, &epubPart{
|
parts = append(parts, &epubPart{
|
||||||
Cover: cover,
|
Cover: cover,
|
||||||
@ -185,7 +188,7 @@ func (e *ePub) Write() error {
|
|||||||
|
|
||||||
content := []zipContent{
|
content := []zipContent{
|
||||||
{"META-INF/container.xml", containerTmpl},
|
{"META-INF/container.xml", containerTmpl},
|
||||||
{"OEBPS/content.opf", e.render(contentTmpl, map[string]any{"Info": e, "Images": part.Images})},
|
{"OEBPS/content.opf", e.render(contentTmpl, map[string]any{"Info": e, "Cover": part.Cover, "Images": part.Images})},
|
||||||
{"OEBPS/toc.ncx", e.render(tocTmpl, map[string]any{"Info": e})},
|
{"OEBPS/toc.ncx", e.render(tocTmpl, map[string]any{"Info": e})},
|
||||||
{"OEBPS/nav.xhtml", e.render(navTmpl, map[string]any{"Info": e})},
|
{"OEBPS/nav.xhtml", e.render(navTmpl, map[string]any{"Info": e})},
|
||||||
{"OEBPS/Text/style.css", styleTmpl},
|
{"OEBPS/Text/style.css", styleTmpl},
|
||||||
@ -204,7 +207,12 @@ func (e *ePub) Write() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wz.WriteImage(part.Cover.Data)
|
|
||||||
|
// Cover exist or part > 1
|
||||||
|
// If no cover, part 2 and more will include the image as a cover
|
||||||
|
if e.HasCover || i > 0 {
|
||||||
|
wz.WriteImage(part.Cover.Data)
|
||||||
|
}
|
||||||
|
|
||||||
for _, img := range part.Images {
|
for _, img := range part.Images {
|
||||||
if err := wz.WriteFile(
|
if err := wz.WriteFile(
|
||||||
|
@ -22,10 +22,6 @@ func (img *ImageData) CompressedSize() uint64 {
|
|||||||
|
|
||||||
func newImageData(id int, part int, img image.Image, quality int) *ImageData {
|
func newImageData(id int, part int, img image.Image, quality int) *ImageData {
|
||||||
name := fmt.Sprintf("OEBPS/Images/%d_p%d.jpg", id, part)
|
name := fmt.Sprintf("OEBPS/Images/%d_p%d.jpg", id, part)
|
||||||
if id == 0 {
|
|
||||||
name = "OEBPS/Images/cover.jpg"
|
|
||||||
}
|
|
||||||
|
|
||||||
data := bytes.NewBuffer([]byte{})
|
data := bytes.NewBuffer([]byte{})
|
||||||
if err := jpeg.Encode(data, img, &jpeg.Options{Quality: quality}); err != nil {
|
if err := jpeg.Encode(data, img, &jpeg.Options{Quality: quality}); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@ -22,11 +22,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Image struct {
|
type Image struct {
|
||||||
Id int
|
Id int
|
||||||
Part int
|
Part int
|
||||||
Data *ImageData
|
Data *ImageData
|
||||||
Width int
|
Width int
|
||||||
Height int
|
Height int
|
||||||
|
IsCover bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type imageTask struct {
|
type imageTask struct {
|
||||||
@ -152,12 +153,13 @@ func LoadImages(path string, options *ImageOptions) ([]*Image, error) {
|
|||||||
newImageData(img.Id, 0, dst, options.Quality),
|
newImageData(img.Id, 0, dst, options.Quality),
|
||||||
dst.Bounds().Dx(),
|
dst.Bounds().Dx(),
|
||||||
dst.Bounds().Dy(),
|
dst.Bounds().Dy(),
|
||||||
|
img.Id == 0,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto split double page
|
// Auto split double page
|
||||||
// Except for cover
|
// Except for cover
|
||||||
// Only if the src image have width > height and is bigger than the view
|
// Only if the src image have width > height and is bigger than the view
|
||||||
if img.Id > 0 &&
|
if (!options.HasCover || img.Id > 0) &&
|
||||||
options.AutoSplitDoublePage &&
|
options.AutoSplitDoublePage &&
|
||||||
src.Bounds().Dx() > src.Bounds().Dy() &&
|
src.Bounds().Dx() > src.Bounds().Dy() &&
|
||||||
src.Bounds().Dx() > options.ViewHeight &&
|
src.Bounds().Dx() > options.ViewHeight &&
|
||||||
@ -173,6 +175,7 @@ func LoadImages(path string, options *ImageOptions) ([]*Image, error) {
|
|||||||
newImageData(img.Id, part, dst, options.Quality),
|
newImageData(img.Id, part, dst, options.Quality),
|
||||||
dst.Bounds().Dx(),
|
dst.Bounds().Dx(),
|
||||||
dst.Bounds().Dy(),
|
dst.Bounds().Dy(),
|
||||||
|
false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,12 +23,14 @@
|
|||||||
<manifest>
|
<manifest>
|
||||||
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
|
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
|
||||||
<item id="nav" href="nav.xhtml" properties="nav" media-type="application/xhtml+xml"/>
|
<item id="nav" href="nav.xhtml" properties="nav" media-type="application/xhtml+xml"/>
|
||||||
<item id="cover" href="Images/cover.jpg" media-type="image/jpeg" properties="cover-image"/>
|
<item id="cover" href="Images/{{ .Cover.Id }}_p{{ .Cover.Part }}.jpg" media-type="image/jpeg" properties="cover-image"/>
|
||||||
<item id="css" href="Text/style.css" media-type="text/css"/>
|
<item id="css" href="Text/style.css" media-type="text/css"/>
|
||||||
<item id="page_part" href="Text/part.xhtml" media-type="application/xhtml+xml"/>
|
<item id="page_part" href="Text/part.xhtml" media-type="application/xhtml+xml"/>
|
||||||
{{ range .Images }}
|
{{ range .Images }}
|
||||||
<item id="page_{{ .Id }}_p{{ .Part}}" href="Text/{{ .Id }}_p{{ .Part}}.xhtml" media-type="application/xhtml+xml"/>
|
<item id="page_{{ .Id }}_p{{ .Part}}" href="Text/{{ .Id }}_p{{ .Part}}.xhtml" media-type="application/xhtml+xml"/>
|
||||||
|
{{ if eq .IsCover false }}
|
||||||
<item id="img_{{ .Id }}_p{{ .Part}}" href="Images/{{ .Id }}_p{{ .Part}}.jpg" media-type="image/jpeg"/>
|
<item id="img_{{ .Id }}_p{{ .Part}}" href="Images/{{ .Id }}_p{{ .Part}}.jpg" media-type="image/jpeg"/>
|
||||||
|
{{ end }}
|
||||||
{{ if eq $info.NoBlankPage false }}
|
{{ if eq $info.NoBlankPage false }}
|
||||||
{{ if eq .Part 1 }}
|
{{ if eq .Part 1 }}
|
||||||
<item id="page_{{ .Id }}_sp" href="Text/{{ .Id }}_sp.xhtml" media-type="application/xhtml+xml"/>
|
<item id="page_{{ .Id }}_sp" href="Text/{{ .Id }}_sp.xhtml" media-type="application/xhtml+xml"/>
|
||||||
|
5
main.go
5
main.go
@ -71,6 +71,7 @@ type Option struct {
|
|||||||
AutoSplitDoublePage bool
|
AutoSplitDoublePage bool
|
||||||
NoBlankPage bool
|
NoBlankPage bool
|
||||||
Manga bool
|
Manga bool
|
||||||
|
NoCover bool
|
||||||
Workers int
|
Workers int
|
||||||
LimitMb int
|
LimitMb int
|
||||||
}
|
}
|
||||||
@ -106,6 +107,7 @@ Options:
|
|||||||
AutoSplitDoublePage: %v
|
AutoSplitDoublePage: %v
|
||||||
NoBlankPage : %v
|
NoBlankPage : %v
|
||||||
Manga : %v
|
Manga : %v
|
||||||
|
HasCover : %v
|
||||||
LimitMb : %s
|
LimitMb : %s
|
||||||
Workers : %d
|
Workers : %d
|
||||||
`,
|
`,
|
||||||
@ -122,6 +124,7 @@ Options:
|
|||||||
o.AutoSplitDoublePage,
|
o.AutoSplitDoublePage,
|
||||||
o.NoBlankPage,
|
o.NoBlankPage,
|
||||||
o.Manga,
|
o.Manga,
|
||||||
|
!o.NoCover,
|
||||||
limitmb,
|
limitmb,
|
||||||
o.Workers,
|
o.Workers,
|
||||||
)
|
)
|
||||||
@ -154,6 +157,7 @@ func main() {
|
|||||||
flag.BoolVar(&opt.AutoSplitDoublePage, "autosplitdoublepage", false, "Auto Split double page when width > height")
|
flag.BoolVar(&opt.AutoSplitDoublePage, "autosplitdoublepage", false, "Auto Split double page when width > height")
|
||||||
flag.BoolVar(&opt.NoBlankPage, "noblankpage", false, "Remove blank pages")
|
flag.BoolVar(&opt.NoBlankPage, "noblankpage", false, "Remove blank pages")
|
||||||
flag.BoolVar(&opt.Manga, "manga", false, "Manga mode (right to left)")
|
flag.BoolVar(&opt.Manga, "manga", false, "Manga mode (right to left)")
|
||||||
|
flag.BoolVar(&opt.NoCover, "nocover", false, "Indicate if your comic doesn't have a cover. The first page will be used as a cover and include after the title.")
|
||||||
flag.IntVar(&opt.LimitMb, "limitmb", 0, "Limit size of the ePub: Default nolimit (0), Minimum 20")
|
flag.IntVar(&opt.LimitMb, "limitmb", 0, "Limit size of the ePub: Default nolimit (0), Minimum 20")
|
||||||
flag.IntVar(&opt.Workers, "workers", runtime.NumCPU(), "Number of workers")
|
flag.IntVar(&opt.Workers, "workers", runtime.NumCPU(), "Number of workers")
|
||||||
flag.Usage = func() {
|
flag.Usage = func() {
|
||||||
@ -261,6 +265,7 @@ func main() {
|
|||||||
AutoSplitDoublePage: opt.AutoSplitDoublePage,
|
AutoSplitDoublePage: opt.AutoSplitDoublePage,
|
||||||
NoBlankPage: opt.NoBlankPage,
|
NoBlankPage: opt.NoBlankPage,
|
||||||
Manga: opt.Manga,
|
Manga: opt.Manga,
|
||||||
|
HasCover: !opt.NoCover,
|
||||||
Workers: opt.Workers,
|
Workers: opt.Workers,
|
||||||
},
|
},
|
||||||
}).Write(); err != nil {
|
}).Write(); err != nil {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user