Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a9e3281a5f | |||
| 962fde8c8d | |||
| a8084ed897 | |||
| 183c42613f | |||
| cad75231b1 | |||
| c32019615d | |||
| dd9000cfea | |||
| 4fc3209b4e | |||
| 000bd20f71 | |||
| f558b109e5 | |||
| 5922f102be | |||
| f84d2d4333 | |||
| 551ab9e137 | |||
| 046cc2c1fd | |||
| a5b1f41ba6 | |||
| 9f628741e0 | |||
| ccbb27ff6d | |||
| 04473e95bf | |||
| c061297ad0 | |||
| 544344d5c2 | |||
| e14aa6baab | |||
| 6400ae14d8 | |||
| 788a9d3bd5 | |||
| bff17636f6 | |||
| bd19faf18e | |||
| cf1e8a1fec | |||
| 63ad96ac3a | |||
| 9bd7193124 | |||
| 09a27ac9a4 | |||
| 4109ae154f | |||
| 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 |
@@ -0,0 +1,120 @@
|
|||||||
|
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: Update apt-get
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
|
||||||
|
- 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: Install libheif dependencies
|
||||||
|
run: |
|
||||||
|
sudo apt-get install libaom-dev -y
|
||||||
|
- 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 --disable-examples
|
||||||
|
- name: Install libheif
|
||||||
|
working-directory: libheif-1.15.2
|
||||||
|
run: |
|
||||||
|
make -j3 && sudo make install
|
||||||
|
|
||||||
|
- name: Wget lcms2
|
||||||
|
uses: wei/wget@v1
|
||||||
|
with:
|
||||||
|
args: https://github.com/mm2/Little-CMS/releases/download/lcms2.15/lcms2-2.15.tar.gz
|
||||||
|
- name: Unpack lcms2
|
||||||
|
run: |
|
||||||
|
tar -xpf lcms2-2.15.tar.gz
|
||||||
|
- name: Configure lcms2
|
||||||
|
working-directory: lcms2-2.15
|
||||||
|
run: |
|
||||||
|
./configure --prefix=/usr --libdir=/usr/lib/x86_64-linux-gnu --enable-shared --disable-static
|
||||||
|
- name: Install lcms2
|
||||||
|
working-directory: lcms2-2.15
|
||||||
|
run: |
|
||||||
|
make -j3 && sudo make install
|
||||||
|
|
||||||
|
- name: Wget highway
|
||||||
|
uses: wei/wget@v1
|
||||||
|
with:
|
||||||
|
args: -O highway-1.0.5.tar.gz https://github.com/google/highway/archive/refs/tags/1.0.5.tar.gz
|
||||||
|
- name: Unpack highway
|
||||||
|
run: |
|
||||||
|
tar -xpf highway-1.0.5.tar.gz && mkdir -p highway-1.0.5/build
|
||||||
|
- name: Configure highway
|
||||||
|
working-directory: highway-1.0.5/build
|
||||||
|
run: |
|
||||||
|
cmake -DCMAKE_INSTALL_PREFIX=/usr -DHWY_ENABLE_TESTS=OFF -DHWY_ENABLE_EXAMPLES=OFF -DHWY_WARNINGS_ARE_ERRORS=OFF ../
|
||||||
|
- name: Install highway
|
||||||
|
working-directory: highway-1.0.5/build
|
||||||
|
run: |
|
||||||
|
make -j3 && sudo make install
|
||||||
|
|
||||||
|
- name: Wget libjxl
|
||||||
|
uses: wei/wget@v1
|
||||||
|
with:
|
||||||
|
args: -O libjxl-0.8.2.tar.gz https://github.com/libjxl/libjxl/archive/refs/tags/v0.8.2.tar.gz
|
||||||
|
- name: Unpack libjxl
|
||||||
|
run: |
|
||||||
|
tar -xpf libjxl-0.8.2.tar.gz && mkdir -p libjxl-0.8.2/build
|
||||||
|
- name: Configure libjxl
|
||||||
|
working-directory: libjxl-0.8.2/build
|
||||||
|
run: |
|
||||||
|
cmake -DBUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DJPEGXL_ENABLE_BENCHMARK=OFF \
|
||||||
|
-DJPEGXL_ENABLE_COVERAGE=OFF -DJPEGXL_ENABLE_FUZZERS=OFF -DJPEGXL_ENABLE_SJPEG=OFF -DJPEGXL_WARNINGS_AS_ERRORS=OFF \
|
||||||
|
-DJPEGXL_ENABLE_SKCMS=OFF -DJPEGXL_ENABLE_VIEWERS=OFF -DJPEGXL_ENABLE_PLUGINS=OFF -DJPEGXL_ENABLE_DOXYGEN=OFF \
|
||||||
|
-DJPEGXL_ENABLE_MANPAGES=OFF -DJPEGXL_ENABLE_JNI=OFF -DJPEGXL_ENABLE_JPEGLI_LIBJPEG=OFF -DJPEGXL_ENABLE_TCMALLOC=OFF \
|
||||||
|
-DJPEGXL_ENABLE_EXAMPLES=OFF -DJPEGXL_ENABLE_TOOLS=OFF -DJPEGXL_ENABLE_OPENEXR=OFF -DBUILD_TESTING=OFF \
|
||||||
|
-DJXL_HWY_DISABLED_TARGETS_FORCED=ON -DJPEGXL_FORCE_SYSTEM_BROTLI=ON -DJPEGXL_FORCE_SYSTEM_HWY=ON ../
|
||||||
|
- name: Install libjxl
|
||||||
|
working-directory: libjxl-0.8.2/build
|
||||||
|
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-lcms --without-lqr --without-lzma --without-openexr --without-pango --without-raw --without-rsvg --without-wmf \
|
||||||
|
--without-xml --disable-openmp --with-jpeg --with-heic --with-jxl --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@v3
|
||||||
|
with:
|
||||||
|
go-version: 1.21
|
||||||
|
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
|
- name: Test
|
||||||
|
run: go test
|
||||||
@@ -6,38 +6,43 @@ CBconvert is a [Comic Book](http://en.wikipedia.org/wiki/Comic_Book_Archive_file
|
|||||||
|
|
||||||
It can convert comics to different formats to fit your various devices.
|
It can convert comics to different formats to fit your various devices.
|
||||||
|
|
||||||
|
<img src="cmd/cbconvert-gui/screenshots/linux-01.jpg" width="700" alt="screenshot" />
|
||||||
|
|
||||||
|
See more [screenshots](https://github.com/gen2brain/cbconvert/blob/master/cmd/cbconvert-gui/screenshots/).
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|
||||||
* reads RAR, ZIP, 7Z, CBR, CBZ, CB7, CBT, PDF, EPUB, and plain directory
|
* reads CBR (RAR), CBZ (ZIP), CB7 (7Z), CBT (TAR), PDF, XPS, EPUB, MOBI and plain directory
|
||||||
* always saves processed comics in CBZ (ZIP) archive format
|
* saves processed files in ZIP archive format or TAR
|
||||||
* images can be converted to JPEG, PNG, TIFF, WEBP, AVIF, or 4-Bit BMP (16 colors) file format
|
* images can be converted to JPEG, PNG, TIFF, WEBP, AVIF, JXL, or 4-Bit BMP (16 colors) image format
|
||||||
* rotate, flip, adjust brightness/contrast, adjust levels (Photoshop-like) or grayscale images
|
* rotate, adjust brightness/contrast, adjust levels (Photoshop-like) or grayscale images
|
||||||
* resize algorithms (NearestNeighbor, Box, Linear, MitchellNetravali, CatmullRom, Gaussian, Lanczos)
|
* resize filters (NearestNeighbor, Box, Linear, MitchellNetravali, CatmullRom, Gaussian, Lanczos)
|
||||||
* export covers from comics
|
* 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
|
### Download
|
||||||
|
|
||||||
* [Windows x86_64](https://github.com/gen2brain/cbconvert/releases/download/0.8.1/cbconvert-0.8.1-windows-x86_64.zip)
|
* [Windows x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-1.0.0-windows-x86_64.zip)
|
||||||
* [Linux x86_64](https://github.com/gen2brain/cbconvert/releases/download/0.8.1/cbconvert-0.8.1-linux-x86_64.tar.gz)
|
* [Linux x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-1.0.0-linux-x86_64.tar.gz)
|
||||||
* [Linux aarch64](https://github.com/gen2brain/cbconvert/releases/download/0.8.1/cbconvert-0.8.1-linux-aarch64.tar.gz)
|
* [macOS x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-1.0.0-darwin-x86_64.zip)
|
||||||
* [macOS x86_64](https://github.com/gen2brain/cbconvert/releases/download/0.8.1/cbconvert-0.8.1-darwin-x86_64.zip)
|
* [macOS aarch64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-1.0.0-darwin-aarch64.zip)
|
||||||
* [macOS aarch64](https://github.com/gen2brain/cbconvert/releases/download/0.8.1/cbconvert-0.8.1-darwin-aarch64.zip)
|
|
||||||
|
[](https://flathub.org/apps/io.github.gen2brain.cbconvert)
|
||||||
|
|
||||||
### Using cbconvert in file managers to generate FreeDesktop thumbnails
|
### Using cbconvert in file managers to generate FreeDesktop thumbnails
|
||||||
|
|
||||||
Copy cbconvert cli binary to your PATH and create file ~/.local/share/thumbnailers/cbconvert.thumbnailer:
|
Copy `cbconvert` cli binary to your PATH and create file `~/.local/share/thumbnailers/cbconvert.thumbnailer`:
|
||||||
|
|
||||||
```
|
```
|
||||||
[Thumbnailer Entry]
|
[Thumbnailer Entry]
|
||||||
TryExec=cbconvert
|
TryExec=cbconvert
|
||||||
Exec=cbconvert thumbnail --quiet --width %s --outfile %o %i
|
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;application/vnd.ms-xpsdocument;
|
||||||
```
|
```
|
||||||
|
|
||||||
This is what it looks like in the PCManFM file manager:
|
This is what it looks like in the PCManFM file manager:
|
||||||
|
|
||||||

|
<img src="cmd/cbconvert/screenshots/thumbnails.jpg" width="700" alt="thumbnails" />
|
||||||
|
|
||||||
|
|
||||||
### Using command line app
|
### Using command line app
|
||||||
@@ -48,8 +53,8 @@ This is what it looks like in the PCManFM file manager:
|
|||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
|
|
||||||
convert*
|
convert
|
||||||
Convert archive or document (default command)
|
Convert archive or document
|
||||||
|
|
||||||
--width
|
--width
|
||||||
Image width (default "0")
|
Image width (default "0")
|
||||||
@@ -58,11 +63,11 @@ This is what it looks like in the PCManFM file manager:
|
|||||||
--fit
|
--fit
|
||||||
Best fit for required width and height (default "false")
|
Best fit for required width and height (default "false")
|
||||||
--format
|
--format
|
||||||
Image format, valid values are jpeg, png, tiff, bmp, webp, avif (default "jpeg")
|
Image format, valid values are jpeg, png, tiff, bmp, webp, avif, jxl (default "jpeg")
|
||||||
|
--archive
|
||||||
|
Archive format, valid values are zip, tar (default "zip")
|
||||||
--quality
|
--quality
|
||||||
Image quality (default "75")
|
Image quality (default "75")
|
||||||
--lossless
|
|
||||||
Lossless compression (avif) (default "false")
|
|
||||||
--filter
|
--filter
|
||||||
0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos (default "2")
|
0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos (default "2")
|
||||||
--no-cover
|
--no-cover
|
||||||
@@ -77,8 +82,6 @@ This is what it looks like in the PCManFM file manager:
|
|||||||
Convert images to grayscale (monochromatic) (default "false")
|
Convert images to grayscale (monochromatic) (default "false")
|
||||||
--rotate
|
--rotate
|
||||||
Rotate images, valid values are 0, 90, 180, 270 (default "0")
|
Rotate images, valid values are 0, 90, 180, 270 (default "0")
|
||||||
--flip
|
|
||||||
Flip images, valid values are none, horizontal, vertical (default "none")
|
|
||||||
--brightness
|
--brightness
|
||||||
Adjust the brightness of the images, must be in the range (-100, 100) (default "0")
|
Adjust the brightness of the images, must be in the range (-100, 100) (default "0")
|
||||||
--contrast
|
--contrast
|
||||||
@@ -113,8 +116,10 @@ This is what it looks like in the PCManFM file manager:
|
|||||||
Image height (default "0")
|
Image height (default "0")
|
||||||
--fit
|
--fit
|
||||||
Best fit for required width and height (default "false")
|
Best fit for required width and height (default "false")
|
||||||
|
--format
|
||||||
|
Image format, valid values are jpeg, png, tiff, bmp, webp, avif, jxl (default "jpeg")
|
||||||
--quality
|
--quality
|
||||||
JPEG image quality (default "75")
|
Image quality (default "75")
|
||||||
--filter
|
--filter
|
||||||
0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos (default "2")
|
0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos (default "2")
|
||||||
--outdir
|
--outdir
|
||||||
@@ -147,30 +152,59 @@ This is what it looks like in the PCManFM file manager:
|
|||||||
Process subdirectories recursively (default "false")
|
Process subdirectories recursively (default "false")
|
||||||
--quiet
|
--quiet
|
||||||
Hide console output (default "false")
|
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
|
### 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/`
|
`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.
|
[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:
|
* Extract covers to ~/covers dir for all supported files found in the directory, Lanczos algorithm is used for resizing:
|
||||||
|
|
||||||
`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:
|
|
||||||
|
|
||||||
`cbconvert cover --outdir ~/covers --filter=7 /media/comics/GrooTheWanderer/`
|
`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
|
### Compile
|
||||||
|
|
||||||
Install ImageMagick7 and libheif (with libaom) libraries and headers and then install to GOBIN:
|
Install ImageMagick7 (with libheif/libjxl support) and MuPDF 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`
|
||||||
|
|
||||||
|
For GUI app, check [IUP requirements](https://github.com/gen2brain/iup-go), and then install:
|
||||||
|
|
||||||
|
`go install -tags extlib github.com/gen2brain/cbconvert/cmd/cbconvert-gui@latest`
|
||||||
|
|||||||
@@ -0,0 +1,422 @@
|
|||||||
|
package cbconvert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"archive/tar"
|
||||||
|
"archive/zip"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/gen2brain/go-unarr"
|
||||||
|
)
|
||||||
|
|
||||||
|
// archiveSave saves workdir to CBZ archive.
|
||||||
|
func (c *Converter) archiveSave(fileName string) error {
|
||||||
|
if c.Opts.Archive == "zip" {
|
||||||
|
return c.archiveSaveZip(fileName)
|
||||||
|
} else if c.Opts.Archive == "tar" {
|
||||||
|
return c.archiveSaveTar(fileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// archiveSaveZip saves workdir to CBZ archive.
|
||||||
|
func (c *Converter) archiveSaveZip(fileName string) error {
|
||||||
|
if c.OnCompress != nil {
|
||||||
|
c.OnCompress()
|
||||||
|
}
|
||||||
|
|
||||||
|
var zipName string
|
||||||
|
if c.Opts.Recursive {
|
||||||
|
err := os.MkdirAll(filepath.Join(c.Opts.OutDir, filepath.Dir(fileName)), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
zipName = filepath.Join(c.Opts.OutDir, filepath.Dir(fileName), fmt.Sprintf("%s%s.cbz", baseNoExt(fileName), c.Opts.Suffix))
|
||||||
|
} else {
|
||||||
|
zipName = filepath.Join(c.Opts.OutDir, fmt.Sprintf("%s%s.cbz", baseNoExt(fileName), c.Opts.Suffix))
|
||||||
|
}
|
||||||
|
|
||||||
|
zipFile, err := os.Create(zipName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
z := zip.NewWriter(zipFile)
|
||||||
|
|
||||||
|
files, err := os.ReadDir(c.Workdir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
r, err := os.ReadFile(filepath.Join(c.Workdir, file.Name()))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := file.Info()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
zipInfo, err := zip.FileInfoHeader(info)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
zipInfo.Method = zip.Deflate
|
||||||
|
w, err := z.CreateHeader(zipInfo)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(r)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = z.Close(); err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = zipFile.Close(); err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.RemoveAll(c.Workdir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveZip: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// archiveSaveTar saves workdir to CBT archive.
|
||||||
|
func (c *Converter) archiveSaveTar(fileName string) error {
|
||||||
|
if c.OnCompress != nil {
|
||||||
|
c.OnCompress()
|
||||||
|
}
|
||||||
|
|
||||||
|
var tarName string
|
||||||
|
if c.Opts.Recursive {
|
||||||
|
err := os.MkdirAll(filepath.Join(c.Opts.OutDir, filepath.Dir(fileName)), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tarName = filepath.Join(c.Opts.OutDir, filepath.Dir(fileName), fmt.Sprintf("%s%s.cbt", baseNoExt(fileName), c.Opts.Suffix))
|
||||||
|
} else {
|
||||||
|
tarName = filepath.Join(c.Opts.OutDir, fmt.Sprintf("%s%s.cbt", baseNoExt(fileName), c.Opts.Suffix))
|
||||||
|
}
|
||||||
|
|
||||||
|
tarFile, err := os.Create(tarName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tw := tar.NewWriter(tarFile)
|
||||||
|
|
||||||
|
files, err := os.ReadDir(c.Workdir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
r, err := os.ReadFile(filepath.Join(c.Workdir, file.Name()))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := file.Info()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
header, err := tar.FileInfoHeader(info, info.Name())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = tw.WriteHeader(header)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tw.Write(r)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tw.Close(); err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = tarFile.Close(); err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.RemoveAll(c.Workdir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSaveTar: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// archiveList lists contents of archive.
|
||||||
|
func (c *Converter) archiveList(fileName string) ([]string, error) {
|
||||||
|
var contents []string
|
||||||
|
|
||||||
|
archive, err := unarr.NewArchive(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return contents, fmt.Errorf("archiveList: %w", err)
|
||||||
|
}
|
||||||
|
defer archive.Close()
|
||||||
|
|
||||||
|
contents, err = archive.List()
|
||||||
|
if err != nil {
|
||||||
|
return contents, fmt.Errorf("archiveList: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return contents, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// archiveComment returns ZIP comment.
|
||||||
|
func (c *Converter) archiveComment(fileName string) (string, error) {
|
||||||
|
zr, err := zip.OpenReader(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("archiveComment: %w", err)
|
||||||
|
}
|
||||||
|
defer zr.Close()
|
||||||
|
|
||||||
|
return zr.Comment, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// archiveSetComment sets ZIP comment.
|
||||||
|
func (c *Converter) archiveSetComment(fileName, commentBody string) error {
|
||||||
|
zr, err := zip.OpenReader(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
defer zr.Close()
|
||||||
|
|
||||||
|
zf, err := os.CreateTemp(os.TempDir(), "cbc")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpName := zf.Name()
|
||||||
|
defer os.Remove(tmpName)
|
||||||
|
|
||||||
|
zw := zip.NewWriter(zf)
|
||||||
|
err = zw.SetComment(commentBody)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, item := range zr.File {
|
||||||
|
ir, err := item.OpenRaw()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
item := item
|
||||||
|
|
||||||
|
it, err := zw.CreateRaw(&item.FileHeader)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(it, ir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = zw.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = zf.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := os.ReadFile(tmpName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(fileName, data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveSetComment: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// archiveFileAdd adds file to archive.
|
||||||
|
func (c *Converter) archiveFileAdd(fileName, newFileName string) error {
|
||||||
|
zr, err := zip.OpenReader(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
defer zr.Close()
|
||||||
|
|
||||||
|
zf, err := os.CreateTemp(os.TempDir(), "cbc")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpName := zf.Name()
|
||||||
|
defer os.Remove(tmpName)
|
||||||
|
|
||||||
|
zw := zip.NewWriter(zf)
|
||||||
|
|
||||||
|
for _, item := range zr.File {
|
||||||
|
if item.Name == newFileName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ir, err := item.OpenRaw()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
item := item
|
||||||
|
|
||||||
|
it, err := zw.CreateRaw(&item.FileHeader)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(it, ir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info, err := os.Stat(newFileName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
newData, err := os.ReadFile(newFileName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
zipInfo, err := zip.FileInfoHeader(info)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
zipInfo.Method = zip.Deflate
|
||||||
|
w, err := zw.CreateHeader(zipInfo)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = w.Write(newData)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = zw.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = zf.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := os.ReadFile(tmpName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(fileName, data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileAdd: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// archiveFileRemove removes files from archive.
|
||||||
|
func (c *Converter) archiveFileRemove(fileName, pattern string) error {
|
||||||
|
zr, err := zip.OpenReader(fileName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
defer zr.Close()
|
||||||
|
|
||||||
|
zf, err := os.CreateTemp(os.TempDir(), "cbc")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpName := zf.Name()
|
||||||
|
defer os.Remove(tmpName)
|
||||||
|
|
||||||
|
zw := zip.NewWriter(zf)
|
||||||
|
|
||||||
|
for _, item := range zr.File {
|
||||||
|
matched, err := filepath.Match(pattern, item.Name)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if matched {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ir, err := item.OpenRaw()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
item := item
|
||||||
|
|
||||||
|
it, err := zw.CreateRaw(&item.FileHeader)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = io.Copy(it, ir)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err = zw.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = zf.Close()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := os.ReadFile(tmpName)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = os.WriteFile(fileName, data, 0644)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("archiveFileRemove: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
package cbconvert
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"image"
|
||||||
|
"image/color"
|
||||||
|
"image/draw"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
// imageToRGBA converts an image.Image to *image.RGBA.
|
||||||
|
func imageToRGBA(src image.Image) *image.RGBA {
|
||||||
|
if dst, ok := src.(*image.RGBA); ok {
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
b := src.Bounds()
|
||||||
|
dst := image.NewRGBA(b)
|
||||||
|
draw.Draw(dst, dst.Bounds(), src, b.Min, draw.Src)
|
||||||
|
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// imageToGray converts an image.Image to *image.Gray.
|
||||||
|
func imageToGray(src image.Image) *image.Gray {
|
||||||
|
if dst, ok := src.(*image.Gray); ok {
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
b := src.Bounds()
|
||||||
|
dst := image.NewGray(b)
|
||||||
|
draw.Draw(dst, dst.Bounds(), src, b.Min, draw.Src)
|
||||||
|
|
||||||
|
return dst
|
||||||
|
}
|
||||||
|
|
||||||
|
// imagesFromPath returns list of found image files for given directory.
|
||||||
|
func imagesFromPath(path string) ([]string, error) {
|
||||||
|
var images []string
|
||||||
|
|
||||||
|
walkFiles := func(fp string, f os.FileInfo, err error) error {
|
||||||
|
if !f.IsDir() && f.Mode()&os.ModeType == 0 {
|
||||||
|
if f.Size() > 0 && (isImage(fp)) {
|
||||||
|
images = append(images, fp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := filepath.Abs(path)
|
||||||
|
if err != nil {
|
||||||
|
return images, fmt.Errorf("imagesFromPath: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stat, err := os.Stat(f)
|
||||||
|
if err != nil {
|
||||||
|
return images, fmt.Errorf("imagesFromPath: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !stat.IsDir() && stat.Mode()&os.ModeType == 0 {
|
||||||
|
if isImage(f) {
|
||||||
|
images = append(images, f)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err = filepath.Walk(f, walkFiles)
|
||||||
|
if err != nil {
|
||||||
|
return images, fmt.Errorf("imagesFromPath: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return images, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// imagesFromSlice returns list of found image files for given slice of files.
|
||||||
|
func imagesFromSlice(files []string) []string {
|
||||||
|
var images []string
|
||||||
|
|
||||||
|
for _, f := range files {
|
||||||
|
if isImage(f) {
|
||||||
|
images = append(images, f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return images
|
||||||
|
}
|
||||||
|
|
||||||
|
// isArchive checks if file is archive.
|
||||||
|
func isArchive(f string) bool {
|
||||||
|
var types = []string{".rar", ".zip", ".7z", ".tar", ".cbr", ".cbz", ".cb7", ".cbt"}
|
||||||
|
for _, t := range types {
|
||||||
|
if strings.ToLower(filepath.Ext(f)) == t {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isDocument checks if file is document.
|
||||||
|
func isDocument(f string) bool {
|
||||||
|
var types = []string{".pdf", ".xps", ".epub", ".mobi"}
|
||||||
|
for _, t := range types {
|
||||||
|
if strings.ToLower(filepath.Ext(f)) == t {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isImage checks if file is image.
|
||||||
|
func isImage(f string) bool {
|
||||||
|
var types = []string{".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".tif", ".webp", ".avif", ".jxl"}
|
||||||
|
for _, t := range types {
|
||||||
|
if strings.ToLower(filepath.Ext(f)) == t {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isNonImage checks for allowed files in archive.
|
||||||
|
func isNonImage(f string) bool {
|
||||||
|
var types = []string{".nfo", ".xml", ".txt"}
|
||||||
|
for _, t := range types {
|
||||||
|
if strings.ToLower(filepath.Ext(f)) == t {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// isSize checks size of file.
|
||||||
|
func isSize(a, b int64) bool {
|
||||||
|
if a > 0 {
|
||||||
|
if b < int64(a)*(1024*1024) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// isGrayScale checks if image is grayscale.
|
||||||
|
func isGrayScale(img image.Image) bool {
|
||||||
|
model := img.ColorModel()
|
||||||
|
if model == color.GrayModel || model == color.Gray16Model {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// baseNoExt returns base name without extension.
|
||||||
|
func baseNoExt(filename string) string {
|
||||||
|
return strings.TrimSuffix(filepath.Base(filename), filepath.Ext(filename))
|
||||||
|
}
|
||||||
|
|
||||||
|
// copyFile copies reader to file.
|
||||||
|
func copyFile(reader io.Reader, filename string) error {
|
||||||
|
err := os.MkdirAll(filepath.Dir(filename), 0755)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("copyFile: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
file, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("copyFile: %w", err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
_, err = io.Copy(file, reader)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("copyFile: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
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 := NewOptions()
|
||||||
|
opts.OutDir = tmpDir
|
||||||
|
|
||||||
|
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", "jxl"} {
|
||||||
|
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 := NewOptions()
|
||||||
|
opts.OutDir = tmpDir
|
||||||
|
|
||||||
|
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 := NewOptions()
|
||||||
|
opts.OutDir = tmpDir
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,10 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=CBconvert
|
||||||
|
GenericName=A Comic Book converter
|
||||||
|
Comment=A comic converter with support for .cb*, .pdf, .xps, .epub, .mobi and directories.
|
||||||
|
Exec=cbconvert-gui
|
||||||
|
Icon=cbconvert
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
StartupNotify=true
|
||||||
|
Categories=Graphics;Utility;
|
||||||
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
[Thumbnailer Entry]
|
||||||
|
TryExec=cbconvert
|
||||||
|
Exec=cbconvert thumbnail --quiet --width %s --outfile %o %i
|
||||||
|
MimeType=application/pdf;application/x-cb7;application/x-cbt;application/epub+zip;application/vnd.comicbook-rar;application/vnd.comicbook+zip;application/x-mobipocket-ebook;application/vnd.ms-xpsdocument;
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Name=CBconvert
|
||||||
|
GenericName=A Comic Book converter
|
||||||
|
Comment=A comic converter with support for .cb*, .pdf, .xps, .epub, .mobi and directories
|
||||||
|
Exec=cbconvert
|
||||||
|
Icon=io.github.gen2brain.cbconvert
|
||||||
|
Terminal=false
|
||||||
|
Type=Application
|
||||||
|
StartupNotify=true
|
||||||
|
Categories=Graphics;
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<component type="desktop-application">
|
||||||
|
<id>io.github.gen2brain.cbconvert</id>
|
||||||
|
|
||||||
|
<name>CBconvert</name>
|
||||||
|
<developer_name>Milan Nikolic</developer_name>
|
||||||
|
<summary>A Comic Book converter</summary>
|
||||||
|
|
||||||
|
<metadata_license>MIT</metadata_license>
|
||||||
|
<project_license>GPL-3</project_license>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
A comic book converter with support for .cb*, .pdf, .xps, .epub, .mobi and directories.
|
||||||
|
Images can be converted to JPEG, PNG, TIFF, WEBP, AVIF, JXL or 4-Bit BMP (16 colors) file format.
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<launchable type="desktop-id">io.github.gen2brain.cbconvert.desktop</launchable>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default">
|
||||||
|
<image>https://raw.githubusercontent.com/gen2brain/cbconvert/master/cmd/cbconvert-gui/screenshots/linux-02.jpg</image>
|
||||||
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image>https://raw.githubusercontent.com/gen2brain/cbconvert/master/cmd/cbconvert-gui/screenshots/linux-01.jpg</image>
|
||||||
|
</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
|
||||||
|
<url type="homepage">https://github.com/gen2brain/cbconvert</url>
|
||||||
|
<url type="bugtracker">https://github.com/gen2brain/cbconvert/issues</url>
|
||||||
|
|
||||||
|
<content_rating type="oars-1.1"/>
|
||||||
|
|
||||||
|
<releases>
|
||||||
|
<release version="1.0.4" date="2024-02-08" type="stable">
|
||||||
|
<description>
|
||||||
|
<ul>
|
||||||
|
<li>Update modules and dependencies</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<url type="details">https://github.com/gen2brain/cbconvert/releases/tag/v1.0.4</url>
|
||||||
|
</release>
|
||||||
|
<release version="1.0.3" date="2023-09-14" type="stable">
|
||||||
|
<description>
|
||||||
|
<ul>
|
||||||
|
<li>Add content rating</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<url type="details">https://github.com/gen2brain/cbconvert/releases/tag/v1.0.3</url>
|
||||||
|
</release>
|
||||||
|
<release version="1.0.2" date="2023-09-14" type="stable">
|
||||||
|
<description>
|
||||||
|
<ul>
|
||||||
|
<li>Change flatpak exec/command name to cbconvert</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<url type="details">https://github.com/gen2brain/cbconvert/releases/tag/v1.0.2</url>
|
||||||
|
</release>
|
||||||
|
<release version="1.0.1" date="2023-09-14" type="stable">
|
||||||
|
<description>
|
||||||
|
<ul>
|
||||||
|
<li>Add flatpak manifest</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<url type="details">https://github.com/gen2brain/cbconvert/releases/tag/v1.0.1</url>
|
||||||
|
</release>
|
||||||
|
<release version="1.0.0" date="2023-09-14" type="stable">
|
||||||
|
<description>
|
||||||
|
<ul>
|
||||||
|
<li>Add GUI</li>
|
||||||
|
<li>Add support for JPEG XL</li>
|
||||||
|
</ul>
|
||||||
|
</description>
|
||||||
|
<url type="details">https://github.com/gen2brain/cbconvert/releases/tag/v1.0.0</url>
|
||||||
|
</release>
|
||||||
|
</releases>
|
||||||
|
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
# git.sr.ht/~jackmordaunt/go-libwebp v1.1.0
|
||||||
|
## explicit; go 1.21
|
||||||
|
git.sr.ht/~jackmordaunt/go-libwebp/lib/common
|
||||||
|
git.sr.ht/~jackmordaunt/go-libwebp/lib/dynamic/webp
|
||||||
|
git.sr.ht/~jackmordaunt/go-libwebp/lib/transpiled/webp
|
||||||
|
git.sr.ht/~jackmordaunt/go-libwebp/webp
|
||||||
|
# github.com/disintegration/imaging v1.6.2
|
||||||
|
## explicit
|
||||||
|
github.com/disintegration/imaging
|
||||||
|
# github.com/dustin/go-humanize v1.0.1
|
||||||
|
## explicit; go 1.16
|
||||||
|
github.com/dustin/go-humanize
|
||||||
|
# github.com/ebitengine/purego v0.5.2
|
||||||
|
## explicit; go 1.18
|
||||||
|
github.com/ebitengine/purego
|
||||||
|
github.com/ebitengine/purego/internal/cgo
|
||||||
|
github.com/ebitengine/purego/internal/fakecgo
|
||||||
|
github.com/ebitengine/purego/internal/strings
|
||||||
|
# github.com/fvbommel/sortorder v1.1.0
|
||||||
|
## explicit; go 1.13
|
||||||
|
github.com/fvbommel/sortorder
|
||||||
|
# github.com/gen2brain/cbconvert v1.0.4-0.20240208144735-a8084ed89758
|
||||||
|
## explicit; go 1.21
|
||||||
|
github.com/gen2brain/cbconvert
|
||||||
|
# github.com/gen2brain/go-fitz v1.23.7
|
||||||
|
## explicit; go 1.20
|
||||||
|
github.com/gen2brain/go-fitz
|
||||||
|
# github.com/gen2brain/go-unarr v0.2.0
|
||||||
|
## explicit; go 1.19
|
||||||
|
github.com/gen2brain/go-unarr
|
||||||
|
github.com/gen2brain/go-unarr/unarrc
|
||||||
|
# github.com/gen2brain/iup-go/iup v0.0.0-20230906093706-8b037fe6a7bd
|
||||||
|
## explicit; go 1.19
|
||||||
|
github.com/gen2brain/iup-go/iup
|
||||||
|
github.com/gen2brain/iup-go/iup/manifest
|
||||||
|
# github.com/godbus/dbus/v5 v5.1.0
|
||||||
|
## explicit; go 1.12
|
||||||
|
github.com/godbus/dbus/v5
|
||||||
|
# github.com/google/uuid v1.6.0
|
||||||
|
## explicit
|
||||||
|
github.com/google/uuid
|
||||||
|
# github.com/mattn/go-isatty v0.0.20
|
||||||
|
## explicit; go 1.15
|
||||||
|
github.com/mattn/go-isatty
|
||||||
|
# github.com/ncruces/go-strftime v0.1.9
|
||||||
|
## explicit; go 1.17
|
||||||
|
github.com/ncruces/go-strftime
|
||||||
|
# github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec
|
||||||
|
## explicit; go 1.12
|
||||||
|
github.com/remyoudompheng/bigfft
|
||||||
|
# golang.org/x/image v0.15.0
|
||||||
|
## explicit; go 1.18
|
||||||
|
golang.org/x/image/bmp
|
||||||
|
golang.org/x/image/ccitt
|
||||||
|
golang.org/x/image/riff
|
||||||
|
golang.org/x/image/tiff
|
||||||
|
golang.org/x/image/tiff/lzw
|
||||||
|
golang.org/x/image/vp8
|
||||||
|
golang.org/x/image/vp8l
|
||||||
|
golang.org/x/image/webp
|
||||||
|
# golang.org/x/sync v0.6.0
|
||||||
|
## explicit; go 1.18
|
||||||
|
golang.org/x/sync/errgroup
|
||||||
|
# golang.org/x/sys v0.17.0
|
||||||
|
## explicit; go 1.18
|
||||||
|
golang.org/x/sys/unix
|
||||||
|
golang.org/x/sys/windows
|
||||||
|
# gopkg.in/gographics/imagick.v3 v3.5.1
|
||||||
|
## explicit; go 1.13
|
||||||
|
gopkg.in/gographics/imagick.v3/imagick
|
||||||
|
gopkg.in/gographics/imagick.v3/imagick/types
|
||||||
|
# modernc.org/libc v1.41.0
|
||||||
|
## explicit; go 1.20
|
||||||
|
modernc.org/libc
|
||||||
|
modernc.org/libc/errno
|
||||||
|
modernc.org/libc/fcntl
|
||||||
|
modernc.org/libc/fts
|
||||||
|
modernc.org/libc/grp
|
||||||
|
modernc.org/libc/honnef.co/go/netdb
|
||||||
|
modernc.org/libc/langinfo
|
||||||
|
modernc.org/libc/limits
|
||||||
|
modernc.org/libc/netdb
|
||||||
|
modernc.org/libc/netinet/in
|
||||||
|
modernc.org/libc/poll
|
||||||
|
modernc.org/libc/pthread
|
||||||
|
modernc.org/libc/pwd
|
||||||
|
modernc.org/libc/signal
|
||||||
|
modernc.org/libc/stdio
|
||||||
|
modernc.org/libc/stdlib
|
||||||
|
modernc.org/libc/sys/socket
|
||||||
|
modernc.org/libc/sys/stat
|
||||||
|
modernc.org/libc/sys/types
|
||||||
|
modernc.org/libc/termios
|
||||||
|
modernc.org/libc/time
|
||||||
|
modernc.org/libc/unistd
|
||||||
|
modernc.org/libc/utime
|
||||||
|
modernc.org/libc/uuid
|
||||||
|
modernc.org/libc/uuid/uuid
|
||||||
|
modernc.org/libc/wctype
|
||||||
|
# modernc.org/mathutil v1.6.0
|
||||||
|
## explicit; go 1.18
|
||||||
|
modernc.org/mathutil
|
||||||
|
# modernc.org/memory v1.7.2
|
||||||
|
## explicit; go 1.18
|
||||||
|
modernc.org/memory
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>English</string>
|
||||||
|
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>cbconvert-gui</string>
|
||||||
|
|
||||||
|
<key>CFBundleIconFile</key>
|
||||||
|
<string>icon</string>
|
||||||
|
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>com.github.gen2brain.cbconvert</string>
|
||||||
|
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>CBconvert</string>
|
||||||
|
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>APPL</string>
|
||||||
|
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0.0</string>
|
||||||
|
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
|
||||||
|
<key>NSHighResolutionCapable</key>
|
||||||
|
<string>True</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>BuildMachineOSBuild</key>
|
||||||
|
<string>19H2</string>
|
||||||
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
|
<string>en</string>
|
||||||
|
<key>CFBundleExecutable</key>
|
||||||
|
<string>iup</string>
|
||||||
|
<key>CFBundleIdentifier</key>
|
||||||
|
<string>br.puc-rio.tecgraf.iup</string>
|
||||||
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
|
<string>6.0</string>
|
||||||
|
<key>CFBundleName</key>
|
||||||
|
<string>iup</string>
|
||||||
|
<key>CFBundlePackageType</key>
|
||||||
|
<string>FMWK</string>
|
||||||
|
<key>CFBundleShortVersionString</key>
|
||||||
|
<string>1.0</string>
|
||||||
|
<key>CFBundleSignature</key>
|
||||||
|
<string>????</string>
|
||||||
|
<key>CFBundleSupportedPlatforms</key>
|
||||||
|
<array>
|
||||||
|
<string>MacOSX</string>
|
||||||
|
</array>
|
||||||
|
<key>CFBundleVersion</key>
|
||||||
|
<string>1</string>
|
||||||
|
<key>DTCompiler</key>
|
||||||
|
<string>com.apple.compilers.llvm.clang.1_0</string>
|
||||||
|
<key>DTPlatformBuild</key>
|
||||||
|
<string>12D4e</string>
|
||||||
|
<key>DTPlatformName</key>
|
||||||
|
<string>macosx</string>
|
||||||
|
<key>DTPlatformVersion</key>
|
||||||
|
<string>11.1</string>
|
||||||
|
<key>DTSDKBuild</key>
|
||||||
|
<string>20C63</string>
|
||||||
|
<key>DTSDKName</key>
|
||||||
|
<string>macosx11.1</string>
|
||||||
|
<key>DTXcode</key>
|
||||||
|
<string>1240</string>
|
||||||
|
<key>DTXcodeBuild</key>
|
||||||
|
<string>12D4e</string>
|
||||||
|
<key>LSMinimumSystemVersion</key>
|
||||||
|
<string>10.14</string>
|
||||||
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
<string>Copyright © 2015 Tecgraf, PUC-Rio, Brazil. All rights reserved.</string>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,30 @@
|
|||||||
|
module github.com/gen2brain/cbconvert/cmd/cbconvert-gui
|
||||||
|
|
||||||
|
go 1.21
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gen2brain/cbconvert v1.0.4-0.20240208144735-a8084ed89758
|
||||||
|
github.com/gen2brain/iup-go/iup v0.0.0-20230906093706-8b037fe6a7bd
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0
|
||||||
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
git.sr.ht/~jackmordaunt/go-libwebp v1.1.0 // indirect
|
||||||
|
github.com/disintegration/imaging v1.6.2 // indirect
|
||||||
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
|
github.com/ebitengine/purego v0.5.2 // indirect
|
||||||
|
github.com/fvbommel/sortorder v1.1.0 // indirect
|
||||||
|
github.com/gen2brain/go-fitz v1.23.7 // indirect
|
||||||
|
github.com/gen2brain/go-unarr v0.2.0 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
golang.org/x/image v0.15.0 // indirect
|
||||||
|
golang.org/x/sync v0.6.0 // indirect
|
||||||
|
golang.org/x/sys v0.17.0 // indirect
|
||||||
|
gopkg.in/gographics/imagick.v3 v3.5.1 // indirect
|
||||||
|
modernc.org/libc v1.41.0 // indirect
|
||||||
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
|
modernc.org/memory v1.7.2 // indirect
|
||||||
|
)
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
git.sr.ht/~jackmordaunt/go-libwebp v1.1.0 h1:rfDv89tb6OuNp8f1TyprOZWaeC/TxqaYvLCI6nHKBY8=
|
||||||
|
git.sr.ht/~jackmordaunt/go-libwebp v1.1.0/go.mod h1:8557wZRj8KWRPBM+osAuAXVVR5nVURZ3SCG5rnACBdE=
|
||||||
|
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/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/ebitengine/purego v0.5.2 h1:r2MQEtkGzZ4LRtFZVAg5bjYKnUbxxloaeuGxH0t7qfs=
|
||||||
|
github.com/ebitengine/purego v0.5.2/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
|
||||||
|
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 v1.0.4-0.20240208144735-a8084ed89758 h1:VXWir2Nq5qkXuIeoCTavOlQ7j2Yab0vIJe1mvKsLe3I=
|
||||||
|
github.com/gen2brain/cbconvert v1.0.4-0.20240208144735-a8084ed89758/go.mod h1:jtc/vKGuG66vIemtQc6Ge69FXo33hX+gFvGtEP/z/SM=
|
||||||
|
github.com/gen2brain/go-fitz v1.23.7 h1:HPhzEVzmOINvCKqQgB/DwMzYh4ArIgy3tMwq1eJTcbg=
|
||||||
|
github.com/gen2brain/go-fitz v1.23.7/go.mod h1:HU04vc+RisUh/kvEd2pB0LAxmK1oyXdN4ftyshUr9rQ=
|
||||||
|
github.com/gen2brain/go-unarr v0.2.0 h1:sYKSjbeNSuZgudd59iGAbMbr113XRFoA7Rt9XWA+QVE=
|
||||||
|
github.com/gen2brain/go-unarr v0.2.0/go.mod h1:hoHheVuf0KT8/hfvkEL7GMwj2h7fq0lF72NdyySdr3c=
|
||||||
|
github.com/gen2brain/iup-go/iup v0.0.0-20230906093706-8b037fe6a7bd h1:k1EaRqSEu/2eahOBY44uYZevryE1HQBz0t7RYCufnHI=
|
||||||
|
github.com/gen2brain/iup-go/iup v0.0.0-20230906093706-8b037fe6a7bd/go.mod h1:HeMeojpQFldBWCMmU5dkmU640AdEcS+SPyEVLMJjjrw=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
|
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
|
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
|
||||||
|
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||||
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||||
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
gopkg.in/gographics/imagick.v3 v3.5.1 h1:58JqK0UCx5RfvbRggF5FKuK6jHwAtTQopUxK8mzFa40=
|
||||||
|
gopkg.in/gographics/imagick.v3 v3.5.1/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA=
|
||||||
|
modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk=
|
||||||
|
modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY=
|
||||||
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
|
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
|
||||||
|
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
//go:build !portal
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/gen2brain/iup-go/iup"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fileDlg(title string, multiple, directory bool) ([]string, error) {
|
||||||
|
ret := make([]string, 0)
|
||||||
|
|
||||||
|
dlg := iup.FileDlg()
|
||||||
|
defer dlg.Destroy()
|
||||||
|
|
||||||
|
if !directory {
|
||||||
|
mf := "YES"
|
||||||
|
if !multiple {
|
||||||
|
mf = "NO"
|
||||||
|
}
|
||||||
|
|
||||||
|
dlg.SetAttributes(map[string]string{
|
||||||
|
"DIALOGTYPE": "OPEN",
|
||||||
|
"MULTIPLEFILES": mf,
|
||||||
|
"EXTFILTER": "Comic Files|*.rar;*.zip;*.7z;*.tar;*.cbr;*.cbz;*.cb7;*.cbt;*.pdf;*.epub;*.mobi;*.xps|",
|
||||||
|
"FILTER": "*.cb*", // for Motif
|
||||||
|
"TITLE": title,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
dlg.SetAttributes(map[string]string{
|
||||||
|
"DIALOGTYPE": "DIR",
|
||||||
|
"TITLE": title,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
iup.Popup(dlg, iup.CENTERPARENT, iup.CENTERPARENT)
|
||||||
|
|
||||||
|
if dlg.GetInt("STATUS") == 0 {
|
||||||
|
if !directory {
|
||||||
|
value := dlg.GetAttribute("VALUE")
|
||||||
|
sp := strings.Split(value, "|")
|
||||||
|
|
||||||
|
if strings.ToLower(iup.GetGlobal("DRIVER")) == "cocoa" {
|
||||||
|
for _, file := range sp {
|
||||||
|
ret = append(ret, file)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if len(sp) > 1 {
|
||||||
|
for _, file := range sp[1 : len(sp)-1] {
|
||||||
|
ret = append(ret, filepath.Join(sp[0], file))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret = append(ret, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value := dlg.GetAttribute("VALUE")
|
||||||
|
ret = append(ret, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
//go:build portal
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"github.com/godbus/dbus/v5"
|
||||||
|
)
|
||||||
|
|
||||||
|
func fileDlg(title string, multiple, directory bool) ([]string, error) {
|
||||||
|
ret := make([]string, 0)
|
||||||
|
|
||||||
|
conn, err := dbus.ConnectSessionBus()
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
dest := "org.freedesktop.portal.Desktop"
|
||||||
|
path := "/org/freedesktop/portal/desktop"
|
||||||
|
resp := "org.freedesktop.portal.Request.Response"
|
||||||
|
|
||||||
|
if err = conn.AddMatchSignal(
|
||||||
|
dbus.WithMatchInterface(dest),
|
||||||
|
dbus.WithMatchObjectPath(dbus.ObjectPath(path)),
|
||||||
|
dbus.WithMatchSender(conn.Names()[0]),
|
||||||
|
); err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
c := make(chan *dbus.Signal, 10)
|
||||||
|
conn.Signal(c)
|
||||||
|
|
||||||
|
type Item struct {
|
||||||
|
Index uint32
|
||||||
|
Filter string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Filter struct {
|
||||||
|
Title string
|
||||||
|
Filters []Item
|
||||||
|
}
|
||||||
|
|
||||||
|
filters := []Filter{
|
||||||
|
{
|
||||||
|
"Comic Files",
|
||||||
|
[]Item{
|
||||||
|
Item{0, "*.rar"},
|
||||||
|
Item{0, "*.zip"},
|
||||||
|
Item{0, "*.7z"},
|
||||||
|
Item{0, "*.tar"},
|
||||||
|
Item{0, "*.cbr"},
|
||||||
|
Item{0, "*.cbz"},
|
||||||
|
Item{0, "*.cb7"},
|
||||||
|
Item{0, "*.cbt"},
|
||||||
|
Item{0, "*.pdf"},
|
||||||
|
Item{0, "*.epub"},
|
||||||
|
Item{0, "*.mobi"},
|
||||||
|
Item{0, "*.xps"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
opts := map[string]any{
|
||||||
|
"multiple": multiple,
|
||||||
|
"directory": directory,
|
||||||
|
}
|
||||||
|
|
||||||
|
if !directory {
|
||||||
|
opts["filters"] = filters
|
||||||
|
}
|
||||||
|
|
||||||
|
obj := conn.Object(dest, dbus.ObjectPath(path))
|
||||||
|
call := obj.Call("org.freedesktop.portal.FileChooser.OpenFile", 0, "", title, opts)
|
||||||
|
if call.Err != nil {
|
||||||
|
return ret, call.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
for v := range c {
|
||||||
|
if v.Name != resp {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
status := v.Body[0].(uint32)
|
||||||
|
|
||||||
|
if status == 0 {
|
||||||
|
m := v.Body[1].(map[string]dbus.Variant)
|
||||||
|
uris := m["uris"].Value().([]string)
|
||||||
|
|
||||||
|
for _, uri := range uris {
|
||||||
|
u, err := url.ParseRequestURI(uri)
|
||||||
|
if err != nil {
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = append(ret, u.Path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
GLIBC_x86_64="/usr/x86_64-pc-linux-gnu-static"
|
||||||
|
MINGW_x86_64="/usr/x86_64-w64-mingw32"
|
||||||
|
MACOS_x86_64="/usr/x86_64-apple-darwin"
|
||||||
|
MACOS_aarch64="/usr/aarch64-apple-darwin"
|
||||||
|
|
||||||
|
VERSION="$(git --git-dir ../../.git describe --tags --abbrev=0 2>/dev/null || echo '1.0.0')"
|
||||||
|
|
||||||
|
BUILDDIR="cbconvert-gui-${VERSION}"
|
||||||
|
|
||||||
|
mkdir -p "${BUILDDIR}"
|
||||||
|
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 -x -o "${BUILDDIR}"/cbconvert-gui -ldflags "-s -w -X main.appVersion=${VERSION}" && \
|
||||||
|
cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && tar -czf "${BUILDDIR}-linux-x86_64.tar.gz" "${BUILDDIR}"
|
||||||
|
rm -rf "${BUILDDIR}"
|
||||||
|
|
||||||
|
mkdir -p "${BUILDDIR}"
|
||||||
|
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 -lxcb -lICE -lXdmcp -lXau -lSM" \
|
||||||
|
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \
|
||||||
|
go build -trimpath -tags 'extlib pkgconfig motif' -v -o "${BUILDDIR}"/cbconvert-gui-motif -ldflags "-s -w -linkmode external -X main.appVersion=${VERSION} '-extldflags=-static'" && \
|
||||||
|
cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && tar -czf "${BUILDDIR}-linux-x86_64-motif.tar.gz" "${BUILDDIR}"
|
||||||
|
rm -rf "${BUILDDIR}"
|
||||||
|
|
||||||
|
mkdir -p "${BUILDDIR}"
|
||||||
|
CC=x86_64-w64-mingw32-gcc \
|
||||||
|
PKG_CONFIG="/usr/bin/x86_64-w64-mingw32-pkg-config" \
|
||||||
|
PKG_CONFIG_PATH="$MINGW_x86_64/usr/lib/pkgconfig" \
|
||||||
|
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-gui.exe -ldflags "-s -w -X main.appVersion=${VERSION} -H=windowsgui '-extldflags=-static -Wl,--allow-multiple-definition'" && \
|
||||||
|
cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && zip -rq "${BUILDDIR}-windows-x86_64.zip" "${BUILDDIR}"
|
||||||
|
rm -rf "${BUILDDIR}"
|
||||||
|
|
||||||
|
export OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1
|
||||||
|
mkdir -p "${BUILDDIR}"
|
||||||
|
cp -r dist/macos/CBconvert.app "${BUILDDIR}"
|
||||||
|
PATH=${PATH}:${MACOS_x86_64}/bin \
|
||||||
|
CC=x86_64-apple-darwin21.1-clang \
|
||||||
|
PKG_CONFIG="x86_64-apple-darwin21.1-pkg-config" \
|
||||||
|
PKG_CONFIG_PATH="$MACOS_x86_64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
||||||
|
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.15" \
|
||||||
|
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 \
|
||||||
|
go build -trimpath -tags 'extlib pkgconfig' -v -o "${BUILDDIR}"/CBconvert.app/Contents/MacOS/cbconvert-gui -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}"
|
||||||
|
|
||||||
|
export OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1
|
||||||
|
mkdir -p "${BUILDDIR}"
|
||||||
|
cp -r dist/macos/CBconvert.app "${BUILDDIR}"
|
||||||
|
PATH=${PATH}:${MACOS_aarch64}/bin \
|
||||||
|
CC=aarch64-apple-darwin21.1-clang \
|
||||||
|
PKG_CONFIG="aarch64-apple-darwin21.1-pkg-config" \
|
||||||
|
PKG_CONFIG_PATH="$MACOS_aarch64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
||||||
|
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.15" \
|
||||||
|
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 \
|
||||||
|
go build -trimpath -tags 'extlib pkgconfig' -v -o "${BUILDDIR}"/CBconvert.app/Contents/MacOS/cbconvert-gui -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}"
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
## Screenshots
|
||||||
|
|
||||||
|
Windows
|
||||||
|
<img src="windows-01.jpg" width="700" title="Windows" alt="Windows" />
|
||||||
|
|
||||||
|
Linux
|
||||||
|
<img src="linux-02.jpg" width="700" title="Linux" alt="Linux" />
|
||||||
|
|
||||||
|
macOS
|
||||||
|
<img src="macos-01.jpg" width="700" title="macOS" alt="macOS" />
|
||||||
|
|
||||||
|
Linux Motif
|
||||||
|
<img src="motif-01.jpg" width="700" title="Linux Motif" alt="Linux Motif" />
|
||||||
|
After Width: | Height: | Size: 152 KiB |
|
After Width: | Height: | Size: 126 KiB |
|
After Width: | Height: | Size: 183 KiB |
|
After Width: | Height: | Size: 186 KiB |
|
After Width: | Height: | Size: 93 KiB |
@@ -1,27 +1,34 @@
|
|||||||
module github.com/gen2brain/cbconvert/cmd/cbconvert
|
module github.com/gen2brain/cbconvert/cmd/cbconvert
|
||||||
|
|
||||||
go 1.19
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gen2brain/cbconvert v0.0.0-20230112123620-c24d7b7e18c4
|
github.com/gen2brain/cbconvert v1.0.4-0.20240208144735-a8084ed89758
|
||||||
github.com/schollz/progressbar/v3 v3.10.0
|
github.com/schollz/progressbar/v3 v3.13.1
|
||||||
github.com/spf13/pflag v1.0.5
|
github.com/spf13/pflag v1.0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/chai2010/webp v1.1.1 // indirect
|
git.sr.ht/~jackmordaunt/go-libwebp v1.1.0 // indirect
|
||||||
github.com/disintegration/imaging v1.6.2 // indirect
|
github.com/disintegration/imaging v1.6.2 // indirect
|
||||||
github.com/fvbommel/sortorder v1.0.2 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/gen2brain/go-fitz v1.20.2 // indirect
|
github.com/ebitengine/purego v0.5.2 // indirect
|
||||||
github.com/gen2brain/go-unarr v0.1.6 // indirect
|
github.com/fvbommel/sortorder v1.1.0 // indirect
|
||||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7 // indirect
|
github.com/gen2brain/go-fitz v1.23.7 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.13 // indirect
|
github.com/gen2brain/go-unarr v0.2.0 // indirect
|
||||||
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
|
||||||
|
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/rivo/uniseg v0.3.4 // indirect
|
github.com/rivo/uniseg v0.3.4 // indirect
|
||||||
github.com/strukturag/libheif v1.13.0 // indirect
|
golang.org/x/image v0.15.0 // indirect
|
||||||
golang.org/x/image v0.2.0 // indirect
|
golang.org/x/sync v0.6.0 // indirect
|
||||||
golang.org/x/sync v0.1.0 // indirect
|
golang.org/x/sys v0.17.0 // indirect
|
||||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
|
golang.org/x/term v0.6.0 // indirect
|
||||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 // indirect
|
gopkg.in/gographics/imagick.v3 v3.5.1 // indirect
|
||||||
gopkg.in/gographics/imagick.v3 v3.4.2 // indirect
|
modernc.org/libc v1.41.0 // indirect
|
||||||
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
|
modernc.org/memory v1.7.2 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,73 +1,66 @@
|
|||||||
github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk=
|
git.sr.ht/~jackmordaunt/go-libwebp v1.1.0 h1:rfDv89tb6OuNp8f1TyprOZWaeC/TxqaYvLCI6nHKBY8=
|
||||||
github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU=
|
git.sr.ht/~jackmordaunt/go-libwebp v1.1.0/go.mod h1:8557wZRj8KWRPBM+osAuAXVVR5nVURZ3SCG5rnACBdE=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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/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 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||||
github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
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/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/gen2brain/cbconvert v0.0.0-20230112123620-c24d7b7e18c4 h1:DMAjwfDN0yhxfJjrZLqCjL1CSEvcBUbOGPPEW1WhYXw=
|
github.com/ebitengine/purego v0.5.2 h1:r2MQEtkGzZ4LRtFZVAg5bjYKnUbxxloaeuGxH0t7qfs=
|
||||||
github.com/gen2brain/cbconvert v0.0.0-20230112123620-c24d7b7e18c4/go.mod h1:GO5h+s7160FK66rth/0QS06HgXFwE57jaP3OTX/8Rv0=
|
github.com/ebitengine/purego v0.5.2/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
|
||||||
github.com/gen2brain/go-fitz v1.20.2 h1:4FPJCU/ImQ32oojBsYn/+oTkRORxbAhAA+Yw1Fm97MA=
|
github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
|
||||||
github.com/gen2brain/go-fitz v1.20.2/go.mod h1:YbQPODTC/UnQ/RK4JyD3zfpDQ19UKiV85nMMT3XpT0s=
|
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||||
github.com/gen2brain/go-unarr v0.1.6 h1:2TtfIQ2dGuCkgEYa+vPE1ydcpkB3CtBbdYMfRSGLdA8=
|
github.com/gen2brain/cbconvert v1.0.4-0.20240208144735-a8084ed89758 h1:VXWir2Nq5qkXuIeoCTavOlQ7j2Yab0vIJe1mvKsLe3I=
|
||||||
github.com/gen2brain/go-unarr v0.1.6/go.mod h1:P05CsEe8jVEXhxqXqp9mFKUKFV0BKpFmtgNWf8Mcoos=
|
github.com/gen2brain/cbconvert v1.0.4-0.20240208144735-a8084ed89758/go.mod h1:jtc/vKGuG66vIemtQc6Ge69FXo33hX+gFvGtEP/z/SM=
|
||||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7 h1:NlUATi3cllRJhpM4mfR9BxiLRXT83bcSLcOa+S8lrME=
|
github.com/gen2brain/go-fitz v1.23.7 h1:HPhzEVzmOINvCKqQgB/DwMzYh4ArIgy3tMwq1eJTcbg=
|
||||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7/go.mod h1:Hku3FQ2laCEwSv7Z8YkC0er38jLaUycUCbsFkWMr+z4=
|
github.com/gen2brain/go-fitz v1.23.7/go.mod h1:HU04vc+RisUh/kvEd2pB0LAxmK1oyXdN4ftyshUr9rQ=
|
||||||
|
github.com/gen2brain/go-unarr v0.2.0 h1:sYKSjbeNSuZgudd59iGAbMbr113XRFoA7Rt9XWA+QVE=
|
||||||
|
github.com/gen2brain/go-unarr v0.2.0/go.mod h1:hoHheVuf0KT8/hfvkEL7GMwj2h7fq0lF72NdyySdr3c=
|
||||||
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
|
||||||
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
|
||||||
|
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
|
||||||
|
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.3.4 h1:3Z3Eu6FGHZWSfNKJTOUiPatWwfc7DzJRU04jFUqJODw=
|
github.com/rivo/uniseg v0.3.4 h1:3Z3Eu6FGHZWSfNKJTOUiPatWwfc7DzJRU04jFUqJODw=
|
||||||
github.com/rivo/uniseg v0.3.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.3.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/schollz/progressbar/v3 v3.10.0 h1:pOab0roS2jf6zkEBKAe9EyEdmRKJvhbbuxqVp9/Qjyw=
|
github.com/schollz/progressbar/v3 v3.13.1 h1:o8rySDYiQ59Mwzy2FELeHY5ZARXZTVJC7iHD6PEFUiE=
|
||||||
github.com/schollz/progressbar/v3 v3.10.0/go.mod h1:0N6zRwbDVLFCFy5chxuukVlRkoHWYFFLzlxQrw/sf3M=
|
github.com/schollz/progressbar/v3 v3.13.1/go.mod h1:xvrbki8kfT1fzWzBT/UZd9L6GA+jdL7HAgq2RFnO6fQ=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
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 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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/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-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/image v0.2.0 h1:/DcQ0w3VHKCC5p0/P2B0JpAZ9Z++V2KOo2fyU89CXBQ=
|
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
|
||||||
golang.org/x/image v0.2.0/go.mod h1:la7oBXb9w3YFjBqaAwtynVioc1ZvOnNteUNrifGNmAI=
|
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
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/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/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-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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035 h1:Q5284mrmYTpACcm+eAKjKJH48BBwSyfJqmmGDTtT8Vc=
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
golang.org/x/term v0.0.0-20220722155259-a9ba230a4035/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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=
|
gopkg.in/gographics/imagick.v3 v3.5.1 h1:58JqK0UCx5RfvbRggF5FKuK6jHwAtTQopUxK8mzFa40=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
gopkg.in/gographics/imagick.v3 v3.5.1/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA=
|
||||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
|
||||||
gopkg.in/gographics/imagick.v3 v3.4.2 h1:vk6oildvhRBVSBfQ4X3raJstApYSeK6CZsyzoSOZk58=
|
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
||||||
gopkg.in/gographics/imagick.v3 v3.4.2/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA=
|
|
||||||
|
|||||||
@@ -1,68 +1,106 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime/debug"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/gen2brain/cbconvert"
|
"github.com/gen2brain/cbconvert"
|
||||||
"github.com/schollz/progressbar/v3"
|
pb "github.com/schollz/progressbar/v3"
|
||||||
flag "github.com/spf13/pflag"
|
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() {
|
func main() {
|
||||||
opts, args := parseFlags()
|
opts, args := parseFlags()
|
||||||
|
|
||||||
|
if opts.Version {
|
||||||
|
fmt.Println(filepath.Base(os.Args[0]), appVersion)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
conv := cbconvert.New(opts)
|
conv := cbconvert.New(opts)
|
||||||
|
|
||||||
c := make(chan os.Signal, 2)
|
c := make(chan os.Signal, 2)
|
||||||
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
|
||||||
go func() {
|
go func() {
|
||||||
for range c {
|
for range c {
|
||||||
fmt.Println("\naborting")
|
if err := os.RemoveAll(conv.Workdir); err != nil {
|
||||||
err := os.RemoveAll(conv.Workdir)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if _, err := os.Stat(opts.Outdir); err != nil {
|
if _, err := os.Stat(opts.OutDir); err != nil {
|
||||||
err = os.MkdirAll(opts.Outdir, 0775)
|
if err := os.MkdirAll(opts.OutDir, 0775); err != nil {
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
conv.Initialize()
|
||||||
|
defer conv.Terminate()
|
||||||
|
|
||||||
files, err := conv.Files(args)
|
files, err := conv.Files(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
var bar *progressbar.ProgressBar
|
var bar *pb.ProgressBar
|
||||||
if opts.Cover || opts.Thumbnail {
|
if opts.Cover || opts.Thumbnail || opts.Meta {
|
||||||
if !opts.Quiet {
|
if !opts.Quiet {
|
||||||
bar = progressbar.NewOptions(conv.Nfiles,
|
bar = pb.NewOptions(conv.Nfiles,
|
||||||
progressbar.OptionShowCount(),
|
pb.OptionShowCount(),
|
||||||
progressbar.OptionClearOnFinish(),
|
pb.OptionClearOnFinish(),
|
||||||
progressbar.OptionUseANSICodes(true),
|
pb.OptionUseANSICodes(true),
|
||||||
progressbar.OptionSetPredictTime(false),
|
pb.OptionSetPredictTime(false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
conv.OnStart = func() {
|
conv.OnStart = func() {
|
||||||
if !opts.Quiet {
|
if !opts.Quiet {
|
||||||
bar = progressbar.NewOptions(conv.Ncontents,
|
bar = pb.NewOptions(conv.Ncontents,
|
||||||
progressbar.OptionShowCount(),
|
pb.OptionShowCount(),
|
||||||
progressbar.OptionClearOnFinish(),
|
pb.OptionClearOnFinish(),
|
||||||
progressbar.OptionUseANSICodes(true),
|
pb.OptionUseANSICodes(true),
|
||||||
progressbar.OptionSetDescription(fmt.Sprintf("Converting %d of %d:", conv.CurrFile, conv.Nfiles)),
|
pb.OptionSetDescription(fmt.Sprintf("Converting %d of %d:", conv.CurrFile, conv.Nfiles)),
|
||||||
progressbar.OptionSetPredictTime(false),
|
pb.OptionSetPredictTime(false),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -75,42 +113,52 @@ func main() {
|
|||||||
|
|
||||||
conv.OnCompress = func() {
|
conv.OnCompress = func() {
|
||||||
if !opts.Quiet {
|
if !opts.Quiet {
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "Compressing %d of %d...\r", conv.CurrFile, conv.Nfiles)
|
fmt.Fprintf(os.Stderr, "Compressing %d of %d...\r", conv.CurrFile, conv.Nfiles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
stat, err := os.Stat(file)
|
switch {
|
||||||
|
case opts.Meta:
|
||||||
|
ret, err := conv.Meta(file.Path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
if opts.Cover {
|
if opts.Cover {
|
||||||
err = conv.ExtractCover(file, stat)
|
fmt.Println(ret)
|
||||||
if err != nil {
|
} else if opts.Comment {
|
||||||
fmt.Println(err)
|
fmt.Println(ret)
|
||||||
os.Exit(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else if opts.Thumbnail {
|
case opts.Cover:
|
||||||
err = conv.ExtractThumbnail(file, stat)
|
if err := conv.Cover(file.Path, file.Stat); err != nil {
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
continue
|
||||||
|
case opts.Thumbnail:
|
||||||
|
if err = conv.Thumbnail(file.Path, file.Stat); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
err = conv.Convert(file, stat)
|
if err := conv.Convert(file.Path, file.Stat); err != nil {
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(os.Stderr, "\r")
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseFlags parses command line flags
|
// parseFlags parses command line flags.
|
||||||
func parseFlags() (cbconvert.Options, []string) {
|
func parseFlags() (cbconvert.Options, []string) {
|
||||||
opts := cbconvert.Options{}
|
opts := cbconvert.Options{}
|
||||||
var args []string
|
var args []string
|
||||||
@@ -120,9 +168,9 @@ func parseFlags() (cbconvert.Options, []string) {
|
|||||||
convert.IntVar(&opts.Width, "width", 0, "Image width")
|
convert.IntVar(&opts.Width, "width", 0, "Image width")
|
||||||
convert.IntVar(&opts.Height, "height", 0, "Image height")
|
convert.IntVar(&opts.Height, "height", 0, "Image height")
|
||||||
convert.BoolVar(&opts.Fit, "fit", false, "Best fit for required width and 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.Format, "format", "jpeg", "Image format, valid values are jpeg, png, tiff, bmp, webp, avif, jxl")
|
||||||
|
convert.StringVar(&opts.Archive, "archive", "zip", "Archive format, valid values are zip, tar")
|
||||||
convert.IntVar(&opts.Quality, "quality", 75, "Image quality")
|
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")
|
convert.IntVar(&opts.Filter, "filter", 2, "0=NearestNeighbor, 1=Box, 2=Linear, 3=MitchellNetravali, 4=CatmullRom, 6=Gaussian, 7=Lanczos")
|
||||||
convert.BoolVar(&opts.NoCover, "no-cover", false, "Do not convert the cover image")
|
convert.BoolVar(&opts.NoCover, "no-cover", false, "Do not convert the cover image")
|
||||||
convert.BoolVar(&opts.NoRGB, "no-rgb", false, "Do not convert images that have RGB colorspace")
|
convert.BoolVar(&opts.NoRGB, "no-rgb", false, "Do not convert images that have RGB colorspace")
|
||||||
@@ -130,17 +178,16 @@ func parseFlags() (cbconvert.Options, []string) {
|
|||||||
convert.BoolVar(&opts.NoConvert, "no-convert", false, "Do not transform or convert images")
|
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.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.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.IntVar(&opts.Brightness, "brightness", 0, "Adjust the brightness of the images, must be in the range (-100, 100)")
|
||||||
convert.Float64Var(&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.Float64Var(&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.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.LevelsGamma, "levels-gamma", 1.0, "Midpoint/Gamma")
|
||||||
convert.Float64Var(&opts.LevelsInMax, "levels-inmax", 255, "Highlight input value")
|
convert.IntVar(&opts.LevelsInMax, "levels-inmax", 255, "Highlight input value")
|
||||||
convert.Float64Var(&opts.LevelsOutMin, "levels-outmin", 0, "Shadow output value")
|
convert.IntVar(&opts.LevelsOutMin, "levels-outmin", 0, "Shadow output value")
|
||||||
convert.Float64Var(&opts.LevelsOutMax, "levels-outmax", 255, "Highlight output value")
|
convert.IntVar(&opts.LevelsOutMax, "levels-outmax", 255, "Highlight output value")
|
||||||
convert.StringVar(&opts.Outdir, "outdir", ".", "Output directory")
|
convert.StringVar(&opts.OutDir, "outdir", ".", "Output directory")
|
||||||
convert.Int64Var(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
|
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.Recursive, "recursive", false, "Process subdirectories recursively")
|
||||||
convert.BoolVar(&opts.Quiet, "quiet", false, "Hide console output")
|
convert.BoolVar(&opts.Quiet, "quiet", false, "Hide console output")
|
||||||
|
|
||||||
@@ -149,10 +196,11 @@ func parseFlags() (cbconvert.Options, []string) {
|
|||||||
cover.IntVar(&opts.Width, "width", 0, "Image width")
|
cover.IntVar(&opts.Width, "width", 0, "Image width")
|
||||||
cover.IntVar(&opts.Height, "height", 0, "Image height")
|
cover.IntVar(&opts.Height, "height", 0, "Image height")
|
||||||
cover.BoolVar(&opts.Fit, "fit", false, "Best fit for required width and 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.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.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.StringVar(&opts.OutDir, "outdir", ".", "Output directory")
|
||||||
cover.Int64Var(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
|
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.Recursive, "recursive", false, "Process subdirectories recursively")
|
||||||
cover.BoolVar(&opts.Quiet, "quiet", false, "Hide console output")
|
cover.BoolVar(&opts.Quiet, "quiet", false, "Hide console output")
|
||||||
|
|
||||||
@@ -162,64 +210,119 @@ func parseFlags() (cbconvert.Options, []string) {
|
|||||||
thumbnail.IntVar(&opts.Height, "height", 0, "Image height")
|
thumbnail.IntVar(&opts.Height, "height", 0, "Image height")
|
||||||
thumbnail.BoolVar(&opts.Fit, "fit", false, "Best fit for required width and 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.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.OutDir, "outdir", ".", "Output directory")
|
||||||
thumbnail.StringVar(&opts.Outfile, "outfile", "", "Output file")
|
thumbnail.StringVar(&opts.OutFile, "outfile", "", "Output file")
|
||||||
thumbnail.Int64Var(&opts.Size, "size", 0, "Process only files larger than size (in MB)")
|
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.Recursive, "recursive", false, "Process subdirectories recursively")
|
||||||
thumbnail.BoolVar(&opts.Quiet, "quiet", false, "Hide console output")
|
thumbnail.BoolVar(&opts.Quiet, "quiet", false, "Hide console output")
|
||||||
|
|
||||||
convert.Usage = func() {
|
meta := flag.NewFlagSet("meta", flag.ExitOnError)
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "Usage: %s <command> [<flags>] [file1 dir1 ... fileOrDirN]\n\n", filepath.Base(os.Args[0]))
|
meta.SortFlags = false
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "\nCommands:\n")
|
meta.BoolVar(&opts.Cover, "cover", false, "Print cover name")
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "\n convert*\n \tConvert archive or document (default command)\n\n")
|
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\n\n")
|
||||||
convert.VisitAll(func(f *flag.Flag) {
|
convert.VisitAll(func(f *flag.Flag) {
|
||||||
_, _ = fmt.Fprintf(os.Stderr, " --%s", f.Name)
|
fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "\n \t")
|
fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
|
||||||
})
|
})
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "\n cover\n \tExtract cover\n\n")
|
fmt.Fprintf(os.Stderr, "\n cover\n \tExtract cover\n\n")
|
||||||
cover.VisitAll(func(f *flag.Flag) {
|
cover.VisitAll(func(f *flag.Flag) {
|
||||||
_, _ = fmt.Fprintf(os.Stderr, " --%s", f.Name)
|
fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "\n \t")
|
fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||||
_, _ = 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")
|
fmt.Fprintf(os.Stderr, "\n thumbnail\n \tExtract cover thumbnail (freedesktop spec.)\n\n")
|
||||||
thumbnail.VisitAll(func(f *flag.Flag) {
|
thumbnail.VisitAll(func(f *flag.Flag) {
|
||||||
_, _ = fmt.Fprintf(os.Stderr, " --%s", f.Name)
|
fmt.Fprintf(os.Stderr, " --%s\n \t", f.Name)
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "\n \t")
|
fmt.Fprintf(os.Stderr, "%v (default %q)\n", f.Usage, f.DefValue)
|
||||||
_, _ = 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 {
|
if len(os.Args) < 2 {
|
||||||
convert.Usage()
|
flag.Usage()
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "no arguments\n")
|
fmt.Fprintf(os.Stderr, "no command\n")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pipe := piped()
|
||||||
|
if pipe {
|
||||||
|
args = lines(os.Stdin)
|
||||||
|
}
|
||||||
|
|
||||||
switch os.Args[1] {
|
switch os.Args[1] {
|
||||||
case "convert":
|
case "convert":
|
||||||
_ = convert.Parse(os.Args[2:])
|
_ = convert.Parse(os.Args[2:])
|
||||||
|
if !pipe {
|
||||||
args = convert.Args()
|
args = convert.Args()
|
||||||
|
}
|
||||||
case "cover":
|
case "cover":
|
||||||
opts.Cover = true
|
opts.Cover = true
|
||||||
_ = cover.Parse(os.Args[2:])
|
_ = cover.Parse(os.Args[2:])
|
||||||
|
if !pipe {
|
||||||
args = cover.Args()
|
args = cover.Args()
|
||||||
|
}
|
||||||
case "thumbnail":
|
case "thumbnail":
|
||||||
opts.Thumbnail = true
|
opts.Thumbnail = true
|
||||||
_ = thumbnail.Parse(os.Args[2:])
|
_ = thumbnail.Parse(os.Args[2:])
|
||||||
|
if !pipe {
|
||||||
args = thumbnail.Args()
|
args = thumbnail.Args()
|
||||||
default:
|
}
|
||||||
_ = convert.Parse(os.Args[1:])
|
case "meta":
|
||||||
args = convert.Args()
|
opts.Meta = true
|
||||||
|
_ = meta.Parse(os.Args[2:])
|
||||||
|
if !pipe {
|
||||||
|
args = meta.Args()
|
||||||
|
}
|
||||||
|
case "version":
|
||||||
|
opts.Version = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) == 0 {
|
if len(args) == 0 && !opts.Version {
|
||||||
convert.Usage()
|
flag.Usage()
|
||||||
_, _ = fmt.Fprintf(os.Stderr, "no arguments\n")
|
_, _ = fmt.Fprintf(os.Stderr, "no arguments\n")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
return opts, args
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
GLIBC_x86_64="/usr/x86_64-pc-linux-gnu-static"
|
GLIBC_x86_64="/usr/x86_64-pc-linux-gnu-static"
|
||||||
MUSL_x86_64="/usr/x86_64-pc-linux-musl"
|
|
||||||
MUSL_aarch64="/usr/aarch64-pc-linux-musl"
|
|
||||||
MINGW_x86_64="/usr/x86_64-w64-mingw32"
|
MINGW_x86_64="/usr/x86_64-w64-mingw32"
|
||||||
MACOS_x86_64="/usr/x86_64-apple-darwin"
|
MACOS_x86_64="/usr/x86_64-apple-darwin"
|
||||||
MACOS_aarch64="/usr/aarch64-apple-darwin"
|
MACOS_aarch64="/usr/aarch64-apple-darwin"
|
||||||
|
|
||||||
VERSION="`git --git-dir ../../.git describe --tags --abbrev=0 2>/dev/null || echo '0.0.0'`"
|
VERSION="$(git --git-dir ../../.git describe --tags --abbrev=0 2>/dev/null || echo '1.0.0')"
|
||||||
|
|
||||||
BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR}
|
BUILDDIR="cbconvert-${VERSION}"
|
||||||
|
|
||||||
|
mkdir -p "${BUILDDIR}"
|
||||||
CC=x86_64-pc-linux-gnu-gcc \
|
CC=x86_64-pc-linux-gnu-gcc \
|
||||||
PKG_CONFIG="x86_64-pc-linux-gnu-pkg-config" \
|
PKG_CONFIG="x86_64-pc-linux-gnu-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$GLIBC_x86_64/usr/lib64/pkgconfig" \
|
PKG_CONFIG_PATH="$GLIBC_x86_64/usr/lib64/pkgconfig" \
|
||||||
@@ -17,70 +17,46 @@ PKG_CONFIG_LIBDIR="$GLIBC_x86_64/usr/lib64/pkgconfig" \
|
|||||||
CGO_CFLAGS="-I$GLIBC_x86_64/usr/include" \
|
CGO_CFLAGS="-I$GLIBC_x86_64/usr/include" \
|
||||||
CGO_LDFLAGS="-L$GLIBC_x86_64/usr/lib64" \
|
CGO_LDFLAGS="-L$GLIBC_x86_64/usr/lib64" \
|
||||||
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \
|
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}
|
cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && tar -czf "${BUILDDIR}-linux-x86_64.tar.gz" "${BUILDDIR}"
|
||||||
rm -rf ${BUILDDIR}
|
rm -rf "${BUILDDIR}"
|
||||||
|
|
||||||
#BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR}
|
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" \
|
|
||||||
#CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \
|
|
||||||
#go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w '-extldflags=-static'" && \
|
|
||||||
#cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && tar -czf "${BUILDDIR}-linux-x86_64.tar.gz" ${BUILDDIR}
|
|
||||||
#rm -rf ${BUILDDIR}
|
|
||||||
|
|
||||||
BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR}
|
|
||||||
CC=aarch64-pc-linux-musl-gcc \
|
|
||||||
PKG_CONFIG="aarch64-pc-linux-musl-pkg-config" \
|
|
||||||
PKG_CONFIG_PATH="$MUSL_aarch64/usr/lib/pkgconfig" \
|
|
||||||
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'" && \
|
|
||||||
cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && tar -czf "${BUILDDIR}-linux-aarch64.tar.gz" ${BUILDDIR}
|
|
||||||
rm -rf ${BUILDDIR}
|
|
||||||
|
|
||||||
BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR}
|
|
||||||
CC=x86_64-w64-mingw32-gcc \
|
CC=x86_64-w64-mingw32-gcc \
|
||||||
PKG_CONFIG="/usr/bin/x86_64-w64-mingw32-pkg-config" \
|
PKG_CONFIG="/usr/bin/x86_64-w64-mingw32-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$MINGW_x86_64/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$MINGW_x86_64/usr/lib/pkgconfig" \
|
||||||
PKG_CONFIG_LIBDIR="$MINGW_x86_64/usr/lib/pkgconfig" \
|
PKG_CONFIG_LIBDIR="$MINGW_x86_64/usr/lib/pkgconfig" \
|
||||||
CGO_CFLAGS="-I$MINGW_x86_64/usr/include" \
|
CGO_CFLAGS="-I$MINGW_x86_64/usr/include" \
|
||||||
CGO_LDFLAGS="-L$MINGW_x86_64/usr/lib" \
|
CGO_LDFLAGS="-L$MINGW_x86_64/usr/lib -ljxl -ljxl_dec -ljxl_profiler -ljxl_threads" \
|
||||||
CGO_ENABLED=1 GOOS=windows GOARCH=amd64 \
|
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}
|
cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && zip -rq "${BUILDDIR}-windows-x86_64.zip" "${BUILDDIR}"
|
||||||
rm -rf ${BUILDDIR}
|
rm -rf "${BUILDDIR}"
|
||||||
|
|
||||||
export OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1
|
export OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1
|
||||||
BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR}
|
mkdir -p "${BUILDDIR}"
|
||||||
PATH=${PATH}:${MACOS_x86_64}/bin \
|
PATH=${PATH}:${MACOS_x86_64}/bin \
|
||||||
CC=x86_64-apple-darwin21.1-clang \
|
CC=x86_64-apple-darwin21.1-clang \
|
||||||
PKG_CONFIG="x86_64-apple-darwin21.1-pkg-config" \
|
PKG_CONFIG="x86_64-apple-darwin21.1-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$MACOS_x86_64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$MACOS_x86_64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
||||||
PKG_CONFIG_LIBDIR="$MACOS_x86_64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
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_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_LDFLAGS="-L$MACOS_x86_64/SDK/MacOSX12.1.sdk/usr/lib -L$MACOS_x86_64/macports/pkgs/opt/local/lib -mmacosx-version-min=10.15" \
|
||||||
CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 \
|
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}
|
cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && zip -rq "${BUILDDIR}-darwin-x86_64.zip" "${BUILDDIR}"
|
||||||
rm -rf ${BUILDDIR}
|
rm -rf "${BUILDDIR}"
|
||||||
|
|
||||||
export OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1
|
export OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1
|
||||||
BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR}
|
mkdir -p "${BUILDDIR}"
|
||||||
PATH=${PATH}:${MACOS_aarch64}/bin \
|
PATH=${PATH}:${MACOS_aarch64}/bin \
|
||||||
CC=aarch64-apple-darwin21.1-clang \
|
CC=aarch64-apple-darwin21.1-clang \
|
||||||
PKG_CONFIG="aarch64-apple-darwin21.1-pkg-config" \
|
PKG_CONFIG="aarch64-apple-darwin21.1-pkg-config" \
|
||||||
PKG_CONFIG_PATH="$MACOS_aarch64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
PKG_CONFIG_PATH="$MACOS_aarch64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
||||||
PKG_CONFIG_LIBDIR="$MACOS_aarch64/SDK/MacOSX12.1.sdk/usr/lib/pkgconfig" \
|
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_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_LDFLAGS="-L$MACOS_aarch64/SDK/MacOSX12.1.sdk/usr/lib -L$MACOS_aarch64/macports/pkgs/opt/local/lib -mmacosx-version-min=10.15" \
|
||||||
CGO_ENABLED=1 GOOS=darwin GOARCH=arm64 \
|
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}
|
cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && zip -rq "${BUILDDIR}-darwin-aarch64.zip" "${BUILDDIR}"
|
||||||
rm -rf ${BUILDDIR}
|
rm -rf "${BUILDDIR}"
|
||||||
|
|||||||
|
After Width: | Height: | Size: 280 KiB |
@@ -1,16 +1,26 @@
|
|||||||
module github.com/gen2brain/cbconvert
|
module github.com/gen2brain/cbconvert
|
||||||
|
|
||||||
go 1.19
|
go 1.21
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/chai2010/webp v1.1.1
|
git.sr.ht/~jackmordaunt/go-libwebp v1.1.0
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/fvbommel/sortorder v1.0.2
|
github.com/dustin/go-humanize v1.0.1
|
||||||
github.com/gen2brain/go-fitz v1.20.1
|
github.com/fvbommel/sortorder v1.1.0
|
||||||
github.com/gen2brain/go-unarr v0.1.6
|
github.com/gen2brain/go-fitz v1.23.7
|
||||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7
|
github.com/gen2brain/go-unarr v0.2.0
|
||||||
github.com/strukturag/libheif v1.13.0
|
golang.org/x/image v0.15.0
|
||||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69
|
golang.org/x/sync v0.6.0
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde
|
gopkg.in/gographics/imagick.v3 v3.5.1
|
||||||
gopkg.in/gographics/imagick.v3 v3.4.1
|
)
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/ebitengine/purego v0.5.1 // indirect
|
||||||
|
github.com/google/uuid v1.3.1 // indirect
|
||||||
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
|
golang.org/x/sys v0.13.0 // indirect
|
||||||
|
modernc.org/libc v1.24.1 // indirect
|
||||||
|
modernc.org/mathutil v1.6.0 // indirect
|
||||||
|
modernc.org/memory v1.7.2 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,24 +1,37 @@
|
|||||||
github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk=
|
git.sr.ht/~jackmordaunt/go-libwebp v1.1.0 h1:rfDv89tb6OuNp8f1TyprOZWaeC/TxqaYvLCI6nHKBY8=
|
||||||
github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU=
|
git.sr.ht/~jackmordaunt/go-libwebp v1.1.0/go.mod h1:8557wZRj8KWRPBM+osAuAXVVR5nVURZ3SCG5rnACBdE=
|
||||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
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/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4=
|
||||||
github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/gen2brain/go-fitz v1.20.1 h1:i5GPe/58q/gbNqa2mO+ZcTymwowbJEsDOXp7D0JwxgU=
|
github.com/ebitengine/purego v0.5.1 h1:hNunhThpOf1vzKl49v6YxIsXLhl92vbBEv1/2Ez3ZrY=
|
||||||
github.com/gen2brain/go-fitz v1.20.1/go.mod h1:UZAxMETTDK4UPpuh80HaRpPzgkSibUihXVzwj2ip5oQ=
|
github.com/ebitengine/purego v0.5.1/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
|
||||||
github.com/gen2brain/go-unarr v0.1.6 h1:2TtfIQ2dGuCkgEYa+vPE1ydcpkB3CtBbdYMfRSGLdA8=
|
github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw=
|
||||||
github.com/gen2brain/go-unarr v0.1.6/go.mod h1:P05CsEe8jVEXhxqXqp9mFKUKFV0BKpFmtgNWf8Mcoos=
|
github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0=
|
||||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7 h1:NlUATi3cllRJhpM4mfR9BxiLRXT83bcSLcOa+S8lrME=
|
github.com/gen2brain/go-fitz v1.23.7 h1:HPhzEVzmOINvCKqQgB/DwMzYh4ArIgy3tMwq1eJTcbg=
|
||||||
github.com/hotei/bmp v0.0.0-20150430041436-f620cebab0c7/go.mod h1:Hku3FQ2laCEwSv7Z8YkC0er38jLaUycUCbsFkWMr+z4=
|
github.com/gen2brain/go-fitz v1.23.7/go.mod h1:HU04vc+RisUh/kvEd2pB0LAxmK1oyXdN4ftyshUr9rQ=
|
||||||
github.com/strukturag/libheif v1.13.0 h1:SuLo/Fl/Nzbw0ixOya1YZSl0Xd27X4fgofGnJdvOHqI=
|
github.com/gen2brain/go-unarr v0.2.0 h1:sYKSjbeNSuZgudd59iGAbMbr113XRFoA7Rt9XWA+QVE=
|
||||||
github.com/strukturag/libheif v1.13.0/go.mod h1:E/PNRlmVtrtj9j2AvBZlrO4dsBDu6KfwDZn7X1Ce8Ks=
|
github.com/gen2brain/go-unarr v0.2.0/go.mod h1:hoHheVuf0KT8/hfvkEL7GMwj2h7fq0lF72NdyySdr3c=
|
||||||
|
github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
||||||
|
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
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.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
|
||||||
golang.org/x/image v0.0.0-20220902085622-e7cb96979f69/go.mod h1:doUCurBvlfPMKfmIpRIywoHmhN3VyhnoFDbvIEWF4hY=
|
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde h1:ejfdSekXMDxDLbRrJMwUk6KnSLZ2McaUCVcIKM+N6jc=
|
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||||
|
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
gopkg.in/gographics/imagick.v3 v3.5.1 h1:58JqK0UCx5RfvbRggF5FKuK6jHwAtTQopUxK8mzFa40=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
gopkg.in/gographics/imagick.v3 v3.5.1/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA=
|
||||||
gopkg.in/gographics/imagick.v3 v3.4.1 h1:CClNBnd1UGxH9KAl4Vuwx+jgNRkyKN+cHlbuFPyt+KU=
|
modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM=
|
||||||
gopkg.in/gographics/imagick.v3 v3.4.1/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA=
|
modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak=
|
||||||
|
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
|
||||||
|
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
|
||||||
|
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
|
||||||
|
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
|
||||||
|
|||||||
|
After Width: | Height: | Size: 229 KiB |
|
After Width: | Height: | Size: 387 KiB |