mirror of
https://github.com/celogeek/go-comic-converter.git
synced 2025-05-25 00:02:37 +02:00
Compare commits
5 Commits
a5ef2a2927
...
ad614d09b4
Author | SHA1 | Date | |
---|---|---|---|
ad614d09b4 | |||
86fbb8cefe | |||
2d21ced2fe | |||
05dd8acc99 | |||
87a127d04a |
@ -73,6 +73,11 @@ func (i EPUBImage) EPUBImgPath() string {
|
|||||||
return "OEBPS/" + i.ImgPath()
|
return "OEBPS/" + i.ImgPath()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MediaType of the epub image
|
||||||
|
func (i EPUBImage) MediaType() string {
|
||||||
|
return "image/" + i.Format
|
||||||
|
}
|
||||||
|
|
||||||
// ImgStyle style to apply to the image.
|
// ImgStyle style to apply to the image.
|
||||||
//
|
//
|
||||||
// center by default.
|
// center by default.
|
||||||
|
@ -1,8 +1,177 @@
|
|||||||
package epubimageprocessor
|
package epubimageprocessor
|
||||||
|
|
||||||
import "github.com/celogeek/go-comic-converter/v3/internal/pkg/epubimage"
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/jpeg"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"slices"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubimage"
|
||||||
|
"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubprogress"
|
||||||
|
"github.com/celogeek/go-comic-converter/v3/internal/pkg/epubzip"
|
||||||
|
)
|
||||||
|
|
||||||
func (e EPUBImageProcessor) PassThrough() (images []epubimage.EPUBImage, err error) {
|
func (e EPUBImageProcessor) PassThrough() (images []epubimage.EPUBImage, err error) {
|
||||||
images = make([]epubimage.EPUBImage, 0)
|
fi, err := os.Stat(e.Input)
|
||||||
return images, nil
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if fi.IsDir() {
|
||||||
|
return e.passThroughDir()
|
||||||
|
} else {
|
||||||
|
switch ext := strings.ToLower(filepath.Ext(e.Input)); ext {
|
||||||
|
case ".cbz", ".zip":
|
||||||
|
return e.passThroughCbz()
|
||||||
|
case ".cbr", ".rar":
|
||||||
|
return e.passThroughCbr()
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown file format (%s): support .cbz, .zip, .cbr, .rar", ext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EPUBImageProcessor) passThroughDir() (images []epubimage.EPUBImage, err error) {
|
||||||
|
imagesPath := make([]string, 0)
|
||||||
|
|
||||||
|
input := filepath.Clean(e.Input)
|
||||||
|
err = filepath.WalkDir(input, func(path string, d fs.DirEntry, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip hidden files
|
||||||
|
if strings.HasPrefix(filepath.Base(path), ".") {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if d.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if slices.Contains([]string{".jpeg", ".jpg"}, strings.ToLower(filepath.Ext(path))) {
|
||||||
|
imagesPath = append(imagesPath, path)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(imagesPath) == 0 {
|
||||||
|
err = errNoImagesFound
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var imgStorage epubzip.StorageImageWriter
|
||||||
|
imgStorage, err = epubzip.NewStorageImageWriter(e.ImgStorage(), e.Image.Format)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// processing
|
||||||
|
bar := epubprogress.New(epubprogress.Options{
|
||||||
|
Quiet: e.Quiet,
|
||||||
|
Json: e.Json,
|
||||||
|
Max: len(imagesPath),
|
||||||
|
Description: "Copying",
|
||||||
|
CurrentJob: 1,
|
||||||
|
TotalJob: 2,
|
||||||
|
})
|
||||||
|
|
||||||
|
for i, imgPath := range imagesPath {
|
||||||
|
var f *os.File
|
||||||
|
f, err = os.Open(imgPath)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var uncompressedData []byte
|
||||||
|
uncompressedData, err = io.ReadAll(f)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = f.Close()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var config image.Config
|
||||||
|
config, err = jpeg.DecodeConfig(bytes.NewReader(uncompressedData))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var rawImage image.Image
|
||||||
|
if i == 0 {
|
||||||
|
rawImage, err = jpeg.Decode(bytes.NewReader(uncompressedData))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p, fn := filepath.Split(imgPath)
|
||||||
|
if p == input {
|
||||||
|
p = ""
|
||||||
|
} else {
|
||||||
|
p = p[len(input)+1:]
|
||||||
|
}
|
||||||
|
|
||||||
|
img := epubimage.EPUBImage{
|
||||||
|
Id: i,
|
||||||
|
Part: 0,
|
||||||
|
Raw: rawImage,
|
||||||
|
Width: config.Width,
|
||||||
|
Height: config.Height,
|
||||||
|
IsBlank: false,
|
||||||
|
DoublePage: config.Width > config.Height,
|
||||||
|
Path: p,
|
||||||
|
Name: fn,
|
||||||
|
Format: "jpeg",
|
||||||
|
OriginalAspectRatio: float64(config.Height) / float64(config.Width),
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imgStorage.AddRaw(img.EPUBImgPath(), uncompressedData)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
images = append(images, img)
|
||||||
|
_ = bar.Add(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = imgStorage.Close()
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_ = bar.Close()
|
||||||
|
|
||||||
|
if len(images) == 0 {
|
||||||
|
err = errNoImagesFound
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EPUBImageProcessor) passThroughCbz() (images []epubimage.EPUBImage, err error) {
|
||||||
|
images = make([]epubimage.EPUBImage, 0)
|
||||||
|
err = errNoImagesFound
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e EPUBImageProcessor) passThroughCbr() (images []epubimage.EPUBImage, err error) {
|
||||||
|
images = make([]epubimage.EPUBImage, 0)
|
||||||
|
err = errNoImagesFound
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
@ -144,7 +144,7 @@ func (o Content) getManifest() []tag {
|
|||||||
var imageTags, pageTags, spaceTags []tag
|
var imageTags, pageTags, spaceTags []tag
|
||||||
addTag := func(img epubimage.EPUBImage, withSpace bool) {
|
addTag := func(img epubimage.EPUBImage, withSpace bool) {
|
||||||
imageTags = append(imageTags,
|
imageTags = append(imageTags,
|
||||||
tag{"item", tagAttrs{"id": img.ImgKey(), "href": img.ImgPath(), "media-type": o.ImageOptions.MediaType()}, ""},
|
tag{"item", tagAttrs{"id": img.ImgKey(), "href": img.ImgPath(), "media-type": img.MediaType()}, ""},
|
||||||
)
|
)
|
||||||
pageTags = append(pageTags,
|
pageTags = append(pageTags,
|
||||||
tag{"item", tagAttrs{"id": img.PageKey(), "href": img.PagePath(), "media-type": "application/xhtml+xml"}, ""},
|
tag{"item", tagAttrs{"id": img.PageKey(), "href": img.PagePath(), "media-type": "application/xhtml+xml"}, ""},
|
||||||
|
@ -66,3 +66,39 @@ func CompressImage(filename string, format string, img image.Image, quality int)
|
|||||||
cdata.Bytes(),
|
cdata.Bytes(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CompressRaw(filename string, uncompressedData []byte) (Image, error) {
|
||||||
|
var (
|
||||||
|
cdata bytes.Buffer
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
wcdata, err := flate.NewWriter(&cdata, flate.BestCompression)
|
||||||
|
if err != nil {
|
||||||
|
return Image{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = wcdata.Write(uncompressedData)
|
||||||
|
if err != nil {
|
||||||
|
return Image{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = wcdata.Close()
|
||||||
|
if err != nil {
|
||||||
|
return Image{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
t := time.Now()
|
||||||
|
//goland:noinspection GoDeprecation
|
||||||
|
return Image{
|
||||||
|
&zip.FileHeader{
|
||||||
|
Name: filename,
|
||||||
|
CompressedSize64: uint64(cdata.Len()),
|
||||||
|
UncompressedSize64: uint64(len(uncompressedData)),
|
||||||
|
CRC32: crc32.Checksum(uncompressedData, crc32.IEEETable),
|
||||||
|
Method: zip.Deflate,
|
||||||
|
ModifiedTime: uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11),
|
||||||
|
ModifiedDate: uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9),
|
||||||
|
},
|
||||||
|
cdata.Bytes(),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
@ -50,3 +50,24 @@ func (e StorageImageWriter) Add(filename string, img image.Image, quality int) e
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e StorageImageWriter) AddRaw(filename string, uncompressedData []byte) error {
|
||||||
|
zipImage, err := CompressRaw(filename, uncompressedData)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
e.mut.Lock()
|
||||||
|
defer e.mut.Unlock()
|
||||||
|
fh, err := e.fz.CreateRaw(zipImage.Header)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, err = fh.Write(zipImage.Data)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -3,7 +3,6 @@ package epub
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"archive/zip"
|
"archive/zip"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -215,11 +214,6 @@ func (e epub) getParts() (parts []epubPart, imgStorage epubzip.StorageImageReade
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(images) == 0 {
|
|
||||||
err = errors.New("no image found")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort result by id and part
|
// sort result by id and part
|
||||||
sort.Slice(images, func(i, j int) bool {
|
sort.Slice(images, func(i, j int) bool {
|
||||||
if images[i].Id == images[j].Id {
|
if images[i].Id == images[j].Id {
|
||||||
|
@ -20,7 +20,3 @@ type Image struct {
|
|||||||
Format string `yaml:"format" json:"format"`
|
Format string `yaml:"format" json:"format"`
|
||||||
AppleBookCompatibility bool `yaml:"apple_book_compatibility" json:"apple_book_compatibility"`
|
AppleBookCompatibility bool `yaml:"apple_book_compatibility" json:"apple_book_compatibility"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i Image) MediaType() string {
|
|
||||||
return "image/" + i.Format
|
|
||||||
}
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user