mirror of
https://github.com/gen2brain/cbconvert
synced 2025-10-14 10:38:51 +02:00
use MuPDF instead of Poppler
This commit is contained in:
67
README.md
67
README.md
@@ -6,11 +6,10 @@ Introduction
|
|||||||
|
|
||||||
CBconvert is a [Comic Book](http://en.wikipedia.org/wiki/Comic_Book_Archive_file) convert tool.
|
CBconvert is a [Comic Book](http://en.wikipedia.org/wiki/Comic_Book_Archive_file) convert tool.
|
||||||
|
|
||||||
|
|
||||||
Features
|
Features
|
||||||
--------
|
--------
|
||||||
|
|
||||||
- reads rar, zip, 7z, gz, bz2, cbr, cbz, cb7, cbt, pdf and plain directory
|
- reads rar, zip, 7z, gz, bz2, cbr, cbz, cb7, cbt, pdf, epub, xps and plain directory
|
||||||
- always saves processed comic in cbz (zip) format
|
- always saves processed comic in cbz (zip) format
|
||||||
- images can be converted to JPEG, PNG or 4-Bit BMP (16 colors) format
|
- images can be converted to JPEG, PNG or 4-Bit BMP (16 colors) format
|
||||||
- choose resize algorithm (NearestNeighbor, Bilinear, Bicubic, MitchellNetravali, Lanczos2/3)
|
- choose resize algorithm (NearestNeighbor, Bilinear, Bicubic, MitchellNetravali, Lanczos2/3)
|
||||||
@@ -23,31 +22,6 @@ Download
|
|||||||
- [Windows static build](https://github.com/gen2brain/cbconvert/releases/download/0.2.0/cbconvert-0.2.0.zip)
|
- [Windows static build](https://github.com/gen2brain/cbconvert/releases/download/0.2.0/cbconvert-0.2.0.zip)
|
||||||
- [Linux 64bit build](https://github.com/gen2brain/cbconvert/releases/download/0.2.0/cbconvert-0.2.0.tar.gz)
|
- [Linux 64bit build](https://github.com/gen2brain/cbconvert/releases/download/0.2.0/cbconvert-0.2.0.tar.gz)
|
||||||
|
|
||||||
Compile
|
|
||||||
-------
|
|
||||||
|
|
||||||
Install poppler, poppler-glib, cairo and imagemagick dev packages:
|
|
||||||
|
|
||||||
apt-get install libpoppler-glib-dev libcairo2-dev libmagickcore-dev libmagickwand-dev
|
|
||||||
|
|
||||||
Install go package:
|
|
||||||
|
|
||||||
go get github.com/gen2brain/cbconvert
|
|
||||||
go install github.com/gen2brain/cbconvert && cbconvert
|
|
||||||
|
|
||||||
Dependencies
|
|
||||||
------------
|
|
||||||
|
|
||||||
go get github.com/cheggaaa/go-poppler
|
|
||||||
go get github.com/cheggaaa/pb
|
|
||||||
go get github.com/gen2brain/go-unarr
|
|
||||||
go get github.com/gographics/imagick/imagick
|
|
||||||
go get github.com/hotei/bmp
|
|
||||||
go get github.com/nfnt/resize
|
|
||||||
go get github.com/skarademir/naturalsort
|
|
||||||
go get github.com/ungerik/go-cairo
|
|
||||||
go get gopkg.in/alecthomas/kingpin.v2
|
|
||||||
|
|
||||||
Using
|
Using
|
||||||
-----
|
-----
|
||||||
|
|
||||||
@@ -93,3 +67,42 @@ Convert all images in archive to 4bit BMP image and save result in ~/comics dire
|
|||||||
Generate thumbnails by freedesktop specification in ~/.thumbnails/normal directory, Lanczos3 algorithm is used for resizing:
|
Generate thumbnails by freedesktop specification in ~/.thumbnails/normal directory, Lanczos3 algorithm is used for resizing:
|
||||||
|
|
||||||
cbconvert --interpolation=5 --outdir ~/.thumbnails/normal --thumbnail /media/comics/GrooTheWanderer/
|
cbconvert --interpolation=5 --outdir ~/.thumbnails/normal --thumbnail /media/comics/GrooTheWanderer/
|
||||||
|
|
||||||
|
Compile
|
||||||
|
-------
|
||||||
|
|
||||||
|
Install imagemagick dev packages:
|
||||||
|
|
||||||
|
apt-get install libmagickcore-dev libmagickwand-dev
|
||||||
|
|
||||||
|
Compile latest MuPDF:
|
||||||
|
|
||||||
|
git clone git://git.ghostscript.com/mupdf.git && cd mupdf
|
||||||
|
git submodule update --init --recursive
|
||||||
|
HAVE_X11=no HAVE_GLFW=no HAVE_GLUT=no WANT_CURL=no make && make install
|
||||||
|
|
||||||
|
Compile unarr library:
|
||||||
|
|
||||||
|
git clone https://github.com/zeniko/unarr && cd unarr
|
||||||
|
mkdir lzma920 && cd lzma920 && curl -L http://www.7-zip.org/a/lzma920.tar.bz2 | tar -xjvp && cd ..
|
||||||
|
curl -L http://zlib.net/zlib-1.2.8.tar.gz | tar -xzvp
|
||||||
|
curl -L http://www.bzip.org/1.0.6/bzip2-1.0.6.tar.gz | tar -xzvp
|
||||||
|
curl -L https://gist.githubusercontent.com/gen2brain/89fe506863be3fb139e8/raw/8783a7d81e22ad84944d146c5e33beab6dffc641/unarr-makefile.patch | patch -p1
|
||||||
|
CFLAGS="-DHAVE_7Z -DHAVE_ZLIB -DHAVE_BZIP2 -I./lzma920/C -I./zlib-1.2.8 -I./bzip2-1.0.6" make
|
||||||
|
cp build/debug/libunarr.a /usr/lib64/ && cp unarr.h /usr/include
|
||||||
|
|
||||||
|
Install dependencies:
|
||||||
|
|
||||||
|
go get github.com/cheggaaa/pb
|
||||||
|
go get github.com/gen2brain/go-fitz
|
||||||
|
go get github.com/gen2brain/go-unarr
|
||||||
|
go get github.com/gographics/imagick/imagick
|
||||||
|
go get github.com/hotei/bmp
|
||||||
|
go get github.com/nfnt/resize
|
||||||
|
go get github.com/skarademir/naturalsort
|
||||||
|
go get gopkg.in/alecthomas/kingpin.v2
|
||||||
|
|
||||||
|
Install go package:
|
||||||
|
|
||||||
|
go get github.com/gen2brain/cbconvert
|
||||||
|
go install github.com/gen2brain/cbconvert
|
||||||
|
90
cbconvert.go
90
cbconvert.go
@@ -39,8 +39,8 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/cheggaaa/go-poppler"
|
|
||||||
"github.com/cheggaaa/pb"
|
"github.com/cheggaaa/pb"
|
||||||
|
"github.com/gen2brain/go-fitz"
|
||||||
"github.com/gen2brain/go-unarr"
|
"github.com/gen2brain/go-unarr"
|
||||||
"github.com/gographics/imagick/imagick"
|
"github.com/gographics/imagick/imagick"
|
||||||
_ "github.com/hotei/bmp"
|
_ "github.com/hotei/bmp"
|
||||||
@@ -154,17 +154,17 @@ func convertImage(img image.Image, index int, pathName string) {
|
|||||||
<-throttle
|
<-throttle
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts pdf file to cbz
|
// Converts PDF/EPUB/XPS document to CBZ
|
||||||
func convertPDF(file string) {
|
func convertDocument(file string) {
|
||||||
workdir, _ = ioutil.TempDir(os.TempDir(), "cbc")
|
workdir, _ = ioutil.TempDir(os.TempDir(), "cbc")
|
||||||
|
|
||||||
doc, err := poppler.Open(file)
|
doc, err := fitz.NewDocument(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "Skipping %s, error: %v", file, err.Error())
|
fmt.Fprintf(os.Stderr, "Skipping %s, error: %v", file, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
npages := doc.GetNPages()
|
npages := doc.Pages()
|
||||||
|
|
||||||
var bar *pb.ProgressBar
|
var bar *pb.ProgressBar
|
||||||
if !opts.Quiet {
|
if !opts.Quiet {
|
||||||
@@ -179,23 +179,19 @@ func convertPDF(file string) {
|
|||||||
bar.Increment()
|
bar.Increment()
|
||||||
}
|
}
|
||||||
|
|
||||||
page := doc.GetPage(n)
|
img, err := doc.Image(n)
|
||||||
images := page.Images()
|
|
||||||
|
|
||||||
if len(images) == 1 {
|
if err == nil && img != nil {
|
||||||
throttle <- 1
|
throttle <- 1
|
||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
|
|
||||||
surface := images[0].GetSurface()
|
go convertImage(img, n, "")
|
||||||
go convertImage(surface.GetImage(), page.Index(), "")
|
|
||||||
} else {
|
|
||||||
// FIXME merge images?
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts archive to cbz
|
// Converts archive to CBZ
|
||||||
func convertArchive(file string) {
|
func convertArchive(file string) {
|
||||||
workdir, _ = ioutil.TempDir(os.TempDir(), "cbc")
|
workdir, _ = ioutil.TempDir(os.TempDir(), "cbc")
|
||||||
|
|
||||||
@@ -271,7 +267,7 @@ func convertArchive(file string) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts directory to cbz
|
// Converts directory to CBZ
|
||||||
func convertDirectory(path string) {
|
func convertDirectory(path string) {
|
||||||
workdir, _ = ioutil.TempDir(os.TempDir(), "cbc")
|
workdir, _ = ioutil.TempDir(os.TempDir(), "cbc")
|
||||||
|
|
||||||
@@ -318,7 +314,7 @@ func convertDirectory(path string) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saves workdir to cbz archive
|
// Saves workdir to CBZ archive
|
||||||
func saveArchive(file string) {
|
func saveArchive(file string) {
|
||||||
defer os.RemoveAll(workdir)
|
defer os.RemoveAll(workdir)
|
||||||
|
|
||||||
@@ -435,28 +431,23 @@ func coverArchive(file string) (image.Image, error) {
|
|||||||
return img, nil
|
return img, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extracts cover from pdf
|
// Extracts cover from document
|
||||||
func coverPDF(file string) (image.Image, error) {
|
func coverDocument(file string) (image.Image, error) {
|
||||||
doc, err := poppler.Open(file)
|
doc, err := fitz.NewDocument(file)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
page := doc.GetPage(0)
|
img, err := doc.Image(0)
|
||||||
images := page.Images()
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
if len(images) == 1 {
|
|
||||||
surface := images[0].GetSurface()
|
|
||||||
img := surface.GetImage()
|
|
||||||
|
|
||||||
if img == nil {
|
|
||||||
return nil, errors.New("Image is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
return img, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, nil
|
if img == nil {
|
||||||
|
return nil, errors.New("Image is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
return img, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extracts cover from directory
|
// Extracts cover from directory
|
||||||
@@ -489,7 +480,7 @@ func getFiles() []string {
|
|||||||
|
|
||||||
walkFiles := func(fp string, f os.FileInfo, err error) error {
|
walkFiles := func(fp string, f os.FileInfo, err error) error {
|
||||||
if !f.IsDir() {
|
if !f.IsDir() {
|
||||||
if isComic(fp) {
|
if isArchive(fp) || isDocument(fp) {
|
||||||
if isSize(f.Size()) {
|
if isSize(f.Size()) {
|
||||||
files = append(files, fp)
|
files = append(files, fp)
|
||||||
}
|
}
|
||||||
@@ -507,7 +498,7 @@ func getFiles() []string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !stat.IsDir() {
|
if !stat.IsDir() {
|
||||||
if isComic(path) {
|
if isArchive(path) || isDocument(path) {
|
||||||
if isSize(stat.Size()) {
|
if isSize(stat.Size()) {
|
||||||
files = append(files, path)
|
files = append(files, path)
|
||||||
}
|
}
|
||||||
@@ -518,7 +509,7 @@ func getFiles() []string {
|
|||||||
} else {
|
} else {
|
||||||
fs, _ := ioutil.ReadDir(path)
|
fs, _ := ioutil.ReadDir(path)
|
||||||
for _, f := range fs {
|
for _, f := range fs {
|
||||||
if isComic(f.Name()) {
|
if isArchive(f.Name()) || isArchive(f.Name()) {
|
||||||
if isSize(f.Size()) {
|
if isSize(f.Size()) {
|
||||||
files = append(files, f.Name())
|
files = append(files, f.Name())
|
||||||
}
|
}
|
||||||
@@ -580,9 +571,20 @@ func getCover(images []string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Checks if file is comic
|
// Checks if file is comic
|
||||||
func isComic(f string) bool {
|
func isArchive(f string) bool {
|
||||||
var types = []string{".rar", ".zip", ".7z", ".gz", ".bz2",
|
var types = []string{".rar", ".zip", ".7z", ".gz",
|
||||||
".cbr", ".cbz", ".cb7", ".cbt", ".pdf"}
|
".bz2", ".cbr", ".cbz", ".cb7", ".cbt"}
|
||||||
|
for _, t := range types {
|
||||||
|
if strings.ToLower(filepath.Ext(f)) == t {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks if file is document
|
||||||
|
func isDocument(f string) bool {
|
||||||
|
var types = []string{".pdf", ".epub", ".xps"}
|
||||||
for _, t := range types {
|
for _, t := range types {
|
||||||
if strings.ToLower(filepath.Ext(f)) == t {
|
if strings.ToLower(filepath.Ext(f)) == t {
|
||||||
return true
|
return true
|
||||||
@@ -665,8 +667,8 @@ func extractCover(file string, info os.FileInfo) {
|
|||||||
var cover image.Image
|
var cover image.Image
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
cover, err = coverDirectory(file)
|
cover, err = coverDirectory(file)
|
||||||
} else if strings.ToLower(filepath.Ext(file)) == ".pdf" {
|
} else if isDocument(file) {
|
||||||
cover, err = coverPDF(file)
|
cover, err = coverDocument(file)
|
||||||
} else {
|
} else {
|
||||||
cover, err = coverArchive(file)
|
cover, err = coverArchive(file)
|
||||||
}
|
}
|
||||||
@@ -698,8 +700,8 @@ func extractThumbnail(file string, info os.FileInfo) {
|
|||||||
var cover image.Image
|
var cover image.Image
|
||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
cover, err = coverDirectory(file)
|
cover, err = coverDirectory(file)
|
||||||
} else if strings.ToLower(filepath.Ext(file)) == ".pdf" {
|
} else if isDocument(file) {
|
||||||
cover, err = coverPDF(file)
|
cover, err = coverDocument(file)
|
||||||
} else {
|
} else {
|
||||||
cover, err = coverArchive(file)
|
cover, err = coverArchive(file)
|
||||||
}
|
}
|
||||||
@@ -749,8 +751,8 @@ func convertComic(file string, info os.FileInfo) {
|
|||||||
if info.IsDir() {
|
if info.IsDir() {
|
||||||
convertDirectory(file)
|
convertDirectory(file)
|
||||||
saveArchive(file)
|
saveArchive(file)
|
||||||
} else if strings.ToLower(filepath.Ext(file)) == ".pdf" {
|
} else if isDocument(file) {
|
||||||
convertPDF(file)
|
convertDocument(file)
|
||||||
saveArchive(file)
|
saveArchive(file)
|
||||||
} else {
|
} else {
|
||||||
convertArchive(file)
|
convertArchive(file)
|
||||||
@@ -761,7 +763,7 @@ func convertComic(file string, info os.FileInfo) {
|
|||||||
// Parses command line flags
|
// Parses command line flags
|
||||||
func parseFlags() {
|
func parseFlags() {
|
||||||
opts = options{}
|
opts = options{}
|
||||||
kingpin.Version("CBconvert 0.2.0")
|
kingpin.Version("CBconvert 0.3.0")
|
||||||
kingpin.CommandLine.Help = "Comic Book convert tool."
|
kingpin.CommandLine.Help = "Comic Book convert tool."
|
||||||
kingpin.Flag("png", "encode images to PNG instead of JPEG").Short('p').BoolVar(&opts.ToPNG)
|
kingpin.Flag("png", "encode images to PNG instead of JPEG").Short('p').BoolVar(&opts.ToPNG)
|
||||||
kingpin.Flag("bmp", "encode images to 4-Bit BMP instead of JPEG").Short('b').BoolVar(&opts.ToBMP)
|
kingpin.Flag("bmp", "encode images to 4-Bit BMP instead of JPEG").Short('b').BoolVar(&opts.ToBMP)
|
||||||
|
11
make.bash
11
make.bash
@@ -5,14 +5,17 @@ mkdir -p build
|
|||||||
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o build/cbconvert
|
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o build/cbconvert
|
||||||
strip build/cbconvert
|
strip build/cbconvert
|
||||||
|
|
||||||
|
#CGO_LDFLAGS="-lm -lz -ldl -lltdl -lfreetype -static-libgcc" CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -v -x -o build/cbconvert-static --ldflags '-extldflags "-static"'
|
||||||
|
#strip build/cbconvert-static
|
||||||
|
|
||||||
CGO_LDFLAGS="-L/usr/i686-pc-mingw32/usr/lib" \
|
CGO_LDFLAGS="-L/usr/i686-pc-mingw32/usr/lib" \
|
||||||
CGO_CFLAGS="-I/usr/i686-pc-mingw32/usr/include -I/usr/i686-pc-mingw32/usr/include/poppler/glib -I/usr/i686-pc-mingw32/usr/include/glib-2.0 -I/usr/i686-pc-mingw32/usr/include/cairo" \
|
CGO_CFLAGS="-I/usr/i686-pc-mingw32/usr/include -Wno-poison-system-directories" \
|
||||||
CGO_CXXFLAGS="-I/usr/i686-pc-mingw32/usr/include -I/usr/i686-pc-mingw32/usr/include/poppler/glib -I/usr/i686-pc-mingw32/usr/include/glib-2.0 -I/usr/i686-pc-mingw32/usr/include/cairo" \
|
CGO_CXXFLAGS="-I/usr/i686-pc-mingw32/usr/include -Wno-poison-system-directories" \
|
||||||
CGO_CPPFLAGS="-I/usr/i686-pc-mingw32/usr/include -I/usr/i686-pc-mingw32/usr/include/poppler/glib -I/usr/i686-pc-mingw32/usr/include/glib-2.0 -I/usr/i686-pc-mingw32/usr/include/cairo" \
|
CGO_CPPFLAGS="-I/usr/i686-pc-mingw32/usr/include -Wno-poison-system-directories" \
|
||||||
PKG_CONFIG=/usr/bin/i686-pc-mingw32-pkg-config \
|
PKG_CONFIG=/usr/bin/i686-pc-mingw32-pkg-config \
|
||||||
PKG_CONFIG_PATH=/usr/i686-pc-mingw32/usr/lib/pkgconfig \
|
PKG_CONFIG_PATH=/usr/i686-pc-mingw32/usr/lib/pkgconfig \
|
||||||
PKG_CONFIG_LIBDIR=/usr/i686-pc-mingw32/usr/lib/pkgconfig \
|
PKG_CONFIG_LIBDIR=/usr/i686-pc-mingw32/usr/lib/pkgconfig \
|
||||||
CC="i686-pc-mingw32-gcc" CXX="i686-pc-mingw32-g++" \
|
CC="i686-pc-mingw32-gcc" CXX="i686-pc-mingw32-g++" \
|
||||||
CC_FOR_TARGET=i686-pc-mingw32-gcc CXX_FOR_TARGET=i686-pc-mingw32-g++ \
|
CC_FOR_TARGET=i686-pc-mingw32-gcc CXX_FOR_TARGET=i686-pc-mingw32-g++ \
|
||||||
CGO_ENABLED=1 GOOS=windows GOARCH=386 go build -x -work -o build/cbconvert.exe -ldflags "-linkmode external -extldflags -static"
|
CGO_ENABLED=1 GOOS=windows GOARCH=386 go build -o build/cbconvert.exe -ldflags "-linkmode external -extldflags -static"
|
||||||
i686-pc-mingw32-strip build/cbconvert.exe
|
i686-pc-mingw32-strip build/cbconvert.exe
|
||||||
|
Reference in New Issue
Block a user