mirror of
https://github.com/gen2brain/cbconvert
synced 2026-06-30 09:11:54 +02:00
Compare commits
51 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f01e858a24 | |||
| 8c21b430a9 | |||
| 5fbd462a78 | |||
| 0797c8456f | |||
| c3f6c5a499 | |||
| fa162972b2 | |||
| aa65bfa4f4 | |||
| 6c293adc1f | |||
| 6936f697b4 | |||
| 83d7a1ea6e | |||
| 3d56765415 | |||
| b1fcf530da | |||
| 7dc21fc0b4 | |||
| fdfa80875e | |||
| 50b0911586 | |||
| 8db1690d3c | |||
| 91e336f772 | |||
| 903a8bbcfc | |||
| e938b140f0 | |||
| 0a3f4d6992 | |||
| c5902fb131 | |||
| d6ece90041 | |||
| c34b4d0a98 | |||
| f0e2232e51 | |||
| 0ba0337ef8 | |||
| 6e97d977ae | |||
| 685b6bf153 | |||
| 14f2e87525 | |||
| cd2f7501e0 | |||
| 69b0b51010 | |||
| c5494af60b | |||
| f447c618de | |||
| 54261d8528 | |||
| f92125643f | |||
| 7b6c766dcc | |||
| dfea3dc6a3 | |||
| 16d01e292e | |||
| 6fe10f5bdb | |||
| 547a3937a8 | |||
| d47c1c1464 | |||
| 5befff07ae | |||
| d4abc99239 | |||
| f1804ce13c | |||
| a74034d669 | |||
| 64fb152c36 | |||
| 7082e3db90 | |||
| 943cd9bb95 | |||
| ec2c321ff3 | |||
| a0ed277971 | |||
| b5b4457088 | |||
| c24d7b7e18 |
@@ -0,0 +1,78 @@
|
||||
on: [push, pull_request]
|
||||
name: Test
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
- name: Setup cmake
|
||||
uses: jwlawson/actions-setup-cmake@v1.13
|
||||
with:
|
||||
cmake-version: '3.27.x'
|
||||
|
||||
- name: Wget libaom
|
||||
uses: wei/wget@v1
|
||||
with:
|
||||
args: https://storage.googleapis.com/aom-releases/libaom-3.7.0.tar.gz
|
||||
- name: Unpack libaom
|
||||
run: |
|
||||
tar -xpf libaom-3.7.0.tar.gz && mkdir build
|
||||
- name: Configure libaom
|
||||
working-directory: build
|
||||
run: |
|
||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release -DENABLE_DOCS=OFF \
|
||||
-DENABLE_EXAMPLES=OFF -DENABLE_NASM=OFF -DENABLE_TESTS=OFF -DENABLE_TOOLS=OFF -DENABLE_WERROR=OFF \
|
||||
-DAOM_TARGET_CPU=generic ../libaom-3.7.0
|
||||
- name: Install libaom
|
||||
working-directory: build
|
||||
run: |
|
||||
make -j3 && sudo make install
|
||||
|
||||
- name: Wget libheif
|
||||
uses: wei/wget@v1
|
||||
with:
|
||||
args: https://github.com/strukturag/libheif/releases/download/v1.15.2/libheif-1.15.2.tar.gz
|
||||
- name: Unpack libheif
|
||||
run: |
|
||||
tar -xpf libheif-1.15.2.tar.gz
|
||||
- name: Configure libheif
|
||||
working-directory: libheif-1.15.2
|
||||
run: |
|
||||
./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu --enable-shared --disable-static --disable-libde265 \
|
||||
--disable-dav1d --disable-go --enable-aom --disable-gdk-pixbuf --disable-rav1e --disable-tests --disable-x265
|
||||
- name: Install libheif
|
||||
working-directory: libheif-1.15.2
|
||||
run: |
|
||||
make -j3 && sudo make install
|
||||
|
||||
- name: Wget ImageMagick
|
||||
uses: wei/wget@v1
|
||||
with:
|
||||
args: -O ImageMagick-7.1.1-15.tar.gz https://github.com/ImageMagick/ImageMagick/archive/refs/tags/7.1.1-15.tar.gz
|
||||
- name: Unpack ImageMagick
|
||||
run: |
|
||||
tar -xpf ImageMagick-7.1.1-15.tar.gz
|
||||
- name: Configure ImageMagick
|
||||
working-directory: ImageMagick-7.1.1-15
|
||||
run: |
|
||||
./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu --enable-shared --disable-static --enable-zero-configuration \
|
||||
--without-frozenpaths --without-utilities --disable-hdri --disable-opencl --without-modules --without-magick-plus-plus --without-perl \
|
||||
--without-bzlib --without-x --without-zip --with-zlib --without-dps --without-djvu --without-autotrace --without-fftw \
|
||||
--without-fpx --without-fontconfig --without-freetype --without-gslib --without-gvc --without-jbig --without-openjp2 \
|
||||
--without-jxl --without-lcms --without-lqr --without-lzma --without-openexr --without-pango --without-raw \
|
||||
--without-rsvg --without-wmf --without-xml --disable-openmp --with-jpeg --with-heic --with-png --with-tiff --with-webp
|
||||
- name: Install ImageMagick
|
||||
working-directory: ImageMagick-7.1.1-15
|
||||
run: |
|
||||
make -j3 && sudo make install
|
||||
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.21
|
||||
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Test
|
||||
run: go test
|
||||
@@ -8,20 +8,21 @@ It can convert comics to different formats to fit your various devices.
|
||||
|
||||
### Features
|
||||
|
||||
* reads RAR, ZIP, 7Z, CBR, CBZ, CB7, CBT, PDF, EPUB, and plain directory
|
||||
* always saves processed comics in CBZ (ZIP) archive format
|
||||
* reads CBR (RAR), CBZ (ZIP), CB7 (7Z), CBT (TAR), PDF, EPUB, MOBI and plain directory
|
||||
* saves processed comics in ZIP archive format or TAR
|
||||
* images can be converted to JPEG, PNG, TIFF, WEBP, AVIF, or 4-Bit BMP (16 colors) file format
|
||||
* rotate, flip, adjust brightness/contrast, adjust levels (Photoshop-like) or grayscale images
|
||||
* resize algorithms (NearestNeighbor, Box, Linear, MitchellNetravali, CatmullRom, Gaussian, Lanczos)
|
||||
* rotate, adjust brightness/contrast, adjust levels (Photoshop-like) or grayscale images
|
||||
* resize filters (NearestNeighbor, Box, Linear, MitchellNetravali, CatmullRom, Gaussian, Lanczos)
|
||||
* export covers from comics
|
||||
* create thumbnails from covers by [FreeDesktop](http://www.freedesktop.org/wiki/) specification
|
||||
* create thumbnails from covers by [FreeDesktop](http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html) specification
|
||||
|
||||
### Download
|
||||
|
||||
* [Windows x86_64](https://github.com/gen2brain/cbconvert/releases/download/0.8.0/cbconvert-0.8.0-windows-x86_64.zip)
|
||||
* [Linux x86_64](https://github.com/gen2brain/cbconvert/releases/download/0.8.0/cbconvert-0.8.0-linux-x86_64.tar.gz)
|
||||
* [macOS x86_64](https://github.com/gen2brain/cbconvert/releases/download/0.8.0/cbconvert-0.8.0-darwin-x86_64.zip)
|
||||
* [macOS aarch64](https://github.com/gen2brain/cbconvert/releases/download/0.8.0/cbconvert-0.8.0-darwin-aarch64.zip)
|
||||
* [Windows x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.0-windows-x86_64.zip)
|
||||
* [Linux x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.0-linux-x86_64.tar.gz)
|
||||
* [Linux aarch64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.0-linux-aarch64.tar.gz)
|
||||
* [macOS x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.0-darwin-x86_64.zip)
|
||||
* [macOS aarch64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.0-darwin-aarch64.zip)
|
||||
|
||||
### Using cbconvert in file managers to generate FreeDesktop thumbnails
|
||||
|
||||
@@ -31,7 +32,7 @@ Copy cbconvert cli binary to your PATH and create file ~/.local/share/thumbnaile
|
||||
[Thumbnailer Entry]
|
||||
TryExec=cbconvert
|
||||
Exec=cbconvert thumbnail --quiet --width %s --outfile %o %i
|
||||
MimeType=application/pdf;application/x-pdf;image/pdf;application/x-cbz;application/x-cbr;application/x-cb7;application/x-cbt;application/epub+zip;application/vnd.comicbook-rar;application/vnd.comicbook+zip;
|
||||
MimeType=application/pdf;application/x-cb7;application/x-cbt;application/epub+zip;application/vnd.comicbook-rar;application/vnd.comicbook+zip;application/x-mobipocket-ebook;
|
||||
```
|
||||
|
||||
This is what it looks like in the PCManFM file manager:
|
||||
@@ -47,8 +48,8 @@ This is what it looks like in the PCManFM file manager:
|
||||
|
||||
Commands:
|
||||
|
||||
convert*
|
||||
Convert archive or document (default command)
|
||||
convert
|
||||
Convert archive or document
|
||||
|
||||
--width
|
||||
Image width (default "0")
|
||||
@@ -58,6 +59,8 @@ This is what it looks like in the PCManFM file manager:
|
||||
Best fit for required width and height (default "false")
|
||||
--format
|
||||
Image format, valid values are jpeg, png, tiff, bmp, webp, avif (default "jpeg")
|
||||
--archive
|
||||
Archive format, valid values are zip, tar (default "zip")
|
||||
--quality
|
||||
Image quality (default "75")
|
||||
--lossless
|
||||
@@ -76,8 +79,6 @@ This is what it looks like in the PCManFM file manager:
|
||||
Convert images to grayscale (monochromatic) (default "false")
|
||||
--rotate
|
||||
Rotate images, valid values are 0, 90, 180, 270 (default "0")
|
||||
--flip
|
||||
Flip images, valid values are none, horizontal, vertical (default "none")
|
||||
--brightness
|
||||
Adjust the brightness of the images, must be in the range (-100, 100) (default "0")
|
||||
--contrast
|
||||
@@ -112,8 +113,10 @@ This is what it looks like in the PCManFM file manager:
|
||||
Image height (default "0")
|
||||
--fit
|
||||
Best fit for required width and height (default "false")
|
||||
--format
|
||||
Image format, valid values are jpeg, png, tiff, bmp, webp, avif (default "jpeg")
|
||||
--quality
|
||||
JPEG image quality (default "75")
|
||||
Image quality (default "75")
|
||||
--filter
|
||||
0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos (default "2")
|
||||
--outdir
|
||||
@@ -146,30 +149,55 @@ This is what it looks like in the PCManFM file manager:
|
||||
Process subdirectories recursively (default "false")
|
||||
--quiet
|
||||
Hide console output (default "false")
|
||||
|
||||
meta
|
||||
CBZ metadata
|
||||
|
||||
--cover
|
||||
Print cover name (default "false")
|
||||
--comment
|
||||
Print zip comment (default "false")
|
||||
--comment-body
|
||||
Set zip comment (default "")
|
||||
--file-add
|
||||
Add file to archive (default "")
|
||||
--file-remove
|
||||
Remove file(s) from archive (glob pattern, i.e. *.xml) (default "")
|
||||
|
||||
```
|
||||
|
||||
### Examples
|
||||
|
||||
Rescale images to 1200px for all supported files found in a directory with a size larger than 60MB:
|
||||
* Rescale images to 1200px for all supported files found in a directory with a size larger than 60MB:
|
||||
|
||||
`cbconvert --recursive --width 1200 --size 60 /media/comics/Thorgal/`
|
||||
|
||||
Convert all images in pdf to 4bit BMP images and save the result in ~/comics directory:
|
||||
* Convert all images in pdf to 4bit BMP images and save the result in ~/comics directory:
|
||||
|
||||
`cbconvert --bmp --outdir ~/comics /media/comics/Garfield/Garfield_01.pdf`
|
||||
`cbconvert --format bmp --outdir ~/comics /media/comics/Garfield/Garfield_01.pdf`
|
||||
|
||||
[BMP](http://en.wikipedia.org/wiki/BMP_file_format) format is a very good choice for black&white pages. Archive size can be smaller 2-3x and the file will be readable by comic readers.
|
||||
|
||||
Generate thumbnails by [freedesktop specification](http://specifications.freedesktop.org/thumbnail-spec/thumbnail-spec-latest.html) in ~/.cache/thumbnails/normal directory with width 512:
|
||||
|
||||
`cbconvert thumbnail --width 512 --outdir ~/.cache/thumbnails/normal /media/comics/GrooTheWanderer/`
|
||||
|
||||
Extract covers to ~/covers dir for all supported files found in the directory, Lanczos algorithm is used for resizing:
|
||||
* Extract covers to ~/covers dir for all supported files found in the directory, Lanczos algorithm is used for resizing:
|
||||
|
||||
`cbconvert cover --outdir ~/covers --filter=7 /media/comics/GrooTheWanderer/`
|
||||
|
||||
* Convert all images to AVIF format:
|
||||
|
||||
`cbconvert --format avif --quality 50 --width 1280 --outdir ~/comics /media/comics/Misc/`
|
||||
|
||||
### Quality settings
|
||||
|
||||
This table maps quality settings for JPEG to the respective AVIF and WEBP quality settings:
|
||||
|
||||
| | | | | |
|
||||
|--------------|----|----|----|----|
|
||||
| JPEG quality | 50 | 60 | 70 | 80 |
|
||||
| AVIF quality | 48 | 51 | 56 | 64 |
|
||||
| WEBP quality | 55 | 64 | 72 | 82 |
|
||||
|
||||
### Compile
|
||||
|
||||
Install ImageMagick7 and libheif (with libaom) libraries and headers and then install to GOBIN:
|
||||
Install ImageMagick7, MuPDF and libheif (with libaom) libraries and headers and then install to GOBIN:
|
||||
|
||||
`go install github.com/gen2brain/cbconvert/cmd/cbconvert@latest`
|
||||
`go install -tags extlib github.com/gen2brain/cbconvert/cmd/cbconvert@latest`
|
||||
|
||||
+1102
-486
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
package cbconvert
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestConvert(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp(os.TempDir(), "cbc")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
opts := Options{}
|
||||
opts.OutDir = tmpDir
|
||||
opts.Archive = "zip"
|
||||
opts.Quality = 75
|
||||
opts.Filter = 2
|
||||
|
||||
conv := New(opts)
|
||||
|
||||
conv.Initialize()
|
||||
defer conv.Terminate()
|
||||
|
||||
files, err := conv.Files([]string{"testdata/test", "testdata"})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
for _, format := range []string{"jpeg", "png", "tiff", "bmp", "webp", "avif"} {
|
||||
conv.Opts.Format = format
|
||||
|
||||
for _, file := range files {
|
||||
conv.Opts.Suffix = fmt.Sprintf("_%s%s", format, filepath.Ext(file.Path))
|
||||
|
||||
err = conv.Convert(file.Path, file.Stat)
|
||||
if err != nil {
|
||||
t.Errorf("format %s: file %s: %v", format, file.Name, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = os.RemoveAll(tmpDir)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCover(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp(os.TempDir(), "cbc")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
opts := Options{}
|
||||
opts.OutDir = tmpDir
|
||||
opts.Quality = 75
|
||||
opts.Filter = 2
|
||||
opts.Format = "jpeg"
|
||||
|
||||
conv := New(opts)
|
||||
|
||||
conv.Initialize()
|
||||
defer conv.Terminate()
|
||||
|
||||
files, err := conv.Files([]string{"testdata/test.cbt"})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
err = conv.Cover(file.Path, file.Stat)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
err = os.RemoveAll(tmpDir)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestThumbnail(t *testing.T) {
|
||||
tmpDir, err := os.MkdirTemp(os.TempDir(), "cbc")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
opts := Options{}
|
||||
opts.OutDir = tmpDir
|
||||
opts.Filter = 2
|
||||
|
||||
conv := New(opts)
|
||||
|
||||
conv.Initialize()
|
||||
defer conv.Terminate()
|
||||
|
||||
files, err := conv.Files([]string{"testdata/test.pdf"})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
err = conv.Thumbnail(file.Path, file.Stat)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
err = os.RemoveAll(tmpDir)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
+14
-11
@@ -1,9 +1,11 @@
|
||||
module github.com/gen2brain/cbconvert/cmd/cbconvert
|
||||
|
||||
go 1.19
|
||||
go 1.21
|
||||
|
||||
toolchain go1.21.0
|
||||
|
||||
require (
|
||||
github.com/gen2brain/cbconvert v0.0.0-20220909080114-0963cb176280
|
||||
github.com/gen2brain/cbconvert v0.0.0-20230902080208-6936f697b466
|
||||
github.com/schollz/progressbar/v3 v3.10.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
)
|
||||
@@ -11,17 +13,18 @@ require (
|
||||
require (
|
||||
github.com/chai2010/webp v1.1.1 // indirect
|
||||
github.com/disintegration/imaging v1.6.2 // indirect
|
||||
github.com/fvbommel/sortorder v1.0.2 // indirect
|
||||
github.com/gen2brain/go-fitz v1.20.2 // indirect
|
||||
github.com/gen2brain/go-unarr v0.1.6 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fvbommel/sortorder v1.1.0 // indirect
|
||||
github.com/gen2brain/go-fitz v1.23.1 // indirect
|
||||
github.com/gen2brain/go-unarr v0.1.7 // indirect
|
||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||
github.com/rivo/uniseg v0.3.4 // indirect
|
||||
github.com/strukturag/libheif v1.13.0 // indirect
|
||||
golang.org/x/image v0.2.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
|
||||
gopkg.in/gographics/imagick.v3 v3.4.2 // indirect
|
||||
github.com/strukturag/libheif v1.15.2 // indirect
|
||||
golang.org/x/image v0.11.0 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/term v0.5.0 // indirect
|
||||
gopkg.in/gographics/imagick.v3 v3.4.3 // indirect
|
||||
)
|
||||
|
||||
+27
-18
@@ -5,14 +5,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
||||
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||
github.com/gen2brain/cbconvert v0.0.0-20220909080114-0963cb176280 h1:wtlm/hA4mVv/CcUCm3gWGOH5oA3qNodLh7zoGjQO7cA=
|
||||
github.com/gen2brain/cbconvert v0.0.0-20220909080114-0963cb176280/go.mod h1:GO5h+s7160FK66rth/0QS06HgXFwE57jaP3OTX/8Rv0=
|
||||
github.com/gen2brain/go-fitz v1.20.2 h1:4FPJCU/ImQ32oojBsYn/+oTkRORxbAhAA+Yw1Fm97MA=
|
||||
github.com/gen2brain/go-fitz v1.20.2/go.mod h1:YbQPODTC/UnQ/RK4JyD3zfpDQ19UKiV85nMMT3XpT0s=
|
||||
github.com/gen2brain/go-unarr v0.1.6 h1:2TtfIQ2dGuCkgEYa+vPE1ydcpkB3CtBbdYMfRSGLdA8=
|
||||
github.com/gen2brain/go-unarr v0.1.6/go.mod h1:P05CsEe8jVEXhxqXqp9mFKUKFV0BKpFmtgNWf8Mcoos=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
|
||||
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||
github.com/gen2brain/cbconvert v0.0.0-20230902080208-6936f697b466 h1:xrc1+L/Wc9BHokp+smaBt/A2R2+nfK0Ws0cvyzTHE7I=
|
||||
github.com/gen2brain/cbconvert v0.0.0-20230902080208-6936f697b466/go.mod h1:5CIPgEHKNZtfH7FR0zzGMAzkFwagUyH7FcjIUDEx7Ps=
|
||||
github.com/gen2brain/go-fitz v1.23.1 h1:x69/szWZXpI3jZ57mMqCg7WqqvtYnQG0lXts3L6M1Fc=
|
||||
github.com/gen2brain/go-fitz v1.23.1/go.mod h1:HU04vc+RisUh/kvEd2pB0LAxmK1oyXdN4ftyshUr9rQ=
|
||||
github.com/gen2brain/go-unarr v0.1.7 h1:mEE7bPShJIsmAX67t6BW2ibpEUO7j5WK152KgNM9NbQ=
|
||||
github.com/gen2brain/go-unarr v0.1.7/go.mod h1:MK9a3hddpaIxjEtrE1f/LA5yJ7gA34cS7Oyr325sY9s=
|
||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7 h1:NlUATi3cllRJhpM4mfR9BxiLRXT83bcSLcOa+S8lrME=
|
||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7/go.mod h1:Hku3FQ2laCEwSv7Z8YkC0er38jLaUycUCbsFkWMr+z4=
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||
@@ -33,41 +35,48 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/strukturag/libheif v1.13.0 h1:SuLo/Fl/Nzbw0ixOya1YZSl0Xd27X4fgofGnJdvOHqI=
|
||||
github.com/strukturag/libheif v1.13.0/go.mod h1:E/PNRlmVtrtj9j2AvBZlrO4dsBDu6KfwDZn7X1Ce8Ks=
|
||||
github.com/strukturag/libheif v1.15.2 h1:pgdcpDHqtLKRXL9ETSTeht0CsJODB3BojpTsb3S/3Wg=
|
||||
github.com/strukturag/libheif v1.15.2/go.mod h1:E/PNRlmVtrtj9j2AvBZlrO4dsBDu6KfwDZn7X1Ce8Ks=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.2.0 h1:/DcQ0w3VHKCC5p0/P2B0JpAZ9Z++V2KOo2fyU89CXBQ=
|
||||
golang.org/x/image v0.2.0/go.mod h1:la7oBXb9w3YFjBqaAwtynVioc1ZvOnNteUNrifGNmAI=
|
||||
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
|
||||
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
|
||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/gographics/imagick.v3 v3.4.2 h1:vk6oildvhRBVSBfQ4X3raJstApYSeK6CZsyzoSOZk58=
|
||||
gopkg.in/gographics/imagick.v3 v3.4.2/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA=
|
||||
gopkg.in/gographics/imagick.v3 v3.4.3 h1:9plKFE/Us913jBN6KohtLG9FNW8LPvfpjiGAORIiEHg=
|
||||
gopkg.in/gographics/imagick.v3 v3.4.3/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA=
|
||||
|
||||
+164
-59
@@ -1,19 +1,57 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime/debug"
|
||||
"syscall"
|
||||
|
||||
"github.com/gen2brain/cbconvert"
|
||||
"github.com/schollz/progressbar/v3"
|
||||
pb "github.com/schollz/progressbar/v3"
|
||||
flag "github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
var appVersion string
|
||||
|
||||
func init() {
|
||||
if appVersion != "" {
|
||||
return
|
||||
}
|
||||
|
||||
info, ok := debug.ReadBuildInfo()
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
if info.Main.Version != "" {
|
||||
appVersion = info.Main.Version
|
||||
}
|
||||
|
||||
for _, kv := range info.Settings {
|
||||
if kv.Value == "" {
|
||||
continue
|
||||
}
|
||||
if kv.Key == "vcs.revision" {
|
||||
appVersion = kv.Value
|
||||
if len(appVersion) > 10 {
|
||||
appVersion = kv.Value[:10]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
opts, args := parseFlags()
|
||||
|
||||
if opts.Version {
|
||||
fmt.Println(filepath.Base(os.Args[0]), appVersion)
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
conv := cbconvert.New(opts)
|
||||
|
||||
c := make(chan os.Signal, 2)
|
||||
@@ -21,48 +59,49 @@ func main() {
|
||||
go func() {
|
||||
for range c {
|
||||
fmt.Println("\naborting")
|
||||
err := os.RemoveAll(conv.Workdir)
|
||||
if err != nil {
|
||||
if err := os.RemoveAll(conv.Workdir); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := os.Stat(opts.Outdir); err != nil {
|
||||
err = os.MkdirAll(opts.Outdir, 0775)
|
||||
if err != nil {
|
||||
if _, err := os.Stat(opts.OutDir); err != nil {
|
||||
if err := os.MkdirAll(opts.OutDir, 0775); err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
conv.Initialize()
|
||||
defer conv.Terminate()
|
||||
|
||||
files, err := conv.Files(args)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
var bar *progressbar.ProgressBar
|
||||
if opts.Cover || opts.Thumbnail {
|
||||
var bar *pb.ProgressBar
|
||||
if opts.Cover || opts.Thumbnail || opts.Meta {
|
||||
if !opts.Quiet {
|
||||
bar = progressbar.NewOptions(conv.Nfiles,
|
||||
progressbar.OptionShowCount(),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
progressbar.OptionUseANSICodes(true),
|
||||
progressbar.OptionSetPredictTime(false),
|
||||
bar = pb.NewOptions(conv.Nfiles,
|
||||
pb.OptionShowCount(),
|
||||
pb.OptionClearOnFinish(),
|
||||
pb.OptionUseANSICodes(true),
|
||||
pb.OptionSetPredictTime(false),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
conv.OnStart = func() {
|
||||
if !opts.Quiet {
|
||||
bar = progressbar.NewOptions(conv.Ncontents,
|
||||
progressbar.OptionShowCount(),
|
||||
progressbar.OptionClearOnFinish(),
|
||||
progressbar.OptionUseANSICodes(true),
|
||||
progressbar.OptionSetDescription(fmt.Sprintf("Converting %d of %d:", conv.CurrFile, conv.Nfiles)),
|
||||
progressbar.OptionSetPredictTime(false),
|
||||
bar = pb.NewOptions(conv.Ncontents,
|
||||
pb.OptionShowCount(),
|
||||
pb.OptionClearOnFinish(),
|
||||
pb.OptionUseANSICodes(true),
|
||||
pb.OptionSetDescription(fmt.Sprintf("Converting %d of %d:", conv.CurrFile, conv.Nfiles)),
|
||||
pb.OptionSetPredictTime(false),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -80,37 +119,47 @@ func main() {
|
||||
}
|
||||
|
||||
for _, file := range files {
|
||||
stat, err := os.Stat(file)
|
||||
switch {
|
||||
case opts.Meta:
|
||||
ret, err := conv.Meta(file.Path)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if opts.Cover {
|
||||
err = conv.ExtractCover(file, stat)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
fmt.Println(ret)
|
||||
} else if opts.Comment {
|
||||
fmt.Println(ret)
|
||||
}
|
||||
|
||||
continue
|
||||
} else if opts.Thumbnail {
|
||||
err = conv.ExtractThumbnail(file, stat)
|
||||
if err != nil {
|
||||
case opts.Cover:
|
||||
if err := conv.Cover(file.Path, file.Stat); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
continue
|
||||
case opts.Thumbnail:
|
||||
if err = conv.Thumbnail(file.Path, file.Stat); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
err = conv.Convert(file, stat)
|
||||
if err != nil {
|
||||
if err := conv.Convert(file.Path, file.Stat); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\r")
|
||||
}
|
||||
|
||||
// parseFlags parses command line flags
|
||||
// parseFlags parses command line flags.
|
||||
func parseFlags() (cbconvert.Options, []string) {
|
||||
opts := cbconvert.Options{}
|
||||
var args []string
|
||||
@@ -121,6 +170,7 @@ func parseFlags() (cbconvert.Options, []string) {
|
||||
convert.IntVar(&opts.Height, "height", 0, "Image height")
|
||||
convert.BoolVar(&opts.Fit, "fit", false, "Best fit for required width and height")
|
||||
convert.StringVar(&opts.Format, "format", "jpeg", "Image format, valid values are jpeg, png, tiff, bmp, webp, avif")
|
||||
convert.StringVar(&opts.Archive, "archive", "zip", "Archive format, valid values are zip, tar")
|
||||
convert.IntVar(&opts.Quality, "quality", 75, "Image quality")
|
||||
convert.BoolVar(&opts.Lossless, "lossless", false, "Lossless compression (avif)")
|
||||
convert.IntVar(&opts.Filter, "filter", 2, "0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos")
|
||||
@@ -130,17 +180,16 @@ func parseFlags() (cbconvert.Options, []string) {
|
||||
convert.BoolVar(&opts.NoConvert, "no-convert", false, "Do not transform or convert images")
|
||||
convert.BoolVar(&opts.Grayscale, "grayscale", false, "Convert images to grayscale (monochromatic)")
|
||||
convert.IntVar(&opts.Rotate, "rotate", 0, "Rotate images, valid values are 0, 90, 180, 270")
|
||||
convert.StringVar(&opts.Flip, "flip", "none", "Flip images, valid values are none, horizontal, vertical")
|
||||
convert.Float64Var(&opts.Brightness, "brightness", 0, "Adjust the brightness of the images, must be in the range (-100, 100)")
|
||||
convert.Float64Var(&opts.Contrast, "contrast", 0, "Adjust the contrast of the images, must be in the range (-100, 100)")
|
||||
convert.IntVar(&opts.Brightness, "brightness", 0, "Adjust the brightness of the images, must be in the range (-100, 100)")
|
||||
convert.IntVar(&opts.Contrast, "contrast", 0, "Adjust the contrast of the images, must be in the range (-100, 100)")
|
||||
convert.StringVar(&opts.Suffix, "suffix", "", "Add suffix to file basename")
|
||||
convert.Float64Var(&opts.LevelsInMin, "levels-inmin", 0, "Shadow input value")
|
||||
convert.IntVar(&opts.LevelsInMin, "levels-inmin", 0, "Shadow input value")
|
||||
convert.Float64Var(&opts.LevelsGamma, "levels-gamma", 1.0, "Midpoint/Gamma")
|
||||
convert.Float64Var(&opts.LevelsInMax, "levels-inmax", 255, "Highlight input value")
|
||||
convert.Float64Var(&opts.LevelsOutMin, "levels-outmin", 0, "Shadow output value")
|
||||
convert.Float64Var(&opts.LevelsOutMax, "levels-outmax", 255, "Highlight output value")
|
||||
convert.StringVar(&opts.Outdir, "outdir", ".", "Output directory")
|
||||
convert.Int64Var(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
|
||||
convert.IntVar(&opts.LevelsInMax, "levels-inmax", 255, "Highlight input value")
|
||||
convert.IntVar(&opts.LevelsOutMin, "levels-outmin", 0, "Shadow output value")
|
||||
convert.IntVar(&opts.LevelsOutMax, "levels-outmax", 255, "Highlight output value")
|
||||
convert.StringVar(&opts.OutDir, "outdir", ".", "Output directory")
|
||||
convert.IntVar(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
|
||||
convert.BoolVar(&opts.Recursive, "recursive", false, "Process subdirectories recursively")
|
||||
convert.BoolVar(&opts.Quiet, "quiet", false, "Hide console output")
|
||||
|
||||
@@ -149,10 +198,11 @@ func parseFlags() (cbconvert.Options, []string) {
|
||||
cover.IntVar(&opts.Width, "width", 0, "Image width")
|
||||
cover.IntVar(&opts.Height, "height", 0, "Image height")
|
||||
cover.BoolVar(&opts.Fit, "fit", false, "Best fit for required width and height")
|
||||
cover.StringVar(&opts.Format, "format", "jpeg", "Image format, valid values are jpeg, png, tiff, bmp, webp, avif")
|
||||
cover.IntVar(&opts.Quality, "quality", 75, "Image quality")
|
||||
cover.IntVar(&opts.Filter, "filter", 2, "0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos")
|
||||
cover.StringVar(&opts.Outdir, "outdir", ".", "Output directory")
|
||||
cover.Int64Var(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
|
||||
cover.StringVar(&opts.OutDir, "outdir", ".", "Output directory")
|
||||
cover.IntVar(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
|
||||
cover.BoolVar(&opts.Recursive, "recursive", false, "Process subdirectories recursively")
|
||||
cover.BoolVar(&opts.Quiet, "quiet", false, "Hide console output")
|
||||
|
||||
@@ -162,64 +212,119 @@ func parseFlags() (cbconvert.Options, []string) {
|
||||
thumbnail.IntVar(&opts.Height, "height", 0, "Image height")
|
||||
thumbnail.BoolVar(&opts.Fit, "fit", false, "Best fit for required width and height")
|
||||
thumbnail.IntVar(&opts.Filter, "filter", 2, "0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos")
|
||||
thumbnail.StringVar(&opts.Outdir, "outdir", ".", "Output directory")
|
||||
thumbnail.StringVar(&opts.Outfile, "outfile", "", "Output file")
|
||||
thumbnail.Int64Var(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
|
||||
thumbnail.StringVar(&opts.OutDir, "outdir", ".", "Output directory")
|
||||
thumbnail.StringVar(&opts.OutFile, "outfile", "", "Output file")
|
||||
thumbnail.IntVar(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
|
||||
thumbnail.BoolVar(&opts.Recursive, "recursive", false, "Process subdirectories recursively")
|
||||
thumbnail.BoolVar(&opts.Quiet, "quiet", false, "Hide console output")
|
||||
|
||||
convert.Usage = func() {
|
||||
meta := flag.NewFlagSet("meta", flag.ExitOnError)
|
||||
meta.SortFlags = false
|
||||
meta.BoolVar(&opts.Cover, "cover", false, "Print cover name")
|
||||
meta.BoolVar(&opts.Comment, "comment", false, "Print zip comment")
|
||||
meta.StringVar(&opts.CommentBody, "comment-body", "", "Set zip comment")
|
||||
meta.StringVar(&opts.FileAdd, "file-add", "", "Add file to archive")
|
||||
meta.StringVar(&opts.FileRemove, "file-remove", "", "Remove file from archive (glob pattern, i.e. *.xml)")
|
||||
|
||||
flag.NewFlagSet("version", flag.ExitOnError)
|
||||
|
||||
flag.Usage = func() {
|
||||
_, _ = fmt.Fprintf(os.Stderr, "Usage: %s <command> [<flags>] [file1 dir1 ... fileOrDirN]\n\n", filepath.Base(os.Args[0]))
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\nCommands:\n")
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n convert*\n \tConvert archive or document (default command)\n\n")
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n convert\n \tConvert archive or document\n\n")
|
||||
convert.VisitAll(func(f *flag.Flag) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n \t")
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
})
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n cover\n \tExtract cover\n\n")
|
||||
cover.VisitAll(func(f *flag.Flag) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n \t")
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
})
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n thumbnail\n \tExtract cover thumbnail (freedesktop spec.)\n\n")
|
||||
thumbnail.VisitAll(func(f *flag.Flag) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n \t")
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
})
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n")
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n meta\n \tCBZ metadata\n\n")
|
||||
meta.VisitAll(func(f *flag.Flag) {
|
||||
_, _ = fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||
_, _ = fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||
})
|
||||
_, _ = fmt.Fprintf(os.Stderr, "\n version\n \tPrint version\n\n")
|
||||
}
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
convert.Usage()
|
||||
_, _ = fmt.Fprintf(os.Stderr, "no arguments\n")
|
||||
_, _ = fmt.Fprintf(os.Stderr, "no command\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
pipe := piped()
|
||||
if pipe {
|
||||
args = lines(os.Stdin)
|
||||
}
|
||||
|
||||
switch os.Args[1] {
|
||||
case "convert":
|
||||
_ = convert.Parse(os.Args[2:])
|
||||
if !pipe {
|
||||
args = convert.Args()
|
||||
}
|
||||
case "cover":
|
||||
opts.Cover = true
|
||||
_ = cover.Parse(os.Args[2:])
|
||||
if !pipe {
|
||||
args = cover.Args()
|
||||
}
|
||||
case "thumbnail":
|
||||
opts.Thumbnail = true
|
||||
_ = thumbnail.Parse(os.Args[2:])
|
||||
if !pipe {
|
||||
args = thumbnail.Args()
|
||||
default:
|
||||
_ = convert.Parse(os.Args[1:])
|
||||
args = convert.Args()
|
||||
}
|
||||
case "meta":
|
||||
opts.Meta = true
|
||||
_ = meta.Parse(os.Args[2:])
|
||||
if !pipe {
|
||||
args = meta.Args()
|
||||
}
|
||||
case "version":
|
||||
opts.Version = true
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
convert.Usage()
|
||||
if len(args) == 0 && !opts.Version {
|
||||
flag.Usage()
|
||||
_, _ = fmt.Fprintf(os.Stderr, "no arguments\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return opts, args
|
||||
}
|
||||
|
||||
// piped checks if we have a piped stdin.
|
||||
func piped() bool {
|
||||
f, err := os.Stdin.Stat()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if f.Mode()&os.ModeNamedPipe == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// lines returns slice of lines from reader.
|
||||
func lines(r io.Reader) []string {
|
||||
data := make([]string, 0)
|
||||
scanner := bufio.NewScanner(r)
|
||||
|
||||
for scanner.Scan() {
|
||||
text := scanner.Text()
|
||||
data = append(data, text)
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
+12
-12
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
MUSL_x86_64="/usr/x86_64-pc-linux-musl"
|
||||
GLIBC_x86_64="/usr/x86_64-pc-linux-gnu-static"
|
||||
MUSL_aarch64="/usr/aarch64-pc-linux-musl"
|
||||
MINGW_x86_64="/usr/x86_64-w64-mingw32"
|
||||
MACOS_x86_64="/usr/x86_64-apple-darwin"
|
||||
@@ -9,14 +9,14 @@ MACOS_aarch64="/usr/aarch64-apple-darwin"
|
||||
VERSION="`git --git-dir ../../.git describe --tags --abbrev=0 2>/dev/null || echo '0.0.0'`"
|
||||
|
||||
BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR}
|
||||
CC=x86_64-pc-linux-musl-gcc \
|
||||
PKG_CONFIG="x86_64-pc-linux-musl-pkg-config" \
|
||||
PKG_CONFIG_PATH="$MUSL_x86_64/usr/lib/pkgconfig" \
|
||||
PKG_CONFIG_LIBDIR="$MUSL_x86_64/usr/lib/pkgconfig" \
|
||||
CGO_CFLAGS="-I$MUSL_x86_64/usr/include" \
|
||||
CGO_LDFLAGS="-L$MUSL_x86_64/usr/lib" \
|
||||
CC=x86_64-pc-linux-gnu-gcc \
|
||||
PKG_CONFIG="x86_64-pc-linux-gnu-pkg-config" \
|
||||
PKG_CONFIG_PATH="$GLIBC_x86_64/usr/lib64/pkgconfig" \
|
||||
PKG_CONFIG_LIBDIR="$GLIBC_x86_64/usr/lib64/pkgconfig" \
|
||||
CGO_CFLAGS="-I$GLIBC_x86_64/usr/include" \
|
||||
CGO_LDFLAGS="-L$GLIBC_x86_64/usr/lib64" \
|
||||
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w '-extldflags=-static'" && \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION} '-extldflags=-static'" && \
|
||||
cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && tar -czf "${BUILDDIR}-linux-x86_64.tar.gz" ${BUILDDIR}
|
||||
rm -rf ${BUILDDIR}
|
||||
|
||||
@@ -28,7 +28,7 @@ PKG_CONFIG_LIBDIR="$MUSL_aarch64/usr/lib/pkgconfig" \
|
||||
CGO_CFLAGS="-I$MUSL_aarch64/usr/include" \
|
||||
CGO_LDFLAGS="-L$MUSL_aarch64/usr/lib" \
|
||||
CGO_ENABLED=1 GOOS=linux GOARCH=arm64 \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w '-extldflags=-static'" && \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION} '-extldflags=-static'" && \
|
||||
cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && tar -czf "${BUILDDIR}-linux-aarch64.tar.gz" ${BUILDDIR}
|
||||
rm -rf ${BUILDDIR}
|
||||
|
||||
@@ -40,7 +40,7 @@ PKG_CONFIG_LIBDIR="$MINGW_x86_64/usr/lib/pkgconfig" \
|
||||
CGO_CFLAGS="-I$MINGW_x86_64/usr/include" \
|
||||
CGO_LDFLAGS="-L$MINGW_x86_64/usr/lib" \
|
||||
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert.exe -ldflags "-s -w '-extldflags=-static -Wl,--allow-multiple-definition'" && \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert.exe -ldflags "-s -w -X main.appVersion=${VERSION} '-extldflags=-static -Wl,--allow-multiple-definition'" && \
|
||||
cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && zip -rq "${BUILDDIR}-windows-x86_64.zip" ${BUILDDIR}
|
||||
rm -rf ${BUILDDIR}
|
||||
|
||||
@@ -54,7 +54,7 @@ PKG_CONFIG_LIBDIR="$MACOS_x86_64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
||||
CGO_CFLAGS="-I$MACOS_x86_64/usr/include -I$MACOS_x86_64/macports/pkgs/opt/local/include" \
|
||||
CGO_LDFLAGS="-L$MACOS_x86_64/SDK/MacOSX12.1.sdk/usr/lib -L$MACOS_x86_64/macports/pkgs/opt/local/lib -mmacosx-version-min=10.13" \
|
||||
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w" && \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION}" && \
|
||||
cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && zip -rq "${BUILDDIR}-darwin-x86_64.zip" ${BUILDDIR}
|
||||
rm -rf ${BUILDDIR}
|
||||
|
||||
@@ -68,6 +68,6 @@ PKG_CONFIG_LIBDIR="$MACOS_aarch64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
||||
CGO_CFLAGS="-I$MACOS_aarch64/usr/include -I$MACOS_aarch64/macports/pkgs/opt/local/include" \
|
||||
CGO_LDFLAGS="-L$MACOS_aarch64/SDK/MacOSX12.1.sdk/usr/lib -L$MACOS_aarch64/macports/pkgs/opt/local/lib -mmacosx-version-min=10.13" \
|
||||
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w" && \
|
||||
go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION}" && \
|
||||
cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && zip -rq "${BUILDDIR}-darwin-aarch64.zip" ${BUILDDIR}
|
||||
rm -rf ${BUILDDIR}
|
||||
|
||||
@@ -1,16 +1,17 @@
|
||||
module github.com/gen2brain/cbconvert
|
||||
|
||||
go 1.19
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/chai2010/webp v1.1.1
|
||||
github.com/disintegration/imaging v1.6.2
|
||||
github.com/fvbommel/sortorder v1.0.2
|
||||
github.com/gen2brain/go-fitz v1.20.1
|
||||
github.com/gen2brain/go-unarr v0.1.6
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/fvbommel/sortorder v1.1.0
|
||||
github.com/gen2brain/go-fitz v1.23.1
|
||||
github.com/gen2brain/go-unarr v0.1.7
|
||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7
|
||||
github.com/strukturag/libheif v1.13.0
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde
|
||||
gopkg.in/gographics/imagick.v3 v3.4.1
|
||||
github.com/strukturag/libheif v1.15.2
|
||||
golang.org/x/image v0.11.0
|
||||
golang.org/x/sync v0.3.0
|
||||
gopkg.in/gographics/imagick.v3 v3.4.3
|
||||
)
|
||||
|
||||
@@ -2,23 +2,53 @@ github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk=
|
||||
github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU=
|
||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
||||
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||
github.com/gen2brain/go-fitz v1.20.1 h1:i5GPe/58q/gbNqa2mO+ZcTymwowbJEsDOXp7D0JwxgU=
|
||||
github.com/gen2brain/go-fitz v1.20.1/go.mod h1:UZAxMETTDK4UPpuh80HaRpPzgkSibUihXVzwj2ip5oQ=
|
||||
github.com/gen2brain/go-unarr v0.1.6 h1:2TtfIQ2dGuCkgEYa+vPE1ydcpkB3CtBbdYMfRSGLdA8=
|
||||
github.com/gen2brain/go-unarr v0.1.6/go.mod h1:P05CsEe8jVEXhxqXqp9mFKUKFV0BKpFmtgNWf8Mcoos=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
|
||||
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||
github.com/gen2brain/go-fitz v1.23.1 h1:x69/szWZXpI3jZ57mMqCg7WqqvtYnQG0lXts3L6M1Fc=
|
||||
github.com/gen2brain/go-fitz v1.23.1/go.mod h1:HU04vc+RisUh/kvEd2pB0LAxmK1oyXdN4ftyshUr9rQ=
|
||||
github.com/gen2brain/go-unarr v0.1.7 h1:mEE7bPShJIsmAX67t6BW2ibpEUO7j5WK152KgNM9NbQ=
|
||||
github.com/gen2brain/go-unarr v0.1.7/go.mod h1:MK9a3hddpaIxjEtrE1f/LA5yJ7gA34cS7Oyr325sY9s=
|
||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7 h1:NlUATi3cllRJhpM4mfR9BxiLRXT83bcSLcOa+S8lrME=
|
||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7/go.mod h1:Hku3FQ2laCEwSv7Z8YkC0er38jLaUycUCbsFkWMr+z4=
|
||||
github.com/strukturag/libheif v1.13.0 h1:SuLo/Fl/Nzbw0ixOya1YZSl0Xd27X4fgofGnJdvOHqI=
|
||||
github.com/strukturag/libheif v1.13.0/go.mod h1:E/PNRlmVtrtj9j2AvBZlrO4dsBDu6KfwDZn7X1Ce8Ks=
|
||||
github.com/strukturag/libheif v1.15.2 h1:pgdcpDHqtLKRXL9ETSTeht0CsJODB3BojpTsb3S/3Wg=
|
||||
github.com/strukturag/libheif v1.15.2/go.mod h1:E/PNRlmVtrtj9j2AvBZlrO4dsBDu6KfwDZn7X1Ce8Ks=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69 h1:Lj6HJGCSn5AjxRAH2+r35Mir4icalbqku+CLUtjnvXY=
|
||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/image v0.11.0 h1:ds2RoQvBvYTiJkwpSFDwCcDFNX7DqjL2WsUgTNk0Ooo=
|
||||
golang.org/x/image v0.11.0/go.mod h1:bglhjqbqVuEb9e9+eNR45Jfu7D+T4Qan+NhQk8Ck2P8=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
gopkg.in/gographics/imagick.v3 v3.4.1 h1:CClNBnd1UGxH9KAl4Vuwx+jgNRkyKN+cHlbuFPyt+KU=
|
||||
gopkg.in/gographics/imagick.v3 v3.4.1/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/gographics/imagick.v3 v3.4.3 h1:9plKFE/Us913jBN6KohtLG9FNW8LPvfpjiGAORIiEHg=
|
||||
gopkg.in/gographics/imagick.v3 v3.4.3/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA=
|
||||
|
||||
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 229 KiB |
Vendored
BIN
Binary file not shown.
|
After Width: | Height: | Size: 387 KiB |
Reference in New Issue
Block a user