diff --git a/README.md b/README.md index 91f72ac..1986229 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,15 @@ 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. +screenshot + +See more [screnshots](https://github.com/gen2brain/cbconvert/blob/master/cmd/cbconvert-gui/screenshots/). + ### Features * reads CBR (RAR), CBZ (ZIP), CB7 (7Z), CBT (TAR), PDF, XPS, EPUB, MOBI and plain directory -* saves processed comics in ZIP archive format or TAR -* images can be converted to JPEG, PNG, TIFF, WEBP, AVIF, JXL, or 4-Bit BMP (16 colors) file format +* saves processed files in ZIP archive format or TAR +* images can be converted to JPEG, PNG, TIFF, WEBP, AVIF, JXL, or 4-Bit BMP (16 colors) image format * rotate, adjust brightness/contrast, adjust levels (Photoshop-like) or grayscale images * resize filters (NearestNeighbor, Box, Linear, MitchellNetravali, CatmullRom, Gaussian, Lanczos) * export covers from comics @@ -18,26 +22,25 @@ It can convert comics to different formats to fit your various devices. ### Download -* [Windows x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.1-windows-x86_64.zip) -* [Linux x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.1-linux-x86_64.tar.gz) -* [Linux aarch64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.1-linux-aarch64.tar.gz) -* [macOS x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.1-darwin-x86_64.zip) -* [macOS aarch64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-0.9.1-darwin-aarch64.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/latest/download/cbconvert-1.0.0-linux-x86_64.tar.gz) +* [macOS x86_64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-1.0.0-darwin-x86_64.zip) +* [macOS aarch64](https://github.com/gen2brain/cbconvert/releases/latest/download/cbconvert-1.0.0-darwin-aarch64.zip) ### 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] 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; +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: -![thumbnails](https://bit.ly/3BaTvTV) +thumbnails ### Using command line app @@ -199,3 +202,7 @@ This table maps quality settings for JPEG to the respective AVIF and WEBP qualit Install ImageMagick7 (with libheif/libjxl support) and MuPDF libraries and headers and then install to GOBIN: `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` diff --git a/cmd/cbconvert-gui/assets/icon.png b/cmd/cbconvert-gui/assets/icon.png new file mode 100644 index 0000000..6e2eb74 Binary files /dev/null and b/cmd/cbconvert-gui/assets/icon.png differ diff --git a/cmd/cbconvert-gui/assets/loading.gif b/cmd/cbconvert-gui/assets/loading.gif new file mode 100644 index 0000000..b201e6f Binary files /dev/null and b/cmd/cbconvert-gui/assets/loading.gif differ diff --git a/cmd/cbconvert-gui/dist/linux/cbconvert.desktop b/cmd/cbconvert-gui/dist/linux/cbconvert.desktop new file mode 100644 index 0000000..4696c5d --- /dev/null +++ b/cmd/cbconvert-gui/dist/linux/cbconvert.desktop @@ -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; diff --git a/cmd/cbconvert-gui/dist/linux/cbconvert.png b/cmd/cbconvert-gui/dist/linux/cbconvert.png new file mode 100644 index 0000000..915e02f Binary files /dev/null and b/cmd/cbconvert-gui/dist/linux/cbconvert.png differ diff --git a/cmd/cbconvert-gui/dist/linux/cbconvert.thumbnailer b/cmd/cbconvert-gui/dist/linux/cbconvert.thumbnailer new file mode 100644 index 0000000..6ab3b12 --- /dev/null +++ b/cmd/cbconvert-gui/dist/linux/cbconvert.thumbnailer @@ -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; diff --git a/cmd/cbconvert-gui/dist/linux/flatpak/01-mupdf-shared.patch b/cmd/cbconvert-gui/dist/linux/flatpak/01-mupdf-shared.patch new file mode 100644 index 0000000..f043330 --- /dev/null +++ b/cmd/cbconvert-gui/dist/linux/flatpak/01-mupdf-shared.patch @@ -0,0 +1,60 @@ +diff -ur mupdf-1.23.3-source.orig/Makefile mupdf-1.23.3-source/Makefile +--- mupdf-1.23.3-source.orig/Makefile 2023-09-05 13:51:19.000000000 +0200 ++++ mupdf-1.23.3-source/Makefile 2023-09-08 09:28:01.165486441 +0200 +@@ -3,7 +3,7 @@ + -include user.make + + ifndef build +- build := release ++ build := debug + endif + + default: all +@@ -290,17 +290,19 @@ + $(THREAD_LIB) : $(THREAD_OBJ) + $(PKCS7_LIB) : $(PKCS7_OBJ) + else +-MUPDF_LIB = $(OUT)/libmupdf.a ++MUPDF_LIB = libmupdf.so + LIBS_TO_INSTALL_IN_LIB = $(MUPDF_LIB) $(THIRD_LIB) +-THIRD_LIB = $(OUT)/libmupdf-third.a ++THIRD_LIB = ++MUPDF_STATIC = $(OUT)/libmupdf.a + ifneq ($(USE_SYSTEM_GLUT),yes) + THIRD_GLUT_LIB = $(OUT)/libmupdf-glut.a + endif + THREAD_LIB = $(OUT)/libmupdf-threads.a + PKCS7_LIB = $(OUT)/libmupdf-pkcs7.a + +-$(MUPDF_LIB) : $(MUPDF_OBJ) +-$(THIRD_LIB) : $(THIRD_OBJ) ++$(MUPDF_LIB) : $(MUPDF_OBJ) $(THIRD_OBJ) ++ $(QUIET_LINK) $(CC) $(LDFLAGS) --shared -Wl,-soname -Wl,$(MUPDF_LIB) -o $@ $^ $(THIRD_LIBS) $(LIBS) ++$(MUPDF_STATIC): $(MUPDF_OBJ) $(THIRD_OBJ) + $(THIRD_GLUT_LIB) : $(THIRD_GLUT_OBJ) + $(THREAD_LIB) : $(THREAD_OBJ) + $(PKCS7_LIB) : $(PKCS7_OBJ) +diff -ur mupdf-1.23.3-source.orig/Makethird mupdf-1.23.3-source/Makethird +--- mupdf-1.23.3-source.orig/Makethird 2023-09-05 13:51:19.000000000 +0200 ++++ mupdf-1.23.3-source/Makethird 2023-09-08 01:16:56.785811250 +0200 +@@ -2,16 +2,16 @@ + + ifeq ($(USE_SYSTEM_LIBS),yes) + USE_SYSTEM_FREETYPE := yes +- USE_SYSTEM_GUMBO := yes ++ USE_SYSTEM_GUMBO := no + USE_SYSTEM_HARFBUZZ := yes +- USE_SYSTEM_JBIG2DEC := yes ++ USE_SYSTEM_JBIG2DEC := no + USE_SYSTEM_JPEGXR := no # not available + USE_SYSTEM_LCMS2 := no # lcms2mt is strongly preferred + USE_SYSTEM_LIBJPEG := yes + USE_SYSTEM_MUJS := no # not available +- USE_SYSTEM_OPENJPEG := yes ++ USE_SYSTEM_OPENJPEG := no + USE_SYSTEM_ZLIB := yes +- USE_SYSTEM_GLUT := yes ++ USE_SYSTEM_GLUT := no + USE_SYSTEM_CURL := yes + USE_SYSTEM_LEPTONICA := yes + USE_SYSTEM_TESSERACT := yes diff --git a/cmd/cbconvert-gui/dist/linux/flatpak/io.github.gen2brain.cbconvert.desktop b/cmd/cbconvert-gui/dist/linux/flatpak/io.github.gen2brain.cbconvert.desktop new file mode 100644 index 0000000..75f9c4e --- /dev/null +++ b/cmd/cbconvert-gui/dist/linux/flatpak/io.github.gen2brain.cbconvert.desktop @@ -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=io.github.gen2brain.cbconvert +Terminal=false +Type=Application +StartupNotify=true +Categories=Graphics; diff --git a/cmd/cbconvert-gui/dist/linux/flatpak/io.github.gen2brain.cbconvert.metainfo.xml b/cmd/cbconvert-gui/dist/linux/flatpak/io.github.gen2brain.cbconvert.metainfo.xml new file mode 100644 index 0000000..1f4598a --- /dev/null +++ b/cmd/cbconvert-gui/dist/linux/flatpak/io.github.gen2brain.cbconvert.metainfo.xml @@ -0,0 +1,44 @@ + + + io.github.gen2brain.cbconvert + + CBconvert + Milan Nikolic + A Comic Book converter + + MIT + GPL-3 + + +

+ 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. +

+
+ + io.github.gen2brain.cbconvert.desktop + + + https://raw.githubusercontent.com/gen2brain/cbconvert/main/cmd/cbconvert-gui/screenshots/linux-02.jpg + + + https://raw.githubusercontent.com/gen2brain/cbconvert/main/cmd/cbconvert-gui/screenshots/linux-01.jpg + + + + https://github.com/gen2brain/cbconvert + https://github.com/gen2brain/cbconvert/issues + + + + +
    +
  • Added new GUI
  • +
  • Added support for JPEG XL
  • +
+
+ https://github.com/gen2brain/cbconvert/releases/tag/v1.0.0 +
+
+ +
diff --git a/cmd/cbconvert-gui/dist/linux/flatpak/io.github.gen2brain.cbconvert.yml b/cmd/cbconvert-gui/dist/linux/flatpak/io.github.gen2brain.cbconvert.yml new file mode 100644 index 0000000..6b0180f --- /dev/null +++ b/cmd/cbconvert-gui/dist/linux/flatpak/io.github.gen2brain.cbconvert.yml @@ -0,0 +1,369 @@ +app-id: io.github.gen2brain.cbconvert +runtime: org.freedesktop.Platform +runtime-version: '23.08' +sdk: org.freedesktop.Sdk +sdk-extensions: + - org.freedesktop.Sdk.Extension.golang + +command: cbconvert-gui + +finish-args: + - --share=ipc + - --socket=x11 + +build-options: + env: + - GOROOT=/usr/lib/sdk/golang + +cleanup: + - '*.a' + - '*.la' + - '/bin/Magick*' + - '/etc' + - '/include' + - '/lib/cmake' + - '/lib/pkgconfig' + - '/lib/ImageMagick*' + - '/share' + +modules: + + - name: libheif + buildsystem: autotools + config-opts: + - --enable-shared + - --disable-static + - --disable-libde265 + - --disable-dav1d + - --disable-go + - --disable-gdk-pixbuf + - --disable-rav1e + - --disable-x265 + - --disable-tests + - --disable-examples + sources: + - type: archive + url: https://github.com/strukturag/libheif/releases/download/v1.15.2/libheif-1.15.2.tar.gz + sha256: 7a4c6077f45180926583e2087571371bdd9cb21b6e6fada85a6fbd544f26a0e2 + + - name: highway + buildsystem: cmake + config-opts: + - -DBUILD_SHARED_LIBS=ON + - -DHWY_ENABLE_TESTS=OFF + - -DHWY_ENABLE_EXAMPLES=OFF + - -DHWY_WARNINGS_ARE_ERRORS=OFF + sources: + - type: archive + url: https://github.com/google/highway/archive/refs/tags/1.0.7.tar.gz + sha256: 5434488108186c170a5e2fca5e3c9b6ef59a1caa4d520b008a9b8be6b8abe6c5 + + - name: libjxl + buildsystem: cmake + config-opts: + - -DBUILD_SHARED_LIBS=ON + - -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 + - -DJPEGXL_FORCE_SYSTEM_BROTLI=ON + - -DJPEGXL_FORCE_SYSTEM_LCMS2=ON + sources: + - type: archive + url: https://github.com/libjxl/libjxl/archive/refs/tags/v0.8.2.tar.gz + sha256: c70916fb3ed43784eb840f82f05d390053a558e2da106e40863919238fa7b420 + + - name: ImageMagick + buildsystem: autotools + config-opts: + - --enable-shared + - --disable-static + - --enable-zero-configuration + - --without-frozenpaths + - --without-utilities + - --without-modules + - --without-magick-plus-plus + - --without-perl + - --without-bzlib + - --without-x + - --without-zip + - --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-hdri + - --disable-opencl + - --disable-openmp + - --with-jpeg + - --with-png + - --with-tiff + - --with-webp + - --with-heic + - --with-jxl + sources: + - type: archive + url: https://github.com/ImageMagick/ImageMagick/archive/refs/tags/7.1.1-15.tar.gz + sha256: 2372192a76af9be43c0543dd7ae6dfbf34b11fc0203583453ce3f9f707c36bcc + + - name: MuPDF + buildsystem: simple + build-commands: + - HAVE_X11=no HAVE_LIBCRYPTO=no HAVE_GLUT=no HAVE_OBJCOPY=no USE_SYSTEM_LIBS=yes build=debug shared=yes tofu=yes tofu_cjk=yes make libs + - install -Dm00755 build/shared-debug-tofu-tofu_cjk/libmupdf.so $FLATPAK_DEST/lib/debug/lib/libmupdf.so.debug + - install -dm00755 $FLATPAK_DEST/lib/debug/source/mupdf/source + - cp -r source $FLATPAK_DEST/lib/debug/source/mupdf + - cp -r include/mupdf $FLATPAK_DEST/include/ + - install -Dsm00755 build/shared-debug-tofu-tofu_cjk/libmupdf.so $FLATPAK_DEST/lib/libmupdf.so + sources: + - type: archive + url: https://mupdf.com/downloads/archive/mupdf-1.23.3-source.tar.gz + sha256: 1ef9a6409bc0a3271586e1b16f78eb156a579521cd212a124b57c4da8b940aad + - type: patch + path: 01-mupdf-shared.patch + + - name: CBconvert + buildsystem: simple + build-commands: + - cp cmd/cbconvert-gui/dist/linux/flatpak/modules.txt cmd/cbconvert-gui/vendor/ + - cd cmd/cbconvert-gui && $GOROOT/bin/go build -mod=vendor -trimpath -tags "extlib portal" -ldflags "-s -w -X main.appVersion=1.0.0" + - install -Dm00755 cmd/cbconvert-gui/cbconvert-gui $FLATPAK_DEST/bin/cbconvert-gui + - install -Dm00644 cmd/cbconvert-gui/dist/linux/cbconvert.png $FLATPAK_DEST/share/icons/hicolor/256x256/apps/$FLATPAK_ID.png + - install -Dm00644 cmd/cbconvert-gui/dist/linux/flatpak/$FLATPAK_ID.desktop $FLATPAK_DEST/share/applications/$FLATPAK_ID.desktop + - install -Dm00644 cmd/cbconvert-gui/dist/linux/flatpak/$FLATPAK_ID.metainfo.xml $FLATPAK_DEST/share/metainfo/$FLATPAK_ID.metainfo.xml + sources: + - type: archive + url: https://github.com/gen2brain/cbconvert/archive/refs/tags/v1.0.0.tar.gz + sha256: d628bb06020f50e57c879794652c1533eee18814e3b9a223cdb11ed9fe88bc01 + + - type: archive + url: https://proxy.golang.org/github.com/gen2brain/cbconvert/@v/v1.0.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/gen2brain/cbconvert + sha256: d628bb06020f50e57c879794652c1533eee18814e3b9a223cdb11ed9fe88bc01 + + - type: archive + url: https://proxy.golang.org/github.com/chai2010/webp/@v/v1.1.1.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/chai2010/webp + sha256: f42fe1697007ea12155a5d1342d61787e1f34ca396192e4995dc4f2b350552ac + + - type: archive + url: https://proxy.golang.org/github.com/davecgh/go-spew/@v/v1.1.1.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/davecgh/go-spew + sha256: 6b44a843951f371b7010c754ecc3cabefe815d5ced1c5b9409fb2d697e8a890d + + - type: archive + url: https://proxy.golang.org/github.com/disintegration/imaging/@v/v1.6.2.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/disintegration/imaging + sha256: 2934e7bace3c8c0b1b4a07144197e8720b9ffbe922600e3a3c764f77792ac7c4 + + - type: archive + url: https://proxy.golang.org/github.com/dustin/go-humanize/@v/v1.0.1.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/dustin/go-humanize + sha256: 319404ea84c8a4e2d3d83f30988b006e7dd04976de3e1a1a90484ad94679fa46 + + - type: archive + url: https://proxy.golang.org/github.com/fvbommel/sortorder/@v/v1.1.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/fvbommel/sortorder + sha256: a4dbc58d2f72212474a7b5e1894b11d6712b687f4cc66ca1f6e202a375d252f7 + + - type: archive + url: https://proxy.golang.org/github.com/gen2brain/go-fitz/@v/v1.23.1.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/gen2brain/go-fitz + sha256: 60fc98c3420d7f7347e7a454fdfd66bca960accc8ed0ac582f4b4d82b38513c8 + + - type: archive + url: https://proxy.golang.org/github.com/gen2brain/go-unarr/@v/v0.1.7.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/gen2brain/go-unarr + sha256: 6f3418edef461c2e1ce5ba77141d402b04d4cf86e89b27c5dc20c922ac63ca4e + + - type: archive + url: https://proxy.golang.org/github.com/gen2brain/iup-go/iup/@v/v0.0.0-20230906093706-8b037fe6a7bd.zip + strip-components: 4 + dest: cmd/cbconvert-gui/vendor/github.com/gen2brain/iup-go/iup + sha256: a75dbec0ce228214533ee971771233f8b57653828af04bc012f72b624b76be5d + + - type: archive + url: https://proxy.golang.org/github.com/godbus/dbus/v5/@v/v5.1.0.zip + strip-components: 4 + dest: cmd/cbconvert-gui/vendor/github.com/godbus/dbus/v5 + sha256: 03dfa8e71089a6f477310d15c4d3a036d82d028532881b50fee254358e782ad9 + + - type: archive + url: https://proxy.golang.org/github.com/google/uuid/@v/v1.3.1.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/google/uuid + sha256: 9d9d6cfb28ce6dbe4b518c42c6bccd67bb531a106859808f36e82a5c3fb8c64d + + - type: archive + url: https://proxy.golang.org/github.com/k0kubun/go-ansi/@v/v0.0.0-20180517002512-3bf9e2903213.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/k0kubun/go-ansi + sha256: 28366085f1787eaf9d6589f050455855f01caf559f2c6d1c4f4e590cd0abbdef + + - type: archive + url: https://proxy.golang.org/github.com/mattn/go-isatty/@v/v0.0.16.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/mattn/go-isatty + sha256: 3d5ff19c4b2a2a164feb84f5cc38af349380c0c4a03d0443dce40bbd6ec3fd2b + + - type: archive + url: https://proxy.golang.org/github.com/mattn/go-runewidth/@v/v0.0.13.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/mattn/go-runewidth + sha256: c104e14c1612a6d736bd109fe5fec9749a8146e1f7d37844d8a0a1296e00d4e9 + + - type: archive + url: https://proxy.golang.org/github.com/mitchellh/colorstring/@v/v0.0.0-20190213212951-d06e56a500db.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/mitchellh/colorstring + sha256: d0733284b20567055e374b420373f5508fa47e95204e59e4b8a66834e7e3964d + + - type: archive + url: https://proxy.golang.org/github.com/pmezard/go-difflib/@v/v1.0.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/pmezard/go-difflib + sha256: de04cecc1a4b8d53e4357051026794bcbc54f2e6a260cfac508ce69d5d6457a0 + + - type: archive + url: https://proxy.golang.org/github.com/rivo/uniseg/@v/v0.3.4.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/rivo/uniseg + sha256: 410ba5034e1683946d68e7fd50ad793c2ad72b157f2959fe4719449666d1e63f + + - type: archive + url: https://proxy.golang.org/github.com/schollz/progressbar/v3/@v/v3.10.0.zip + strip-components: 4 + dest: cmd/cbconvert-gui/vendor/github.com/schollz/progressbar/v3 + sha256: 2cdbf5e4bc314bf140911a923f22d5d9401d73f3b2c7311f6df5c2837d2743ba + + - type: archive + url: https://proxy.golang.org/github.com/spf13/pflag/@v/v1.0.5.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/spf13/pflag + sha256: fc6e704f2f6a84ddcdce6de0404e5340fa20c8676181bf5d381b17888107ba84 + + - type: archive + url: https://proxy.golang.org/github.com/stretchr/objx/@v/v0.1.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/stretchr/objx + sha256: 1fa10dab404ed7fc8ed2a033f8784187d5df3513ced3841ce39e46d37850eb1d + + - type: archive + url: https://proxy.golang.org/github.com/stretchr/testify/@v/v1.3.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/stretchr/testify + sha256: 8c935aed71cc334d5bfdf04b34909d9965cf28f80198dec13fb954dc292e6588 + + - type: archive + url: https://proxy.golang.org/github.com/strukturag/libheif/@v/v1.15.2.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/strukturag/libheif + sha256: bec8ad8e81d33d96b9ea8d11036a14ff4501b62f2cb79dbe49147a701c5c1d38 + + - type: archive + url: https://proxy.golang.org/github.com/yuin/goldmark/@v/v1.4.13.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/github.com/yuin/goldmark + sha256: bb41a602b174345fda392c8ad83fcc93217c285c763699677630be90feb7a5e3 + + - type: archive + url: https://proxy.golang.org/golang.org/x/crypto/@v/v0.0.0-20210921155107-089bfa567519.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/crypto + sha256: eb2426a7891915213cc5da1da7b6fc6e9e2cf253d518d8e169e038e287f414e3 + + - type: archive + url: https://proxy.golang.org/golang.org/x/image/@v/v0.12.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/image + sha256: eee2ea2f688c5bbe2a8ce36ba57f37573f5b63828560cd34f8621f0f8d07e6bd + + - type: archive + url: https://proxy.golang.org/golang.org/x/mod/@v/v0.8.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/mod + sha256: 4ae8176799d8cda819e70731ba6855735003e7e4930436e34584c75c96c496e0 + + - type: archive + url: https://proxy.golang.org/golang.org/x/net/@v/v0.6.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/net + sha256: 7ff2f50b1f3a58833f867d1646421569a91d8c19a0999793c5af79b10c16b8b8 + + - type: archive + url: https://proxy.golang.org/golang.org/x/sync/@v/v0.3.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/sync + sha256: 1870e7a196f7119d4c6edba7de9cdfc49ee13c8cb7921f3a947568171c6152e0 + + - type: archive + url: https://proxy.golang.org/golang.org/x/sys/@v/v0.5.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/sys + sha256: cf47336ac1bf675fa6d6dd5ac5399b0143c513404c449fa3f3380a58123c7908 + + - type: archive + url: https://proxy.golang.org/golang.org/x/term/@v/v0.5.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/term + sha256: 7d89c49ab41306950128a0f4b7c67fb8e2d2f637ece8e024e6cf38d17a33193b + + - type: archive + url: https://proxy.golang.org/golang.org/x/text/@v/v0.13.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/text + sha256: ed544fb017e967c053892df7b068612fce707ba32b57f35824cb041e31c6ae0f + + - type: archive + url: https://proxy.golang.org/golang.org/x/tools/@v/v0.6.0.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/tools + sha256: 9a29c8904c2acd4b65825e916cbdaf417086f35bb68c54af9a6283a0e1341e85 + + - type: archive + url: https://proxy.golang.org/golang.org/x/xerrors/@v/v0.0.0-20190717185122-a985d3407aa7.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/golang.org/x/xerrors + sha256: c4e9f063cfed546c90f00a9657deac4f915a8994f8cbe6dbd3f18e79eb8302cf + + - type: archive + url: https://proxy.golang.org/gopkg.in/gographics/imagick.v3/@v/v3.4.3.zip + strip-components: 3 + dest: cmd/cbconvert-gui/vendor/gopkg.in/gographics/imagick.v3 + sha256: ae0a425a2ffcbe92447c5da005deff2c0aac1e25995c443b86ae4bd48861d9e1 diff --git a/cmd/cbconvert-gui/dist/linux/flatpak/modules.txt b/cmd/cbconvert-gui/dist/linux/flatpak/modules.txt new file mode 100644 index 0000000..d6cefa6 --- /dev/null +++ b/cmd/cbconvert-gui/dist/linux/flatpak/modules.txt @@ -0,0 +1,45 @@ +# github.com/chai2010/webp v1.1.1 +## explicit; go 1.17 +github.com/chai2010/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/fvbommel/sortorder v1.1.0 +## explicit; go 1.13 +github.com/fvbommel/sortorder +# github.com/gen2brain/cbconvert v0.0.0-20230913113913-6400ae14d89a +## explicit; go 1.21 +github.com/gen2brain/cbconvert +# github.com/gen2brain/go-fitz v1.23.1 +## explicit; go 1.20 +github.com/gen2brain/go-fitz +# github.com/gen2brain/go-unarr v0.1.7 +## explicit; go 1.18 +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.3.1 +## explicit +github.com/google/uuid +# golang.org/x/image v0.12.0 +## explicit; go 1.12 +golang.org/x/image/bmp +golang.org/x/image/ccitt +golang.org/x/image/tiff +golang.org/x/image/tiff/lzw +# golang.org/x/sync v0.3.0 +## explicit; go 1.17 +golang.org/x/sync/errgroup +# gopkg.in/gographics/imagick.v3 v3.4.3 +## explicit; go 1.13 +gopkg.in/gographics/imagick.v3/imagick +gopkg.in/gographics/imagick.v3/imagick/types diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Info.plist b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Info.plist new file mode 100644 index 0000000..a872529 --- /dev/null +++ b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Info.plist @@ -0,0 +1,35 @@ + + + + + CFBundleDevelopmentRegion + English + + CFBundleExecutable + cbconvert-gui + + CFBundleIconFile + icon + + CFBundleIdentifier + com.github.gen2brain.cbconvert + + CFBundleInfoDictionaryVersion + 6.0 + + CFBundleName + CBconvert + + CFBundlePackageType + APPL + + CFBundleShortVersionString + 1.0.0 + + CFBundleVersion + 1 + + NSHighResolutionCapable + True + + diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/CanonicalServiceMenu.nib b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/CanonicalServiceMenu.nib new file mode 100644 index 0000000..bb8afd7 Binary files /dev/null and b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/CanonicalServiceMenu.nib differ diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/CanonicalWindowMenu.nib b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/CanonicalWindowMenu.nib new file mode 100644 index 0000000..9233fa5 Binary files /dev/null and b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/CanonicalWindowMenu.nib differ diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupCocoaOutlineView.nib b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupCocoaOutlineView.nib new file mode 100644 index 0000000..e1a67b7 Binary files /dev/null and b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupCocoaOutlineView.nib differ diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupCocoaOutlineViewToggle.nib b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupCocoaOutlineViewToggle.nib new file mode 100644 index 0000000..fa9e4f5 Binary files /dev/null and b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupCocoaOutlineViewToggle.nib differ diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupMainMenu.nib b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupMainMenu.nib new file mode 100644 index 0000000..5cbd260 Binary files /dev/null and b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupMainMenu.nib differ diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupTextSpinner.nib b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupTextSpinner.nib new file mode 100644 index 0000000..e461b69 Binary files /dev/null and b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupTextSpinner.nib differ diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupTextSpinnerNoBindings.nib b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupTextSpinnerNoBindings.nib new file mode 100644 index 0000000..a250916 Binary files /dev/null and b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Base.lproj/IupTextSpinnerNoBindings.nib differ diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Info.plist b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Info.plist new file mode 100644 index 0000000..d3d4eeb --- /dev/null +++ b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/Info.plist @@ -0,0 +1,50 @@ + + + + + BuildMachineOSBuild + 19H2 + CFBundleDevelopmentRegion + en + CFBundleExecutable + iup + CFBundleIdentifier + br.puc-rio.tecgraf.iup + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + iup + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleSupportedPlatforms + + MacOSX + + CFBundleVersion + 1 + DTCompiler + com.apple.compilers.llvm.clang.1_0 + DTPlatformBuild + 12D4e + DTPlatformName + macosx + DTPlatformVersion + 11.1 + DTSDKBuild + 20C63 + DTSDKName + macosx11.1 + DTXcode + 1240 + DTXcodeBuild + 12D4e + LSMinimumSystemVersion + 10.14 + NSHumanReadableCopyright + Copyright © 2015 Tecgraf, PUC-Rio, Brazil. All rights reserved. + + diff --git a/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/icon.icns b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/icon.icns new file mode 100644 index 0000000..b0fae00 Binary files /dev/null and b/cmd/cbconvert-gui/dist/macos/CBconvert.app/Contents/Resources/icon.icns differ diff --git a/cmd/cbconvert-gui/dist/windows/icon.ico b/cmd/cbconvert-gui/dist/windows/icon.ico new file mode 100644 index 0000000..20805da Binary files /dev/null and b/cmd/cbconvert-gui/dist/windows/icon.ico differ diff --git a/cmd/cbconvert-gui/go.mod b/cmd/cbconvert-gui/go.mod new file mode 100644 index 0000000..2f09161 --- /dev/null +++ b/cmd/cbconvert-gui/go.mod @@ -0,0 +1,22 @@ +module github.com/gen2brain/cbconvert/cmd/cbconvert-gui + +go 1.21 + +require ( + github.com/gen2brain/cbconvert v0.0.0-20230913113913-6400ae14d89a + github.com/gen2brain/iup-go/iup v0.0.0-20230906093706-8b037fe6a7bd + github.com/godbus/dbus/v5 v5.1.0 +) + +require ( + github.com/chai2010/webp v1.1.1 // indirect + github.com/disintegration/imaging v1.6.2 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/fvbommel/sortorder v1.1.0 // indirect + github.com/gen2brain/go-fitz v1.23.1 // indirect + github.com/gen2brain/go-unarr v0.1.7 // indirect + github.com/google/uuid v1.3.1 // indirect + golang.org/x/image v0.12.0 // indirect + golang.org/x/sync v0.3.0 // indirect + gopkg.in/gographics/imagick.v3 v3.4.3 // indirect +) diff --git a/cmd/cbconvert-gui/go.sum b/cmd/cbconvert-gui/go.sum new file mode 100644 index 0000000..11ce282 --- /dev/null +++ b/cmd/cbconvert-gui/go.sum @@ -0,0 +1,58 @@ +github.com/chai2010/webp v1.1.1 h1:jTRmEccAJ4MGrhFOrPMpNGIJ/eybIgwKpcACsrTEapk= +github.com/chai2010/webp v1.1.1/go.mod h1:0XVwvZWdjjdxpUEIf7b9g9VkHFnInUSYujwqTLEuldU= +github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= +github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= +github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/gen2brain/cbconvert v0.0.0-20230913113913-6400ae14d89a h1:czcZxl/PPXyHWXdFoBeOSHLmPVf7JGm7SISBTDi4uKs= +github.com/gen2brain/cbconvert v0.0.0-20230913113913-6400ae14d89a/go.mod h1:3zoSNHGpunxvS5cXpge9XwU585Zxsr4ly13dryeQCGk= +github.com/gen2brain/go-fitz v1.23.1 h1:x69/szWZXpI3jZ57mMqCg7WqqvtYnQG0lXts3L6M1Fc= +github.com/gen2brain/go-fitz v1.23.1/go.mod h1:HU04vc+RisUh/kvEd2pB0LAxmK1oyXdN4ftyshUr9rQ= +github.com/gen2brain/go-unarr v0.1.7 h1:mEE7bPShJIsmAX67t6BW2ibpEUO7j5WK152KgNM9NbQ= +github.com/gen2brain/go-unarr v0.1.7/go.mod h1:MK9a3hddpaIxjEtrE1f/LA5yJ7gA34cS7Oyr325sY9s= +github.com/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.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +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.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= +golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/gographics/imagick.v3 v3.4.3 h1:9plKFE/Us913jBN6KohtLG9FNW8LPvfpjiGAORIiEHg= +gopkg.in/gographics/imagick.v3 v3.4.3/go.mod h1:+Q9nyA2xRZXrDyTtJ/eko+8V/5E7bWYs08ndkZp8UmA= diff --git a/cmd/cbconvert-gui/main.go b/cmd/cbconvert-gui/main.go new file mode 100644 index 0000000..3c5726f --- /dev/null +++ b/cmd/cbconvert-gui/main.go @@ -0,0 +1,1025 @@ +package main + +import ( + "bytes" + "context" + _ "embed" + "errors" + "fmt" + "image/gif" + "image/png" + "net/url" + "os" + "runtime/debug" + "strconv" + "strings" + + "github.com/gen2brain/cbconvert" + "github.com/gen2brain/iup-go/iup" +) + +//go:generate rsrc --ico dist/windows/icon.ico --arch amd64 -o main_windows_amd64.syso + +//go:embed assets/icon.png +var appIcon []byte + +//go:embed assets/loading.gif +var appLoading []byte + +var appVersion string + +var ( + index = -1 + files []cbconvert.File +) + +func init() { + _ = os.Setenv("GDK_BACKEND", "x11") + + 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) > 7 { + appVersion = kv.Value[:7] + } + } + } +} + +func main() { + iup.Open() + defer iup.Close() + + iup.SetGlobal("UTF8MODE", "YES") + iup.SetGlobal("UTF8MODE_FILE", "YES") + + img, _ := png.Decode(bytes.NewReader(appIcon)) + iup.ImageFromImage(img).SetHandle("icon") + + dlg := iup.Dialog(layout()).SetAttributes(fmt.Sprintf(`TITLE="CBconvert %s", ICON=icon`, appVersion)).SetHandle("dlg") + + dlg.SetCallback("POSTMESSAGE_CB", iup.PostMessageFunc(func(ih iup.Ihandle, s string, i int, p any) int { + sp := strings.Split(s, ": ") + if len(sp) > 1 { + iup.MessageError(ih, fmt.Sprintf("%s\n\n%s", sp[0], strings.Join(sp[1:], ": "))) + } + + return iup.DEFAULT + })) + + dlg.SetCallback("RESIZE_CB", iup.ResizeFunc(func(ih iup.Ihandle, width, height int) int { + iup.GetHandle("Preview").SetAttribute("IMAGE", "") + iup.Refresh(ih) + + previewPost() + + return iup.DEFAULT + })) + + iup.Map(dlg) + setActive() + + iup.ShowXY(dlg, iup.CENTER, iup.CENTER) + iup.MainLoop() +} + +func options() cbconvert.Options { + var opts cbconvert.Options + opts.Recursive = iup.GetHandle("Recursive").GetAttribute("VALUE") == "ON" + opts.NoRGB = iup.GetHandle("NoRGB").GetAttribute("VALUE") == "ON" + opts.NoCover = iup.GetHandle("NoCover").GetAttribute("VALUE") == "ON" + opts.Size = iup.GetHandle("Size").GetInt("VALUE") + opts.OutDir = iup.GetHandle("OutDir").GetAttribute("VALUE") + opts.Suffix = iup.GetHandle("Suffix").GetAttribute("VALUE") + opts.NoConvert = iup.GetHandle("NoConvert").GetAttribute("VALUE") == "ON" + opts.NoNonImage = iup.GetHandle("NoNonImage").GetAttribute("VALUE") == "ON" + opts.Archive = strings.ToLower(iup.GetHandle("Archive").GetAttribute("VALUESTRING")) + opts.Format = strings.ToLower(iup.GetHandle("Format").GetAttribute("VALUESTRING")) + opts.Width = iup.GetHandle("Width").GetInt("VALUE") + opts.Height = iup.GetHandle("Height").GetInt("VALUE") + opts.Fit = iup.GetHandle("Fit").GetAttribute("VALUE") == "ON" + opts.Filter = iup.GetHandle("Filter").GetInt("VALUE") - 1 + opts.Quality = iup.GetHandle("Quality").GetInt("VALUE") + opts.Grayscale = iup.GetHandle("Grayscale").GetAttribute("VALUE") == "ON" + opts.Brightness = iup.GetHandle("Brightness").GetInt("VALUE") + opts.Contrast = iup.GetHandle("Contrast").GetInt("VALUE") + opts.Rotate = iup.GetHandle("Rotate").GetInt("VALUESTRING") + opts.LevelsInMin = iup.GetHandle("LevelsInMin").GetInt("VALUE") + opts.LevelsInMax = iup.GetHandle("LevelsInMax").GetInt("VALUE") + opts.LevelsOutMin = iup.GetHandle("LevelsOutMin").GetInt("VALUE") + opts.LevelsOutMax = iup.GetHandle("LevelsOutMax").GetInt("VALUE") + opts.LevelsGamma = iup.GetHandle("LevelsGamma").GetDouble("VALUE") + + return opts +} + +func setActive() { + opts := options() + count := iup.GetHandle("List").GetInt("COUNT") + + if count == 0 { + iup.GetHandle("Remove").SetAttribute("ACTIVE", "NO") + iup.GetHandle("RemoveAll").SetAttribute("ACTIVE", "NO") + + iup.GetHandle("Preview").SetAttribute("IMAGE", "") + iup.GetHandle("PreviewInfo").SetAttribute("TITLE", "") + } else { + if index != -1 { + iup.GetHandle("Remove").SetAttribute("ACTIVE", "YES") + } + iup.GetHandle("RemoveAll").SetAttribute("ACTIVE", "YES") + } + + if opts.OutDir == "" { + iup.GetHandle("Thumbnail").SetAttributes(`ACTIVE=NO`) + iup.GetHandle("Cover").SetAttributes(`ACTIVE=NO`) + iup.GetHandle("Convert").SetAttributes(`ACTIVE=NO`) + if count > 0 { + iup.GetHandle("Thumbnail").SetAttributes(`ACTIVE=NO, TIP="Set Output Directory"`) + iup.GetHandle("Cover").SetAttributes(`ACTIVE=NO, TIP="Set Output Directory"`) + iup.GetHandle("Convert").SetAttributes(`ACTIVE=NO, TIP="Set Output Directory"`) + } + } else { + if count > 0 { + iup.GetHandle("Thumbnail").SetAttributes(`ACTIVE=YES, TIP=""`) + iup.GetHandle("Cover").SetAttributes(`ACTIVE=YES, TIP=""`) + iup.GetHandle("Convert").SetAttributes(`ACTIVE=YES, TIP=""`) + } else { + iup.GetHandle("Thumbnail").SetAttributes(`ACTIVE=NO`) + iup.GetHandle("Cover").SetAttributes(`ACTIVE=NO`) + iup.GetHandle("Convert").SetAttributes(`ACTIVE=NO`) + } + } + + if opts.NoConvert { + iup.GetHandle("VboxImage").SetAttribute("ACTIVE", "NO") + iup.GetHandle("VboxTransform").SetAttribute("ACTIVE", "NO") + } else { + iup.GetHandle("VboxImage").SetAttribute("ACTIVE", "YES") + iup.GetHandle("VboxTransform").SetAttribute("ACTIVE", "YES") + } + + if (opts.Format == "jpeg" || opts.Format == "webp" || opts.Format == "avif" || opts.Format == "jxl") && !opts.NoConvert { + iup.GetHandle("VboxQuality").SetAttribute("ACTIVE", "YES") + } else { + iup.GetHandle("VboxQuality").SetAttribute("ACTIVE", "NO") + } + + if opts.Width != 0 && opts.Height != 0 && !opts.NoConvert { + iup.GetHandle("Fit").SetAttribute("ACTIVE", "YES") + } else { + iup.GetHandle("Fit").SetAttribute("ACTIVE", "NO") + } +} + +func layout() iup.Ihandle { + return iup.Vbox( + iup.Hbox( + preview(), + iup.Hbox( + iup.Vbox( + list(), + tabs(), + ).SetAttributes("NGAP=5"), + ).SetAttributes("NGAP=5"), + buttons(), + ).SetAttributes("NGAP=5, NMARGIN=5x5"), + + iup.Label("").SetAttributes("SEPARATOR=HORIZONTAL"), + status(), + ) +} + +func list() iup.Ihandle { + return iup.Vbox( + iup.List().SetAttributes("EXPAND=YES, VISIBLECOLUMNS=16, VISIBLELINES=5").SetHandle("List"). + SetCallback("ACTION", iup.ListActionFunc(func(ih iup.Ihandle, text string, item int, state int) int { + if state == 1 { + index = item - 1 + setActive() + previewPost() + } + + return iup.DEFAULT + })). + SetCallback("DROPFILES_CB", iup.DropFilesFunc(func(ih iup.Ihandle, fileName string, num, x, y int) int { + dec, err := url.QueryUnescape(fileName) + if err != nil { + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + return iup.DEFAULT + } + + conv := cbconvert.New(options()) + + fs, err := conv.Files([]string{dec}) + if err != nil { + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + return iup.DEFAULT + } + + for _, file := range fs { + iup.SetAttribute(iup.GetHandle("List"), "APPENDITEM", fmt.Sprintf("%s (%s)", file.Name, file.SizeHuman)) + files = append(files, file) + } + + setActive() + + return iup.DEFAULT + })), + ) +} + +func previewPost() { + if index == -1 || len(files) == 0 { + return + } + + width, height := previewSize() + iup.GetHandle("Loading").SetAttributes("VISIBLE=YES, START=YES") + if strings.ToLower(iup.GetGlobal("DRIVER")) == "motif" { + iup.GetHandle("Preview").SetAttribute("IMAGE", "") + } + + opts := options() + + go func(opts cbconvert.Options) { + conv := cbconvert.New(opts) + + conv.Initialize() + defer conv.Terminate() + + file := files[index] + img, err := conv.Preview(file.Path, file.Stat, width, height) + if err != nil { + fmt.Println(err) + } + + iup.PostMessage(iup.GetHandle("Preview"), "", 0, img) + }(opts) +} + +func previewSize() (int, int) { + var width, height int + sp := strings.Split(iup.GetHandle("Preview").GetAttribute("RASTERSIZE"), "x") + if len(sp) == 2 { + width, _ = strconv.Atoi(sp[0]) + height, _ = strconv.Atoi(sp[1]) + } + + return width, height +} + +func preview() iup.Ihandle { + return iup.Frame( + iup.Vbox( + iup.Label("").SetAttributes("EXPAND=YES, ALIGNMENT=ACENTER, MINSIZE=400x, IMAGE=cover").SetHandle("Preview"). + SetCallback("POSTMESSAGE_CB", iup.PostMessageFunc(func(ih iup.Ihandle, s string, i int, p any) int { + img := p.(cbconvert.Image) + + if img.Image != nil { + iup.Destroy(iup.GetHandle("cover")) + iup.ImageFromImage(img.Image).SetHandle("cover") + ih.SetAttribute("IMAGE", "cover") + } + + iup.GetHandle("Loading").SetAttributes("VISIBLE=NO, STOP=YES") + iup.GetHandle("PreviewInfo").SetAttribute("TITLE", fmt.Sprintf("%s (%dx%d)", img.SizeHuman, img.Width, img.Height)) + + return iup.DEFAULT + })), + iup.Label("").SetAttributes("EXPAND=HORIZONTAL, ALIGNMENT=ACENTER").SetHandle("PreviewInfo"), + ), + ) +} + +func tabs() iup.Ihandle { + vboxInput := iup.Vbox( + iup.Toggle(" Recurse SubDirectories").SetHandle("Recursive"). + SetAttributes(`TIP="Process subdirectories recursively"`), + iup.Toggle(" Only Grayscale Images").SetHandle("NoRGB"). + SetAttributes(`TIP="Do not convert images that have RGB colorspace"`), + iup.Toggle(" Exclude Cover").SetHandle("NoCover"). + SetAttributes(`TIP="Do not convert the cover image"`), + iup.Toggle(" Do not Transform or Convert Images").SetHandle("NoConvert"). + SetAttributes(`TIP="Copy images from archive or directory without modifications"`). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + setActive() + + return iup.DEFAULT + })), + iup.Vbox( + iup.Label("Minimum Size (MiB):"), + iup.Text().SetAttributes(`SPIN=YES, SPINMAX=2048, VISIBLECOLUMNS=4, MASK="/d*"`).SetHandle("Size"). + SetAttributes(`TIP="Process only files larger than minimum size"`), + ), + iup.Space().SetAttributes("EXPAND=HORIZONTAL"), + ).SetHandle("VboxInput").SetAttributes("MARGIN=5x5, GAP=5") + + vboxOutput := iup.Vbox( + iup.Vbox( + iup.Label("Output Directory:"), + iup.Text().SetAttributes("VISIBLECOLUMNS=16, MINSIZE=100x").SetHandle("OutDir"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + setActive() + + return iup.DEFAULT + })), + iup.Button("Browse...").SetAttributes("PADDING=DEFAULTBUTTONPADDING"). + SetCallback("ACTION", iup.ActionFunc(onOutputDirectory)), + ), + iup.Vbox( + iup.Label("Add Suffix to Output File:"), + iup.Text().SetAttributes("VISIBLECOLUMNS=16, MINSIZE=100x").SetHandle("Suffix"). + SetAttribute("TIP", "Add suffix to filename, i.e. filename_suffix.cbz"), + ), + iup.Vbox( + iup.Toggle(" Remove Non-Image Files from the Archive").SetHandle("NoNonImage"). + SetAttribute("TIP", "Remove .nfo, .xml, .txt files from the archive"), + ), + iup.Vbox( + iup.Label("Archive Format:"), + iup.List().SetAttributes(map[string]string{ + "DROPDOWN": "YES", + "VALUE": "1", + "1": "ZIP", + "2": "TAR", + }).SetHandle("Archive"), + ), + ).SetHandle("VboxOutput").SetAttributes("MARGIN=5x5, GAP=5") + + vboxImage := iup.Vbox( + iup.Vbox( + iup.Label("Format:"), + iup.List().SetAttributes(map[string]string{ + "DROPDOWN": "YES", + "VALUE": "1", + "1": "JPEG", + "2": "PNG", + "3": "TIFF", + "4": "BMP", + "5": "WEBP", + "6": "AVIF", + "7": "JXL", + }).SetHandle("Format"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + setActive() + previewPost() + + return iup.DEFAULT + })), + ), + iup.Vbox( + iup.Label("Size:"), + iup.Hbox( + iup.Text().SetAttributes(`CUEBANNER=" width", VISIBLECOLUMNS=4, MASK="/d*"`).SetHandle("Width"). + SetAttribute("TIP", "If one of, width or height is not set, the image aspect ratio is preserved"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + setActive() + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + iup.Label("x"), + iup.Text().SetAttributes(`CUEBANNER=" height", VISIBLECOLUMNS=4, MASK="/d*"`).SetHandle("Height"). + SetAttribute("TIP", "If one of, width or height is not set, the image aspect ratio is preserved"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + setActive() + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + ).SetAttributes("ALIGNMENT=ACENTER, MARGIN=0"), + ), + iup.Vbox( + iup.Toggle(" Best Fit").SetHandle("Fit"). + SetAttributes(`TIP="Best fit for required width and height"`), + ), + iup.Vbox( + iup.Label("Resize Filter:"), + iup.List().SetAttributes(map[string]string{ + "DROPDOWN": "YES", + "VALUE": "3", + "TIP": "Linear is the bilinear filter, smooth and reasonably fast", + "1": "NearestNeighbor", + "2": "Box", + "3": "Linear", + "4": "MitchellNetravali", + "5": "CatmullRom", + "6": "Gaussian", + "7": "Lanczos", + }).SetHandle("Filter").SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(onFilterChanged)), + ), + iup.Vbox( + iup.Hbox( + iup.Label("Quality: "), + iup.Label("75").SetHandle("LabelQuality"), + ).SetAttributes("MARGIN=0"), + iup.Val("").SetAttributes(`MIN=0, MAX=100, VALUE=75, SHOWTICKS=10`).SetHandle("Quality"). + SetAttribute("TIP", "Quality affects JPEG, WEBP, AVIF and JXL"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + iup.GetHandle("LabelQuality").SetAttribute("TITLE", ih.GetInt("VALUE")) + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + ).SetHandle("VboxQuality"), + iup.Vbox( + iup.Toggle(" Grayscale").SetHandle("Grayscale"). + SetAttributes(`TIP="Convert images to grayscale (monochromatic)"`). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + previewPost() + + return iup.DEFAULT + })), + ), + ).SetHandle("VboxImage").SetAttributes("MARGIN=5x5, GAP=5") + + vboxTransform := iup.Vbox( + iup.Vbox( + iup.Hbox( + iup.Label("Brightness: "), + iup.Label("0").SetHandle("LabelBrightness"), + ).SetAttributes("ALIGNMENT=ACENTER, MARGIN=0"), + iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Brightness"). + SetAttributes(`TIP="Adjust the brightness of the images"`). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + iup.GetHandle("LabelBrightness").SetAttribute("TITLE", iup.GetHandle("Brightness").GetInt("VALUE")) + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + ), + iup.Vbox( + iup.Hbox( + iup.Label("Contrast: "), + iup.Label("0").SetHandle("LabelContrast"), + ).SetAttributes("ALIGNMENT=ACENTER, MARGIN=0"), + iup.Val("").SetAttributes(`MIN=-100, MAX=100, VALUE=0, SHOWTICKS=10`).SetHandle("Contrast"). + SetAttributes(`TIP="Adjust the contrast of the images"`). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + iup.GetHandle("LabelContrast").SetAttribute("TITLE", iup.GetHandle("Contrast").GetInt("VALUE")) + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + ), + iup.Vbox( + iup.Label("Rotate:"), + iup.List().SetAttributes(map[string]string{ + "DROPDOWN": "YES", + "VALUE": "1", + "1": "0", + "2": "90", + "3": "180", + "4": "270", + }).SetHandle("Rotate"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + previewPost() + + return iup.DEFAULT + })), + ), + iup.Vbox( + iup.Label("Input Levels:"), + iup.Hbox( + iup.Text().SetAttributes(`SPIN=YES, SPINMAX=255, VALUE=0, VISIBLECOLUMNS=3, MASK="/d*"`). + SetHandle("LevelsInMin").SetAttribute("TIP", "Min"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + iup.Fill(), + iup.Val("").SetAttributes(`VALUE=1.0, SHOWTICKS=10`). + SetHandle("LevelsGamma").SetAttribute("TIP", "Gamma"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + iup.Fill(), + iup.Text().SetAttributes(`SPIN=YES, SPINMAX=255, VALUE=255, VISIBLECOLUMNS=3, MASK="/d*"`). + SetHandle("LevelsInMax").SetAttribute("TIP", "Max"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + ).SetAttributes("ALIGNMENT=ACENTER, MAXSIZE=340x"), + ), + iup.Vbox( + iup.Label("Output Levels:"), + iup.Hbox( + iup.Text().SetAttributes(`SPIN=YES, SPINMAX=255, VALUE=0, VISIBLECOLUMNS=3, MASK="/d*"`). + SetHandle("LevelsOutMin").SetAttribute("TIP", "Min"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + iup.Fill(), + iup.Text().SetAttributes(`SPIN=YES, SPINMAX=255, VALUE=255, VISIBLECOLUMNS=3, MASK="/d*"`). + SetHandle("LevelsOutMax").SetAttribute("TIP", "Max"). + SetCallback("VALUECHANGED_CB", iup.ValueChangedFunc(func(ih iup.Ihandle) int { + ih.SetAttribute("MYVALUE", ih.GetInt("VALUE")) + + return iup.DEFAULT + })). + SetCallback("KILLFOCUS_CB", iup.KillFocusFunc(func(ih iup.Ihandle) int { + if ih.GetAttribute("MYVALUE") != "" { + previewPost() + } + ih.SetAttribute("MYVALUE", "") + + return iup.DEFAULT + })), + ).SetAttributes("ALIGNMENT=ACENTER, MAXSIZE=340x"), + ), + ).SetHandle("VboxTransform").SetAttributes("MARGIN=5x5, GAP=5") + + return iup.Tabs( + vboxInput.SetAttributes("TABTITLE=Input"), + vboxOutput.SetAttributes("TABTITLE=Output"), + vboxImage.SetAttributes("TABTITLE=Image"), + vboxTransform.SetAttributes("TABTITLE=Transform"), + ).SetHandle("Tabs").SetAttributes("MINSIZE=320x400, EXPAND=HORIZONTAL") +} + +func buttons() iup.Ihandle { + return iup.Vbox( + iup.Frame( + iup.Vbox( + iup.Button("Add &Files...").SetHandle("AddFiles").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). + SetCallback("ACTION", iup.ActionFunc(onAddFiles)), + iup.Button("Add &Dir...").SetHandle("AddDir").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). + SetCallback("ACTION", iup.ActionFunc(onAddDir)), + iup.Button("Remove").SetHandle("Remove").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). + SetCallback("ACTION", iup.ActionFunc(onRemove)), + iup.Button("Remove All").SetHandle("RemoveAll").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). + SetCallback("ACTION", iup.ActionFunc(onRemoveAll)), + ).SetAttributes("NGAP=5"), + ), + iup.Frame( + iup.Vbox( + iup.Button("Thumbnail").SetHandle("Thumbnail").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). + SetCallback("ACTION", iup.ActionFunc(onThumbnail)), + iup.Button("Cover").SetHandle("Cover").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). + SetCallback("ACTION", iup.ActionFunc(onCover)), + ).SetAttributes("NGAP=5"), + ), + iup.Frame( + iup.Vbox( + iup.Button("&Convert").SetHandle("Convert").SetAttributes("EXPAND=HORIZONTAL, PADDING=DEFAULTBUTTONPADDING"). + SetCallback("ACTION", iup.ActionFunc(onConvert)), + ), + ), + ).SetHandle("Buttons").SetAttributes("ALIGNMENT=ACENTER, NGAP=10") +} + +func status() iup.Ihandle { + return iup.Hbox( + loading(), + iup.Fill(), + iup.Label("File 1 of 1").SetHandle("LabelStatus1").SetAttributes("VISIBLE=NO"), + iup.Space().SetAttribute("SIZE", "5x0"), + iup.Label("(000/000)").SetHandle("LabelStatus2").SetAttributes("VISIBLE=NO"), + iup.Space().SetAttribute("SIZE", "5x0"), + iup.ProgressBar().SetAttributes("RASTERSIZE=200x15, VISIBLE=NO").SetHandle("ProgressBar"). + SetCallback("POSTMESSAGE_CB", iup.PostMessageFunc(func(ih iup.Ihandle, s string, i int, p any) int { + switch s { + case "convert": + conv := p.(*cbconvert.Convertor) + ih.SetAttributes("VALUE=0, VISIBLE=YES") + ih.SetAttribute("MAX", conv.Ncontents) + + iup.GetHandle("List").SetAttributes("ACTIVE=NO") + iup.GetHandle("Tabs").SetAttributes("ACTIVE=NO") + iup.GetHandle("Buttons").SetAttributes("ACTIVE=NO") + + iup.GetHandle("LabelStatus1").SetAttribute("TITLE", fmt.Sprintf("File %d of %d", conv.CurrFile, conv.Nfiles)) + iup.GetHandle("LabelStatus1").SetAttributes("VISIBLE=YES") + iup.GetHandle("LabelStatus2").SetAttributes("VISIBLE=YES") + + iup.Refresh(iup.GetHandle("StatusBar")) + case "start": + conv := p.(*cbconvert.Convertor) + ih.SetAttributes("VALUE=0, VISIBLE=YES") + ih.SetAttribute("MAX", conv.Nfiles) + + iup.GetHandle("List").SetAttributes("ACTIVE=NO") + iup.GetHandle("Tabs").SetAttributes("ACTIVE=NO") + iup.GetHandle("Buttons").SetAttributes("ACTIVE=NO") + + iup.GetHandle("LabelStatus2").SetAttributes("VISIBLE=YES") + case "progress": + conv := p.(*cbconvert.Convertor) + ih.SetAttribute("VALUE", conv.CurrContent) + iup.GetHandle("LabelStatus2").SetAttribute("TITLE", fmt.Sprintf("(%03d/%03d)", conv.CurrContent, conv.Ncontents)) + + iup.Refresh(iup.GetHandle("StatusBar")) + case "progress2": + conv := p.(*cbconvert.Convertor) + ih.SetAttribute("VALUE", conv.CurrFile) + iup.GetHandle("LabelStatus2").SetAttribute("TITLE", fmt.Sprintf("(%03d/%03d)", conv.CurrFile, conv.Nfiles)) + + iup.Refresh(iup.GetHandle("StatusBar")) + case "finish": + iup.GetHandle("List").SetAttributes("ACTIVE=YES") + iup.GetHandle("Tabs").SetAttributes("ACTIVE=YES") + iup.GetHandle("Buttons").SetAttributes("ACTIVE=YES") + + iup.GetHandle("LabelStatus1").SetAttributes(`TITLE="", VISIBLE=NO`) + iup.GetHandle("LabelStatus2").SetAttributes(`TITLE="", VISIBLE=NO`) + ih.SetAttributes("VALUE=0, VISIBLE=NO") + + iup.Refresh(iup.GetHandle("StatusBar")) + + iup.GetHandle("dlg").SetCallback("K_ANY", nil) + iup.GetHandle("dlg").SetCallback("CLOSE_CB", nil) + } + + return iup.DEFAULT + })), + iup.Space().SetAttribute("SIZE", "5x0"), + ).SetAttributes("ALIGNMENT=ACENTER, NMARGIN=5x5").SetHandle("StatusBar") +} + +func loading() iup.Ihandle { + img, _ := gif.DecodeAll(bytes.NewReader(appLoading)) + animation := iup.User() + + for idx, i := range img.Image { + name := fmt.Sprintf("Loading%d", idx) + iup.ImageFromImage(i).SetHandle(name) + iup.Append(animation, iup.GetHandle(name)) + } + + return iup.AnimatedLabel(animation).SetAttributes("VISIBLE=NO").SetHandle("Loading") +} + +func onAddFiles(ih iup.Ihandle) int { + args, err := fileDlg("Add Files", true, false) + if err != nil { + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + return iup.DEFAULT + } + + if len(args) > 0 { + conv := cbconvert.New(options()) + + fs, err := conv.Files(args) + if err != nil { + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + return iup.DEFAULT + } + + for _, file := range fs { + iup.SetAttribute(iup.GetHandle("List"), "APPENDITEM", fmt.Sprintf("%s (%s)", file.Name, file.SizeHuman)) + files = append(files, file) + } + + setActive() + } + + return iup.DEFAULT +} + +func onAddDir(ih iup.Ihandle) int { + args, err := fileDlg("Add Directory", false, true) + if err != nil { + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + return iup.DEFAULT + } + + if len(args) > 0 { + conv := cbconvert.New(options()) + + fs, err := conv.Files(args) + if err != nil { + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + return iup.DEFAULT + } + + for _, file := range fs { + iup.SetAttribute(iup.GetHandle("List"), "APPENDITEM", fmt.Sprintf("%s (%s)", file.Name, file.SizeHuman)) + files = append(files, file) + } + + setActive() + } + + return iup.DEFAULT +} + +func onRemove(ih iup.Ihandle) int { + if index == -1 || len(files) == 0 { + return iup.IGNORE + } + + files = append(files[:index], files[index+1:]...) + + iup.GetHandle("List").SetAttribute("REMOVEITEM", iup.GetHandle("List").GetAttribute("VALUE")) + setActive() + + return iup.DEFAULT +} + +func onRemoveAll(ih iup.Ihandle) int { + index = -1 + files = make([]cbconvert.File, 0) + + iup.GetHandle("List").SetAttribute("REMOVEITEM", "ALL") + setActive() + + return iup.DEFAULT +} + +func onThumbnail(ih iup.Ihandle) int { + conv := cbconvert.New(options()) + conv.Nfiles = len(files) + + conv.OnProgress = func() { + iup.PostMessage(iup.GetHandle("ProgressBar"), "progress2", 0, conv) + } + + var canceled = false + conv.OnCancel = func() { + canceled = true + } + + iup.GetHandle("dlg").SetCallback("K_ANY", iup.KAnyFunc(func(ih iup.Ihandle, c int) int { + if c == iup.K_ESC { + conv.Cancel() + } + + return iup.DEFAULT + })) + + iup.PostMessage(iup.GetHandle("ProgressBar"), "start", 0, conv) + + go func(c *cbconvert.Convertor) { + c.Initialize() + defer c.Terminate() + + for _, file := range files { + if canceled { + break + } + + if err := c.Thumbnail(file.Path, file.Stat); err != nil { + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + continue + } + } + + iup.PostMessage(iup.GetHandle("ProgressBar"), "finish", 0, 0) + }(conv) + + return iup.DEFAULT +} + +func onCover(ih iup.Ihandle) int { + conv := cbconvert.New(options()) + conv.Nfiles = len(files) + + conv.OnProgress = func() { + iup.PostMessage(iup.GetHandle("ProgressBar"), "progress2", 0, conv) + } + + var canceled = false + conv.OnCancel = func() { + canceled = true + } + + iup.GetHandle("dlg").SetCallback("K_ANY", iup.KAnyFunc(func(ih iup.Ihandle, c int) int { + if c == iup.K_ESC { + conv.Cancel() + } + + return iup.DEFAULT + })) + + iup.PostMessage(iup.GetHandle("ProgressBar"), "start", 0, conv) + + go func(c *cbconvert.Convertor) { + c.Initialize() + defer c.Terminate() + + for _, file := range files { + if canceled { + break + } + + if err := c.Cover(file.Path, file.Stat); err != nil { + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + continue + } + } + + iup.PostMessage(iup.GetHandle("ProgressBar"), "finish", 0, 0) + }(conv) + + return iup.DEFAULT +} + +func onConvert(ih iup.Ihandle) int { + conv := cbconvert.New(options()) + conv.Nfiles = len(files) + + conv.OnStart = func() { + iup.PostMessage(iup.GetHandle("ProgressBar"), "convert", 0, conv) + } + + conv.OnProgress = func() { + iup.PostMessage(iup.GetHandle("ProgressBar"), "progress", 0, conv) + } + + iup.GetHandle("dlg").SetCallback("K_ANY", iup.KAnyFunc(func(ih iup.Ihandle, c int) int { + if c == iup.K_ESC { + conv.Cancel() + } + + return iup.DEFAULT + })).SetCallback("CLOSE_CB", iup.CloseFunc(func(ih iup.Ihandle) int { + if err := os.RemoveAll(conv.Workdir); err != nil { + fmt.Println(err) + } + + return iup.DEFAULT + })) + + go func(c *cbconvert.Convertor) { + c.Initialize() + defer c.Terminate() + + for _, file := range files { + if err := c.Convert(file.Path, file.Stat); err != nil { + if errors.Is(err, context.Canceled) { + if err := os.RemoveAll(c.Workdir); err != nil { + fmt.Println(err) + } + + break + } + + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + if err := os.RemoveAll(c.Workdir); err != nil { + fmt.Println(err) + } + + continue + } + } + + iup.PostMessage(iup.GetHandle("ProgressBar"), "finish", 0, 0) + }(conv) + + return iup.DEFAULT +} + +func onOutputDirectory(ih iup.Ihandle) int { + args, err := fileDlg("Output Directory", false, true) + if err != nil { + iup.PostMessage(iup.GetHandle("dlg"), err.Error(), 0, 0) + fmt.Println(err) + + return iup.DEFAULT + } + + if len(args) == 1 { + iup.GetHandle("OutDir").SetAttribute("VALUE", args[0]) + } + + setActive() + + return iup.DEFAULT +} + +func onFilterChanged(ih iup.Ihandle) int { + switch ih.GetInt("VALUE") { + case 1: + ih.SetAttribute("TIP", "NearestNeighbor is the fastest resampling filter, no antialiasing") + case 2: + ih.SetAttribute("TIP", "Box filter (averaging pixels)") + case 3: + ih.SetAttribute("TIP", "Linear is the bilinear filter, smooth and reasonably fast") + case 4: + ih.SetAttribute("TIP", "MitchellNetravali is a smooth bicubic filter") + case 5: + ih.SetAttribute("TIP", "CatmullRom is a sharp bicubic filter") + case 6: + ih.SetAttribute("TIP", "Gaussian is a blurring filter that uses gaussian function, useful for noise removal") + case 7: + ih.SetAttribute("TIP", "Lanczos is a high-quality resampling filter, it's slower than cubic filters") + } + + previewPost() + + return iup.DEFAULT +} diff --git a/cmd/cbconvert-gui/main_filedlg.go b/cmd/cbconvert-gui/main_filedlg.go new file mode 100644 index 0000000..064b007 --- /dev/null +++ b/cmd/cbconvert-gui/main_filedlg.go @@ -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 +} diff --git a/cmd/cbconvert-gui/main_filedlg_portal.go b/cmd/cbconvert-gui/main_filedlg_portal.go new file mode 100644 index 0000000..2dea3b3 --- /dev/null +++ b/cmd/cbconvert-gui/main_filedlg_portal.go @@ -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 +} diff --git a/cmd/cbconvert-gui/main_windows_amd64.syso b/cmd/cbconvert-gui/main_windows_amd64.syso new file mode 100644 index 0000000..fbd9cbe Binary files /dev/null and b/cmd/cbconvert-gui/main_windows_amd64.syso differ diff --git a/cmd/cbconvert-gui/make.bash b/cmd/cbconvert-gui/make.bash new file mode 100755 index 0000000..b9485ed --- /dev/null +++ b/cmd/cbconvert-gui/make.bash @@ -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}" diff --git a/cmd/cbconvert-gui/screenshots/README.md b/cmd/cbconvert-gui/screenshots/README.md new file mode 100644 index 0000000..9dcd4a6 --- /dev/null +++ b/cmd/cbconvert-gui/screenshots/README.md @@ -0,0 +1,13 @@ +## Screenshots + +Windows +Windows + +Linux +Linux + +macOS +macOS + +Linux Motif +Linux Motif diff --git a/cmd/cbconvert-gui/screenshots/linux-01.jpg b/cmd/cbconvert-gui/screenshots/linux-01.jpg new file mode 100644 index 0000000..3034e67 Binary files /dev/null and b/cmd/cbconvert-gui/screenshots/linux-01.jpg differ diff --git a/cmd/cbconvert-gui/screenshots/linux-02.jpg b/cmd/cbconvert-gui/screenshots/linux-02.jpg new file mode 100644 index 0000000..123cd04 Binary files /dev/null and b/cmd/cbconvert-gui/screenshots/linux-02.jpg differ diff --git a/cmd/cbconvert-gui/screenshots/macos-01.jpg b/cmd/cbconvert-gui/screenshots/macos-01.jpg new file mode 100644 index 0000000..c83e62d Binary files /dev/null and b/cmd/cbconvert-gui/screenshots/macos-01.jpg differ diff --git a/cmd/cbconvert-gui/screenshots/motif-01.jpg b/cmd/cbconvert-gui/screenshots/motif-01.jpg new file mode 100644 index 0000000..d8f0bbe Binary files /dev/null and b/cmd/cbconvert-gui/screenshots/motif-01.jpg differ diff --git a/cmd/cbconvert-gui/screenshots/windows-01.jpg b/cmd/cbconvert-gui/screenshots/windows-01.jpg new file mode 100644 index 0000000..4e88f46 Binary files /dev/null and b/cmd/cbconvert-gui/screenshots/windows-01.jpg differ diff --git a/cmd/cbconvert/make.bash b/cmd/cbconvert/make.bash index ed0abf6..976a76d 100755 --- a/cmd/cbconvert/make.bash +++ b/cmd/cbconvert/make.bash @@ -5,9 +5,11 @@ 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 '0.0.0'`" +VERSION="$(git --git-dir ../../.git describe --tags --abbrev=0 2>/dev/null || echo '0.0.0')" -BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR} +BUILDDIR="cbconvert-${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" \ @@ -15,46 +17,46 @@ PKG_CONFIG_LIBDIR="$GLIBC_x86_64/usr/lib64/pkgconfig" \ CGO_CFLAGS="-I$GLIBC_x86_64/usr/include" \ CGO_LDFLAGS="-L$GLIBC_x86_64/usr/lib64" \ CGO_ENABLED=1 GOOS=linux GOARCH=amd64 \ -go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION} '-extldflags=-static'" && \ -cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && tar -czf "${BUILDDIR}-linux-x86_64.tar.gz" ${BUILDDIR} -rm -rf ${BUILDDIR} +go build -trimpath -tags 'extlib pkgconfig' -v -o "${BUILDDIR}"/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION} '-extldflags=-static'" && \ +cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && tar -czf "${BUILDDIR}-linux-x86_64.tar.gz" "${BUILDDIR}" +rm -rf "${BUILDDIR}" -BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${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_LDFLAGS="-L$MINGW_x86_64/usr/lib -ljxl -ljxl_dec -ljxl_profiler -ljxl_threads" \ CGO_ENABLED=1 GOOS=windows GOARCH=amd64 \ -go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert.exe -ldflags "-s -w -X main.appVersion=${VERSION} '-extldflags=-static -Wl,--allow-multiple-definition'" && \ -cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && zip -rq "${BUILDDIR}-windows-x86_64.zip" ${BUILDDIR} -rm -rf ${BUILDDIR} +go build -trimpath -tags 'extlib pkgconfig' -v -o "${BUILDDIR}"/cbconvert.exe -ldflags "-s -w -X main.appVersion=${VERSION} '-extldflags=-static -Wl,--allow-multiple-definition'" && \ +cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && zip -rq "${BUILDDIR}-windows-x86_64.zip" "${BUILDDIR}" +rm -rf "${BUILDDIR}" export OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1 -BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR} +mkdir -p "${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.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 \ -go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION}" && \ -cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && zip -rq "${BUILDDIR}-darwin-x86_64.zip" ${BUILDDIR} -rm -rf ${BUILDDIR} +go build -trimpath -tags 'extlib pkgconfig' -v -o "${BUILDDIR}"/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION}" && \ +cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && zip -rq "${BUILDDIR}-darwin-x86_64.zip" "${BUILDDIR}" +rm -rf "${BUILDDIR}" export OSXCROSS_PKG_CONFIG_USE_NATIVE_VARIABLES=1 -BUILDDIR="cbconvert-${VERSION}"; mkdir -p ${BUILDDIR} +mkdir -p "${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.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 \ -go build -trimpath -tags 'extlib pkgconfig' -v -o ${BUILDDIR}/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION}" && \ -cp ../../README.md ../../AUTHORS ../../COPYING ${BUILDDIR} && zip -rq "${BUILDDIR}-darwin-aarch64.zip" ${BUILDDIR} -rm -rf ${BUILDDIR} +go build -trimpath -tags 'extlib pkgconfig' -v -o "${BUILDDIR}"/cbconvert -ldflags "-linkmode external -s -w -X main.appVersion=${VERSION}" && \ +cp ../../README.md ../../AUTHORS ../../COPYING "${BUILDDIR}" && zip -rq "${BUILDDIR}-darwin-aarch64.zip" "${BUILDDIR}" +rm -rf "${BUILDDIR}" diff --git a/cmd/cbconvert/screenshots/thumbnails.jpg b/cmd/cbconvert/screenshots/thumbnails.jpg new file mode 100644 index 0000000..719b137 Binary files /dev/null and b/cmd/cbconvert/screenshots/thumbnails.jpg differ