mirror of
https://github.com/celogeek/go-comic-converter.git
synced 2025-05-25 16:22:37 +02:00
move image transformation to processing
This commit is contained in:
parent
02f86eb55e
commit
6295fefa02
@ -1,70 +0,0 @@
|
|||||||
package epubimagefilters
|
|
||||||
|
|
||||||
import (
|
|
||||||
"image"
|
|
||||||
|
|
||||||
epubimage "github.com/celogeek/go-comic-converter/v2/internal/epub/image"
|
|
||||||
"github.com/disintegration/gift"
|
|
||||||
)
|
|
||||||
|
|
||||||
// create filter to apply to the source
|
|
||||||
func NewGift(img image.Image, options *epubimage.Options) *gift.GIFT {
|
|
||||||
g := gift.New()
|
|
||||||
g.SetParallelization(false)
|
|
||||||
|
|
||||||
if options.Crop {
|
|
||||||
g.Add(AutoCrop(
|
|
||||||
img,
|
|
||||||
options.CropRatioLeft,
|
|
||||||
options.CropRatioUp,
|
|
||||||
options.CropRatioRight,
|
|
||||||
options.CropRatioBottom,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
if options.AutoRotate && img.Bounds().Dx() > img.Bounds().Dy() {
|
|
||||||
g.Add(gift.Rotate90())
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.Contrast != 0 {
|
|
||||||
g.Add(gift.Contrast(float32(options.Contrast)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if options.Brightness != 0 {
|
|
||||||
g.Add(gift.Brightness(float32(options.Brightness)))
|
|
||||||
}
|
|
||||||
|
|
||||||
g.Add(
|
|
||||||
Resize(options.ViewWidth, options.ViewHeight, gift.LanczosResampling),
|
|
||||||
Pixel(),
|
|
||||||
)
|
|
||||||
return g
|
|
||||||
}
|
|
||||||
|
|
||||||
// create filters to cut image into 2 equal pieces
|
|
||||||
func NewGiftSplitDoublePage(options *epubimage.Options) []*gift.GIFT {
|
|
||||||
gifts := make([]*gift.GIFT, 2)
|
|
||||||
|
|
||||||
gifts[0] = gift.New(
|
|
||||||
CropSplitDoublePage(options.Manga),
|
|
||||||
)
|
|
||||||
|
|
||||||
gifts[1] = gift.New(
|
|
||||||
CropSplitDoublePage(!options.Manga),
|
|
||||||
)
|
|
||||||
|
|
||||||
for _, g := range gifts {
|
|
||||||
g.SetParallelization(false)
|
|
||||||
if options.Contrast != 0 {
|
|
||||||
g.Add(gift.Contrast(float32(options.Contrast)))
|
|
||||||
}
|
|
||||||
if options.Brightness != 0 {
|
|
||||||
g.Add(gift.Brightness(float32(options.Brightness)))
|
|
||||||
}
|
|
||||||
|
|
||||||
g.Add(
|
|
||||||
Resize(options.ViewWidth, options.ViewHeight, gift.LanczosResampling),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return gifts
|
|
||||||
}
|
|
@ -61,7 +61,7 @@ func LoadImages(o *Options) ([]*epubimage.Image, error) {
|
|||||||
})
|
})
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
|
|
||||||
for i := 0; i < o.Workers; i++ {
|
for i := 0; i < o.WorkersRatio(50); i++ {
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
@ -69,52 +69,23 @@ func LoadImages(o *Options) ([]*epubimage.Image, error) {
|
|||||||
for img := range imageInput {
|
for img := range imageInput {
|
||||||
src := img.Image
|
src := img.Image
|
||||||
|
|
||||||
g := epubimagefilters.NewGift(src, o.Image)
|
for part, dst := range TransformImage(src, img.Id, o.Image) {
|
||||||
// Convert image
|
var raw image.Image
|
||||||
dst := image.NewGray(g.Bounds(src.Bounds()))
|
if img.Id == 0 && part == 0 {
|
||||||
g.Draw(dst, src)
|
raw = dst
|
||||||
|
}
|
||||||
|
|
||||||
var raw image.Image
|
imageOutput <- &epubimage.Image{
|
||||||
if img.Id == 0 {
|
Id: img.Id,
|
||||||
raw = dst
|
Part: part,
|
||||||
}
|
Raw: raw,
|
||||||
|
Data: epubimagedata.New(img.Id, part, dst, o.Image.Quality),
|
||||||
imageOutput <- &epubimage.Image{
|
Width: dst.Bounds().Dx(),
|
||||||
Id: img.Id,
|
Height: dst.Bounds().Dy(),
|
||||||
Part: 0,
|
IsCover: img.Id == 0 && part == 0,
|
||||||
Raw: raw,
|
DoublePage: part == 0 && src.Bounds().Dx() > src.Bounds().Dy(),
|
||||||
Data: epubimagedata.New(img.Id, 0, dst, o.Image.Quality),
|
Path: img.Path,
|
||||||
Width: dst.Bounds().Dx(),
|
Name: img.Name,
|
||||||
Height: dst.Bounds().Dy(),
|
|
||||||
IsCover: img.Id == 0,
|
|
||||||
DoublePage: src.Bounds().Dx() > src.Bounds().Dy(),
|
|
||||||
Path: img.Path,
|
|
||||||
Name: img.Name,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auto split double page
|
|
||||||
// Except for cover
|
|
||||||
// Only if the src image have width > height and is bigger than the view
|
|
||||||
if (!o.Image.HasCover || img.Id > 0) &&
|
|
||||||
o.Image.AutoSplitDoublePage &&
|
|
||||||
src.Bounds().Dx() > src.Bounds().Dy() {
|
|
||||||
gifts := epubimagefilters.NewGiftSplitDoublePage(o.Image)
|
|
||||||
for i, g := range gifts {
|
|
||||||
part := i + 1
|
|
||||||
dst := image.NewGray(g.Bounds(src.Bounds()))
|
|
||||||
g.Draw(dst, src)
|
|
||||||
|
|
||||||
imageOutput <- &epubimage.Image{
|
|
||||||
Id: img.Id,
|
|
||||||
Part: part,
|
|
||||||
Data: epubimagedata.New(img.Id, part, dst, o.Image.Quality),
|
|
||||||
Width: dst.Bounds().Dx(),
|
|
||||||
Height: dst.Bounds().Dy(),
|
|
||||||
IsCover: false,
|
|
||||||
DoublePage: false,
|
|
||||||
Path: img.Path,
|
|
||||||
Name: img.Name,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -153,3 +124,80 @@ func LoadCoverTitleData(img *epubimage.Image, title string, quality int) *epubim
|
|||||||
|
|
||||||
return epubimagedata.NewRaw("OEBPS/Images/title.jpg", dst, quality)
|
return epubimagedata.NewRaw("OEBPS/Images/title.jpg", dst, quality)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// transform image into 1 or 3 images
|
||||||
|
// only doublepage with autosplit has 3 versions
|
||||||
|
func TransformImage(src image.Image, srcId int, o *epubimage.Options) []image.Image {
|
||||||
|
var filters, splitFilter []gift.Filter
|
||||||
|
var images []image.Image
|
||||||
|
|
||||||
|
if o.Crop {
|
||||||
|
f := epubimagefilters.AutoCrop(
|
||||||
|
src,
|
||||||
|
o.CropRatioLeft,
|
||||||
|
o.CropRatioUp,
|
||||||
|
o.CropRatioRight,
|
||||||
|
o.CropRatioBottom,
|
||||||
|
)
|
||||||
|
filters = append(filters, f)
|
||||||
|
splitFilter = append(splitFilter, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.AutoRotate && src.Bounds().Dx() > src.Bounds().Dy() {
|
||||||
|
filters = append(filters, gift.Rotate90())
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.Contrast != 0 {
|
||||||
|
f := gift.Contrast(float32(o.Contrast))
|
||||||
|
filters = append(filters, f)
|
||||||
|
splitFilter = append(splitFilter, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
if o.Brightness != 0 {
|
||||||
|
f := gift.Brightness(float32(o.Brightness))
|
||||||
|
filters = append(filters, f)
|
||||||
|
splitFilter = append(splitFilter, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
filters = append(filters,
|
||||||
|
epubimagefilters.Resize(o.ViewWidth, o.ViewHeight, gift.LanczosResampling),
|
||||||
|
epubimagefilters.Pixel(),
|
||||||
|
)
|
||||||
|
|
||||||
|
// convert
|
||||||
|
{
|
||||||
|
g := gift.New(filters...)
|
||||||
|
dst := image.NewGray(g.Bounds(src.Bounds()))
|
||||||
|
g.Draw(dst, src)
|
||||||
|
images = append(images, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto split off
|
||||||
|
if !o.AutoSplitDoublePage {
|
||||||
|
return images
|
||||||
|
}
|
||||||
|
|
||||||
|
// portrait, no need to split
|
||||||
|
if src.Bounds().Dx() <= src.Bounds().Dy() {
|
||||||
|
return images
|
||||||
|
}
|
||||||
|
|
||||||
|
// cover
|
||||||
|
if o.HasCover && srcId == 0 {
|
||||||
|
return images
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert double page
|
||||||
|
for _, b := range []bool{o.Manga, !o.Manga} {
|
||||||
|
g := gift.New(splitFilter...)
|
||||||
|
g.Add(
|
||||||
|
epubimagefilters.CropSplitDoublePage(b),
|
||||||
|
epubimagefilters.Resize(o.ViewWidth, o.ViewHeight, gift.LanczosResampling),
|
||||||
|
)
|
||||||
|
dst := image.NewGray(g.Bounds(src.Bounds()))
|
||||||
|
g.Draw(dst, src)
|
||||||
|
images = append(images, dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
return images
|
||||||
|
}
|
||||||
|
@ -43,6 +43,14 @@ type Options struct {
|
|||||||
|
|
||||||
var errNoImagesFound = errors.New("no images found")
|
var errNoImagesFound = errors.New("no images found")
|
||||||
|
|
||||||
|
func (o *Options) WorkersRatio(pct int) (nbWorkers int) {
|
||||||
|
nbWorkers = o.Workers * pct / 100
|
||||||
|
if nbWorkers < 1 {
|
||||||
|
nbWorkers = 1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Options) Load() (totalImages int, output chan *tasks, err error) {
|
func (o *Options) Load() (totalImages int, output chan *tasks, err error) {
|
||||||
fi, err := os.Stat(o.Input)
|
fi, err := os.Stat(o.Input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -112,8 +120,8 @@ func (o *Options) loadDir() (totalImages int, output chan *tasks, err error) {
|
|||||||
// read in parallel and get an image
|
// read in parallel and get an image
|
||||||
output = make(chan *tasks, o.Workers)
|
output = make(chan *tasks, o.Workers)
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
wg.Add(o.Workers)
|
for j := 0; j < o.WorkersRatio(50); j++ {
|
||||||
for j := 0; j < o.Workers; j++ {
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for job := range jobs {
|
for job := range jobs {
|
||||||
@ -204,8 +212,8 @@ func (o *Options) loadCbz() (totalImages int, output chan *tasks, err error) {
|
|||||||
|
|
||||||
output = make(chan *tasks, o.Workers)
|
output = make(chan *tasks, o.Workers)
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
wg.Add(o.Workers)
|
for j := 0; j < o.WorkersRatio(50); j++ {
|
||||||
for j := 0; j < o.Workers; j++ {
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for job := range jobs {
|
for job := range jobs {
|
||||||
@ -323,8 +331,8 @@ func (o *Options) loadCbr() (totalImages int, output chan *tasks, err error) {
|
|||||||
// send file to the queue
|
// send file to the queue
|
||||||
output = make(chan *tasks, o.Workers)
|
output = make(chan *tasks, o.Workers)
|
||||||
wg := &sync.WaitGroup{}
|
wg := &sync.WaitGroup{}
|
||||||
wg.Add(o.Workers)
|
for j := 0; j < o.WorkersRatio(50); j++ {
|
||||||
for j := 0; j < o.Workers; j++ {
|
wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for job := range jobs {
|
for job := range jobs {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user