mirror of
https://github.com/Belphemur/CBZOptimizer.git
synced 2026-01-11 16:17:04 +01:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
839ad9ed9d | ||
|
|
c8879349e1 | ||
|
|
5ac59a93c5 | ||
|
|
72c6776793 |
@@ -30,10 +30,10 @@ func WriteChapterToCBZ(chapter *manga.Chapter, outputFilePath string) error {
|
|||||||
var fileName string
|
var fileName string
|
||||||
if page.IsSplitted {
|
if page.IsSplitted {
|
||||||
// Use the format page%03d-%02d for split pages
|
// Use the format page%03d-%02d for split pages
|
||||||
fileName = fmt.Sprintf("page_%04d-%02d%s", page.Index, page.SplitPartIndex, page.Extension)
|
fileName = fmt.Sprintf("%04d-%02d%s", page.Index, page.SplitPartIndex, page.Extension)
|
||||||
} else {
|
} else {
|
||||||
// Use the format page%03d for non-split pages
|
// Use the format page%03d for non-split pages
|
||||||
fileName = fmt.Sprintf("page_%04d%s", page.Index, page.Extension)
|
fileName = fmt.Sprintf("%04d%s", page.Index, page.Extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new file in the ZIP archive
|
// Create a new file in the ZIP archive
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ func TestWriteChapterToCBZ(t *testing.T) {
|
|||||||
IsConverted: true,
|
IsConverted: true,
|
||||||
ConvertedTime: time.Now(),
|
ConvertedTime: time.Now(),
|
||||||
},
|
},
|
||||||
expectedFiles: []string{"page_0000.jpg", "ComicInfo.xml", "Converted.txt"},
|
expectedFiles: []string{"0000.jpg", "ComicInfo.xml", "Converted.txt"},
|
||||||
},
|
},
|
||||||
//test case where there is only one page and no
|
//test case where there is only one page and no
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,7 @@ func TestWriteChapterToCBZ(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedFiles: []string{"page_0000.jpg"},
|
expectedFiles: []string{"0000.jpg"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Multiple pages with ComicInfo",
|
name: "Multiple pages with ComicInfo",
|
||||||
@@ -64,7 +64,7 @@ func TestWriteChapterToCBZ(t *testing.T) {
|
|||||||
},
|
},
|
||||||
ComicInfoXml: "<Series>Boundless Necromancer</Series>",
|
ComicInfoXml: "<Series>Boundless Necromancer</Series>",
|
||||||
},
|
},
|
||||||
expectedFiles: []string{"page_0000.jpg", "page_0001.jpg", "ComicInfo.xml"},
|
expectedFiles: []string{"0000.jpg", "0001.jpg", "ComicInfo.xml"},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Split page",
|
name: "Split page",
|
||||||
@@ -79,7 +79,7 @@ func TestWriteChapterToCBZ(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedFiles: []string{"page_0000-01.jpg"},
|
expectedFiles: []string{"0000-01.jpg"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ func init() {
|
|||||||
command.Flags().Uint8P("quality", "q", 85, "Quality for conversion (0-100)")
|
command.Flags().Uint8P("quality", "q", 85, "Quality for conversion (0-100)")
|
||||||
command.Flags().IntP("parallelism", "n", 2, "Number of chapters to convert in parallel")
|
command.Flags().IntP("parallelism", "n", 2, "Number of chapters to convert in parallel")
|
||||||
command.Flags().BoolP("override", "o", false, "Override the original CBZ files")
|
command.Flags().BoolP("override", "o", false, "Override the original CBZ files")
|
||||||
|
command.Flags().BoolP("split", "s", false, "Split long pages into smaller chunks")
|
||||||
command.PersistentFlags().VarP(
|
command.PersistentFlags().VarP(
|
||||||
formatFlag,
|
formatFlag,
|
||||||
"format", "f",
|
"format", "f",
|
||||||
@@ -58,6 +59,11 @@ func ConvertCbzCommand(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("invalid quality value")
|
return fmt.Errorf("invalid quality value")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
split, err := cmd.Flags().GetBool("split")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("invalid split value")
|
||||||
|
}
|
||||||
|
|
||||||
parallelism, err := cmd.Flags().GetInt("parallelism")
|
parallelism, err := cmd.Flags().GetInt("parallelism")
|
||||||
if err != nil || parallelism < 1 {
|
if err != nil || parallelism < 1 {
|
||||||
return fmt.Errorf("invalid parallelism value")
|
return fmt.Errorf("invalid parallelism value")
|
||||||
@@ -86,7 +92,13 @@ func ConvertCbzCommand(cmd *cobra.Command, args []string) error {
|
|||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
for path := range fileChan {
|
for path := range fileChan {
|
||||||
err := utils.Optimize(chapterConverter, path, quality, override)
|
err := utils.Optimize(&utils.OptimizeOptions{
|
||||||
|
ChapterConverter: chapterConverter,
|
||||||
|
Path: path,
|
||||||
|
Quality: quality,
|
||||||
|
Override: override,
|
||||||
|
Split: split,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errorChan <- fmt.Errorf("error processing file %s: %w", path, err)
|
errorChan <- fmt.Errorf("error processing file %s: %w", path, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,17 +17,16 @@ import (
|
|||||||
// MockConverter is a mock implementation of the Converter interface
|
// MockConverter is a mock implementation of the Converter interface
|
||||||
type MockConverter struct{}
|
type MockConverter struct{}
|
||||||
|
|
||||||
func (m *MockConverter) Format() constant.ConversionFormat {
|
func (m *MockConverter) ConvertChapter(chapter *manga.Chapter, quality uint8, split bool, progress func(message string, current uint32, total uint32)) (*manga.Chapter, error) {
|
||||||
return constant.WebP
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MockConverter) ConvertChapter(chapter *manga.Chapter, quality uint8, progress func(string)) (*manga.Chapter, error) {
|
|
||||||
// Simulate conversion by setting the IsConverted flag
|
|
||||||
chapter.IsConverted = true
|
chapter.IsConverted = true
|
||||||
chapter.ConvertedTime = time.Now()
|
chapter.ConvertedTime = time.Now()
|
||||||
return chapter, nil
|
return chapter, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MockConverter) Format() constant.ConversionFormat {
|
||||||
|
return constant.WebP
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MockConverter) PrepareConverter() error {
|
func (m *MockConverter) PrepareConverter() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -79,6 +78,7 @@ func TestConvertCbzCommand(t *testing.T) {
|
|||||||
cmd.Flags().Uint8P("quality", "q", 85, "Quality for conversion (0-100)")
|
cmd.Flags().Uint8P("quality", "q", 85, "Quality for conversion (0-100)")
|
||||||
cmd.Flags().IntP("parallelism", "n", 2, "Number of chapters to convert in parallel")
|
cmd.Flags().IntP("parallelism", "n", 2, "Number of chapters to convert in parallel")
|
||||||
cmd.Flags().BoolP("override", "o", false, "Override the original CBZ files")
|
cmd.Flags().BoolP("override", "o", false, "Override the original CBZ files")
|
||||||
|
cmd.Flags().BoolP("split", "s", false, "Split long pages into smaller chunks")
|
||||||
|
|
||||||
// Execute the command
|
// Execute the command
|
||||||
err = ConvertCbzCommand(cmd, []string{tempDir})
|
err = ConvertCbzCommand(cmd, []string{tempDir})
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ func init() {
|
|||||||
command.Flags().BoolP("override", "o", true, "Override the original CBZ files")
|
command.Flags().BoolP("override", "o", true, "Override the original CBZ files")
|
||||||
_ = viper.BindPFlag("override", command.Flags().Lookup("override"))
|
_ = viper.BindPFlag("override", command.Flags().Lookup("override"))
|
||||||
|
|
||||||
|
command.Flags().BoolP("split", "s", false, "Split long pages into smaller chunks")
|
||||||
|
_ = viper.BindPFlag("split", command.Flags().Lookup("split"))
|
||||||
|
|
||||||
command.PersistentFlags().VarP(
|
command.PersistentFlags().VarP(
|
||||||
formatFlag,
|
formatFlag,
|
||||||
"format", "f",
|
"format", "f",
|
||||||
@@ -61,6 +64,8 @@ func WatchCommand(_ *cobra.Command, args []string) error {
|
|||||||
|
|
||||||
override := viper.GetBool("override")
|
override := viper.GetBool("override")
|
||||||
|
|
||||||
|
split := viper.GetBool("split")
|
||||||
|
|
||||||
converterType := constant.FindConversionFormat(viper.GetString("format"))
|
converterType := constant.FindConversionFormat(viper.GetString("format"))
|
||||||
chapterConverter, err := converter.Get(converterType)
|
chapterConverter, err := converter.Get(converterType)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -109,7 +114,13 @@ func WatchCommand(_ *cobra.Command, args []string) error {
|
|||||||
for _, e := range event.Events {
|
for _, e := range event.Events {
|
||||||
switch e {
|
switch e {
|
||||||
case inotifywaitgo.CLOSE_WRITE, inotifywaitgo.MOVE:
|
case inotifywaitgo.CLOSE_WRITE, inotifywaitgo.MOVE:
|
||||||
err := utils.Optimize(chapterConverter, event.Filename, quality, override)
|
err := utils.Optimize(&utils.OptimizeOptions{
|
||||||
|
ChapterConverter: chapterConverter,
|
||||||
|
Path: path,
|
||||||
|
Quality: quality,
|
||||||
|
Override: override,
|
||||||
|
Split: split,
|
||||||
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors <- fmt.Errorf("error processing file %s: %w", event.Filename, err)
|
errors <- fmt.Errorf("error processing file %s: %w", event.Filename, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
type Converter interface {
|
type Converter interface {
|
||||||
// Format of the converter
|
// Format of the converter
|
||||||
Format() (format constant.ConversionFormat)
|
Format() (format constant.ConversionFormat)
|
||||||
ConvertChapter(chapter *manga.Chapter, quality uint8, progress func(string)) (*manga.Chapter, error)
|
ConvertChapter(chapter *manga.Chapter, quality uint8, split bool, progress func(message string, current uint32, total uint32)) (*manga.Chapter, error)
|
||||||
PrepareConverter() error
|
PrepareConverter() error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,18 +14,22 @@ func TestConvertChapter(t *testing.T) {
|
|||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
genTestChapter func(path string) (*manga.Chapter, error)
|
genTestChapter func(path string) (*manga.Chapter, error)
|
||||||
|
split bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "All split pages",
|
name: "All split pages",
|
||||||
genTestChapter: genBigPages,
|
genTestChapter: genBigPages,
|
||||||
|
split: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "No split pages",
|
name: "No split pages",
|
||||||
genTestChapter: genSmallPages,
|
genTestChapter: genSmallPages,
|
||||||
|
split: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Mix of split and no split pages",
|
name: "Mix of split and no split pages",
|
||||||
genTestChapter: genMixSmallBig,
|
genTestChapter: genMixSmallBig,
|
||||||
|
split: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Load test genTestChapter from testdata
|
// Load test genTestChapter from testdata
|
||||||
@@ -50,11 +54,11 @@ func TestConvertChapter(t *testing.T) {
|
|||||||
|
|
||||||
quality := uint8(80)
|
quality := uint8(80)
|
||||||
|
|
||||||
progress := func(msg string) {
|
progress := func(msg string, current uint32, total uint32) {
|
||||||
t.Log(msg)
|
t.Log(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
convertedChapter, err := converter.ConvertChapter(chapter, quality, progress)
|
convertedChapter, err := converter.ConvertChapter(chapter, quality, false, progress)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to convert genTestChapter: %v", err)
|
t.Fatalf("failed to convert genTestChapter: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/belphemur/CBZOptimizer/converter/constant"
|
"github.com/belphemur/CBZOptimizer/converter/constant"
|
||||||
packer2 "github.com/belphemur/CBZOptimizer/manga"
|
"github.com/belphemur/CBZOptimizer/manga"
|
||||||
"github.com/oliamb/cutter"
|
"github.com/oliamb/cutter"
|
||||||
"golang.org/x/exp/slices"
|
"golang.org/x/exp/slices"
|
||||||
_ "golang.org/x/image/webp"
|
_ "golang.org/x/image/webp"
|
||||||
@@ -48,7 +48,7 @@ func (converter *Converter) PrepareConverter() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uint8, progress func(string)) (*packer2.Chapter, error) {
|
func (converter *Converter) ConvertChapter(chapter *manga.Chapter, quality uint8, split bool, progress func(message string, current uint32, total uint32)) (*manga.Chapter, error) {
|
||||||
err := converter.PrepareConverter()
|
err := converter.PrepareConverter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -57,7 +57,7 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
|
|||||||
var wgConvertedPages sync.WaitGroup
|
var wgConvertedPages sync.WaitGroup
|
||||||
maxGoroutines := runtime.NumCPU()
|
maxGoroutines := runtime.NumCPU()
|
||||||
|
|
||||||
pagesChan := make(chan *packer2.PageContainer, maxGoroutines)
|
pagesChan := make(chan *manga.PageContainer, maxGoroutines)
|
||||||
errChan := make(chan error, maxGoroutines)
|
errChan := make(chan error, maxGoroutines)
|
||||||
|
|
||||||
var wgPages sync.WaitGroup
|
var wgPages sync.WaitGroup
|
||||||
@@ -65,13 +65,13 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
|
|||||||
|
|
||||||
guard := make(chan struct{}, maxGoroutines)
|
guard := make(chan struct{}, maxGoroutines)
|
||||||
pagesMutex := sync.Mutex{}
|
pagesMutex := sync.Mutex{}
|
||||||
var pages []*packer2.Page
|
var pages []*manga.Page
|
||||||
var totalPages = uint32(len(chapter.Pages))
|
var totalPages = uint32(len(chapter.Pages))
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
for page := range pagesChan {
|
for page := range pagesChan {
|
||||||
guard <- struct{}{} // would block if guard channel is already filled
|
guard <- struct{}{} // would block if guard channel is already filled
|
||||||
go func(pageToConvert *packer2.PageContainer) {
|
go func(pageToConvert *manga.PageContainer) {
|
||||||
defer wgConvertedPages.Done()
|
defer wgConvertedPages.Done()
|
||||||
convertedPage, err := converter.convertPage(pageToConvert, quality)
|
convertedPage, err := converter.convertPage(pageToConvert, quality)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -93,7 +93,7 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
|
|||||||
}
|
}
|
||||||
pagesMutex.Lock()
|
pagesMutex.Lock()
|
||||||
pages = append(pages, convertedPage.Page)
|
pages = append(pages, convertedPage.Page)
|
||||||
progress(fmt.Sprintf("Converted %d/%d pages to %s format", len(pages), totalPages, converter.Format()))
|
progress(fmt.Sprintf("Converted %d/%d pages to %s format", len(pages), totalPages, converter.Format()), uint32(len(pages)), totalPages)
|
||||||
pagesMutex.Unlock()
|
pagesMutex.Unlock()
|
||||||
<-guard
|
<-guard
|
||||||
}(page)
|
}(page)
|
||||||
@@ -101,10 +101,12 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
for _, page := range chapter.Pages {
|
for _, page := range chapter.Pages {
|
||||||
go func(page *packer2.Page) {
|
go func(page *manga.Page) {
|
||||||
defer wgPages.Done()
|
defer wgPages.Done()
|
||||||
|
|
||||||
splitNeeded, img, format, err := converter.checkPageNeedsSplit(page)
|
splitNeeded, img, format, err := converter.checkPageNeedsSplit(page)
|
||||||
|
// Respect choice to split or not
|
||||||
|
splitNeeded = split && splitNeeded
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errChan <- fmt.Errorf("error checking if page %d of genTestChapter %s needs split: %v", page.Index, chapter.FilePath, err)
|
errChan <- fmt.Errorf("error checking if page %d of genTestChapter %s needs split: %v", page.Index, chapter.FilePath, err)
|
||||||
return
|
return
|
||||||
@@ -112,7 +114,7 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
|
|||||||
|
|
||||||
if !splitNeeded {
|
if !splitNeeded {
|
||||||
wgConvertedPages.Add(1)
|
wgConvertedPages.Add(1)
|
||||||
pagesChan <- packer2.NewContainer(page, img, format)
|
pagesChan <- manga.NewContainer(page, img, format)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
images, err := converter.cropImage(img)
|
images, err := converter.cropImage(img)
|
||||||
@@ -123,9 +125,9 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
|
|||||||
|
|
||||||
atomic.AddUint32(&totalPages, uint32(len(images)-1))
|
atomic.AddUint32(&totalPages, uint32(len(images)-1))
|
||||||
for i, img := range images {
|
for i, img := range images {
|
||||||
page := &packer2.Page{Index: page.Index, IsSplitted: true, SplitPartIndex: uint16(i)}
|
page := &manga.Page{Index: page.Index, IsSplitted: true, SplitPartIndex: uint16(i)}
|
||||||
wgConvertedPages.Add(1)
|
wgConvertedPages.Add(1)
|
||||||
pagesChan <- packer2.NewContainer(page, img, "N/A")
|
pagesChan <- manga.NewContainer(page, img, "N/A")
|
||||||
}
|
}
|
||||||
}(page)
|
}(page)
|
||||||
}
|
}
|
||||||
@@ -144,7 +146,7 @@ func (converter *Converter) ConvertChapter(chapter *packer2.Chapter, quality uin
|
|||||||
return nil, fmt.Errorf("encountered errors: %v", errList)
|
return nil, fmt.Errorf("encountered errors: %v", errList)
|
||||||
}
|
}
|
||||||
|
|
||||||
slices.SortFunc(pages, func(a, b *packer2.Page) int {
|
slices.SortFunc(pages, func(a, b *manga.Page) int {
|
||||||
if a.Index == b.Index {
|
if a.Index == b.Index {
|
||||||
return int(b.SplitPartIndex - a.SplitPartIndex)
|
return int(b.SplitPartIndex - a.SplitPartIndex)
|
||||||
}
|
}
|
||||||
@@ -190,7 +192,7 @@ func (converter *Converter) cropImage(img image.Image) ([]image.Image, error) {
|
|||||||
return parts, nil
|
return parts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (converter *Converter) checkPageNeedsSplit(page *packer2.Page) (bool, image.Image, string, error) {
|
func (converter *Converter) checkPageNeedsSplit(page *manga.Page) (bool, image.Image, string, error) {
|
||||||
reader := io.Reader(bytes.NewBuffer(page.Contents.Bytes()))
|
reader := io.Reader(bytes.NewBuffer(page.Contents.Bytes()))
|
||||||
img, format, err := image.Decode(reader)
|
img, format, err := image.Decode(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -203,7 +205,7 @@ func (converter *Converter) checkPageNeedsSplit(page *packer2.Page) (bool, image
|
|||||||
return height >= converter.maxHeight, img, format, nil
|
return height >= converter.maxHeight, img, format, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (converter *Converter) convertPage(container *packer2.PageContainer, quality uint8) (*packer2.PageContainer, error) {
|
func (converter *Converter) convertPage(container *manga.PageContainer, quality uint8) (*manga.PageContainer, error) {
|
||||||
if container.Format == "webp" {
|
if container.Format == "webp" {
|
||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,24 +8,34 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type OptimizeOptions struct {
|
||||||
|
ChapterConverter converter.Converter
|
||||||
|
Path string
|
||||||
|
Quality uint8
|
||||||
|
Override bool
|
||||||
|
Split bool
|
||||||
|
}
|
||||||
|
|
||||||
// Optimize optimizes a CBZ file using the specified converter.
|
// Optimize optimizes a CBZ file using the specified converter.
|
||||||
func Optimize(chapterConverter converter.Converter, path string, quality uint8, override bool) error {
|
func Optimize(options *OptimizeOptions) error {
|
||||||
log.Printf("Processing file: %s\n", path)
|
log.Printf("Processing file: %s\n", options.Path)
|
||||||
|
|
||||||
// Load the chapter
|
// Load the chapter
|
||||||
chapter, err := cbz.LoadChapter(path)
|
chapter, err := cbz.LoadChapter(options.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to load chapter: %v", err)
|
return fmt.Errorf("failed to load chapter: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if chapter.IsConverted {
|
if chapter.IsConverted {
|
||||||
log.Printf("Chapter already converted: %s", path)
|
log.Printf("Chapter already converted: %s", options.Path)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the chapter
|
// Convert the chapter
|
||||||
convertedChapter, err := chapterConverter.ConvertChapter(chapter, quality, func(msg string) {
|
convertedChapter, err := options.ChapterConverter.ConvertChapter(chapter, options.Quality, options.Split, func(msg string, current uint32, total uint32) {
|
||||||
log.Printf("[%s]%s", path, msg)
|
if current%10 == 0 || current == total {
|
||||||
|
log.Printf("[%s] Converting: %d/%d", chapter.FilePath, current, total)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to convert chapter: %v", err)
|
return fmt.Errorf("failed to convert chapter: %v", err)
|
||||||
@@ -33,9 +43,9 @@ func Optimize(chapterConverter converter.Converter, path string, quality uint8,
|
|||||||
convertedChapter.SetConverted()
|
convertedChapter.SetConverted()
|
||||||
|
|
||||||
// Write the converted chapter back to a CBZ file
|
// Write the converted chapter back to a CBZ file
|
||||||
outputPath := path
|
outputPath := options.Path
|
||||||
if !override {
|
if !options.Override {
|
||||||
outputPath = strings.TrimSuffix(path, ".cbz") + "_converted.cbz"
|
outputPath = strings.TrimSuffix(options.Path, ".cbz") + "_converted.cbz"
|
||||||
}
|
}
|
||||||
err = cbz.WriteChapterToCBZ(convertedChapter, outputPath)
|
err = cbz.WriteChapterToCBZ(convertedChapter, outputPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user