From 2c3fb88e7ec83420fc22bffdfaf3a1b60912492e Mon Sep 17 00:00:00 2001 From: Milan Nikolic Date: Sun, 1 Nov 2015 13:57:30 +0100 Subject: [PATCH] use unarr instead of libarchive --- README.md | 16 +++--- cbconvert.go | 136 ++++++++++++++++++++++++++------------------------- 2 files changed, 78 insertions(+), 74 deletions(-) diff --git a/README.md b/README.md index e176391..ffdc650 100644 --- a/README.md +++ b/README.md @@ -26,9 +26,9 @@ Download Compile ------- -Install poppler, poppler-glib, cairo, libarchive and imagemagick dev packages: +Install poppler, poppler-glib, cairo and imagemagick dev packages: - apt-get install libpoppler-glib-dev libcairo2-dev libarchive-dev libmagickcore-dev libmagickwand-dev + apt-get install libpoppler-glib-dev libcairo2-dev libmagickcore-dev libmagickwand-dev Install go package: @@ -38,9 +38,9 @@ Install go package: Dependencies ------------ - go get github.com/MStoykov/go-libarchive 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 @@ -80,14 +80,16 @@ Using Examples -------- +Rescale images to 1200px for all supported files found in directory with size larger then 60MB: + cbconvert --recursive --width 1200 --size 60 /media/comics/Thorgal/ -Rescale images to 1200px for all supported files found in directory with size larger then 60MB. +Convert all images in archive to 4bit BMP image and save result in ~/comics directory: cbconvert --bmp --outdir ~/comics /media/comics/Garfield/Garfield_01.cbz -Convert all images in archive to 4bit BMP image and save result in ~/comics directory. [BMP](http://en.wikipedia.org/wiki/BMP_file_format) format is uncompressed, for black&white pages very good choice. Archive size can be smaller 2-3x and file will be readable by comic readers. +[BMP](http://en.wikipedia.org/wiki/BMP_file_format) format is uncompressed, for black&white pages very good choice. Archive size can be smaller 2-3x and file will be readable by comic readers. + +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/ - -Generate thumbnails by freedesktop specification in ~/.thumbnails/normal directory, Lanczos3 algorithm is used for resizing. diff --git a/cbconvert.go b/cbconvert.go index d4d2467..ace68ba 100644 --- a/cbconvert.go +++ b/cbconvert.go @@ -39,9 +39,9 @@ import ( "sync" "syscall" - "github.com/MStoykov/go-libarchive" "github.com/cheggaaa/go-poppler" "github.com/cheggaaa/pb" + "github.com/gen2brain/go-unarr" "github.com/gographics/imagick/imagick" _ "github.com/hotei/bmp" "github.com/nfnt/resize" @@ -199,69 +199,63 @@ func convertPDF(file string) { func convertArchive(file string) { workdir, _ = ioutil.TempDir(os.TempDir(), "cbc") - f, err := os.Open(file) - if err != nil { - fmt.Fprintf(os.Stderr, "Error Open: %v\n", err.Error()) - return - } - defer f.Close() + ncontents := len(listArchive(file)) - reader, err := archive.NewReader(f) + archive, err := unarr.NewArchive(file) if err != nil { fmt.Fprintf(os.Stderr, "Error NewReader: %v\n", err.Error()) } - defer reader.Free() - defer reader.Close() + defer archive.Close() var bar *pb.ProgressBar if !opts.Quiet { - s, _ := f.Stat() - bar = pb.New(int(s.Size())) - bar.SetUnits(pb.U_BYTES) + bar = pb.New(ncontents) bar.ShowTimeLeft = false bar.Prefix(fmt.Sprintf("Converting %d of %d: ", current, nfiles)) bar.Start() } for { - entry, err := reader.Next() + err := archive.Entry() if err != nil { - if err == archive.ErrArchiveEOF { + if err == io.EOF { break } else { - fmt.Fprintf(os.Stderr, "Error Next: %v\n", err.Error()) + fmt.Fprintf(os.Stderr, "Error Entry: %v\n", err.Error()) continue } } - stat := entry.Stat() - if stat.Mode()&os.ModeType != 0 || stat.IsDir() { - continue - } - if !opts.Quiet { - size := reader.Size() - bar.Set(size) + bar.Increment() } - pathname := entry.PathName() + size := archive.Size() + pathname := archive.Name() + + buf := make([]byte, size) + for size > 0 { + n, err := archive.Read(buf) + if err != nil && err != io.EOF { + break + } + size -= n + } + + if size > 0 { + fmt.Printf("Error Read\n") + continue + } if isImage(pathname) { - buf := new(bytes.Buffer) - _, err := buf.ReadFrom(reader) - if err != nil { - fmt.Fprintf(os.Stderr, "Error ReadFrom: %v\n", err.Error()) - continue - } - - img, err := decodeImage(bytes.NewReader(buf.Bytes()), pathname) + img, err := decodeImage(bytes.NewReader(buf), pathname) if err != nil { fmt.Fprintf(os.Stderr, "Error Decode: %v\n", err.Error()) continue } if opts.NoRGB && !isGrayScale(img) { - copyFile(bytes.NewReader(buf.Bytes()), filepath.Join(workdir, filepath.Base(pathname))) + copyFile(bytes.NewReader(buf), filepath.Join(workdir, filepath.Base(pathname))) continue } @@ -271,7 +265,7 @@ func convertArchive(file string) { go convertImage(img, 0, pathname) } } else { - copyFile(reader, filepath.Join(workdir, filepath.Base(pathname))) + copyFile(bytes.NewReader(buf), filepath.Join(workdir, filepath.Base(pathname))) } } wg.Wait() @@ -368,64 +362,72 @@ func saveArchive(file string) { z.Close() } -// Unpacks archive to directory -func unpackArchive(file string, dir string) { - f, err := os.Open(file) - if err != nil { - fmt.Fprintf(os.Stderr, "Error Open: %v\n", err.Error()) - return - } - defer f.Close() - - reader, err := archive.NewReader(f) +// Lists contents of archive +func listArchive(file string) []string { + var contents []string + archive, err := unarr.NewArchive(file) if err != nil { fmt.Fprintf(os.Stderr, "Error NewReader: %v\n", err.Error()) - return } - defer reader.Free() - defer reader.Close() + defer archive.Close() for { - entry, err := reader.Next() + err := archive.Entry() if err != nil { - if err == archive.ErrArchiveEOF { + if err == io.EOF { break } else { + fmt.Fprintf(os.Stderr, "Error Entry: %v\n", err.Error()) continue } } - if entry.Stat().Mode()&os.ModeType == 0 { - err = copyFile(reader, filepath.Join(dir, entry.PathName())) - } - - if err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err.Error()) - } + pathname := archive.Name() + contents = append(contents, pathname) } + + return contents } // Extracts cover from archive func coverArchive(file string) (image.Image, error) { - tmpdir, _ := ioutil.TempDir(os.TempDir(), "cbc") - defer os.RemoveAll(tmpdir) + var images []string - unpackArchive(file, tmpdir) - - images := getImages(tmpdir) - if len(images) == 0 { - return nil, errors.New("No images") + contents := listArchive(file) + for _, c := range contents { + if isImage(c) { + images = append(images, c) + } } cover := getCover(images) - p, err := os.Open(cover) + archive, err := unarr.NewArchive(file) if err != nil { return nil, err } - defer p.Close() + defer archive.Close() - img, err := decodeImage(p, cover) + err = archive.EntryFor(cover) + if err != nil { + return nil, err + } + + size := archive.Size() + buf := make([]byte, size) + for size > 0 { + n, err := archive.Read(buf) + if err != nil && err != io.EOF { + break + } + size -= n + } + + if size > 0 { + return nil, errors.New("Error Read") + } + + img, err := decodeImage(bytes.NewReader(buf), cover) if err != nil { return nil, err } @@ -759,7 +761,7 @@ func convertComic(file string, info os.FileInfo) { // Parses command line flags func parseFlags() { opts = options{} - kingpin.Version("CBconvert 0.1.0") + kingpin.Version("CBconvert 0.2.0") kingpin.CommandLine.Help = "Comic Book convert tool." 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)