diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml
index 650a55b..2d2a801 100644
--- a/.github/workflows/docker-publish.yml
+++ b/.github/workflows/docker-publish.yml
@@ -24,17 +24,17 @@ jobs:
uses: actions/checkout@v6
- name: Login to GitHub Container Registry
- uses: docker/login-action@v3
+ uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up QEMU
- uses: docker/setup-qemu-action@v3
+ uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
+ uses: docker/setup-buildx-action@v4
- name: Set Release Date
id: release_date
@@ -43,7 +43,7 @@ jobs:
- name: Docker meta
id: meta
- uses: docker/metadata-action@v5
+ uses: docker/metadata-action@v6
with:
images: ghcr.io/${{ github.repository_owner }}/kcc
# Always creates the "latest" tag
@@ -54,7 +54,7 @@ jobs:
type=raw,value=${{ steps.release_date.outputs.release_date }}
- name: Build and push
- uses: docker/build-push-action@v6
+ uses: docker/build-push-action@v7
with:
platforms: linux/amd64,linux/arm64,linux/arm/v7
context: .
diff --git a/.github/workflows/package-linux.yml b/.github/workflows/package-linux.yml
index b1d22d8..a862ee2 100644
--- a/.github/workflows/package-linux.yml
+++ b/.github/workflows/package-linux.yml
@@ -59,12 +59,12 @@ jobs:
env:
UPDATE_INFO: gh-releases-zsync|ciromattia|kcc|latest|*x86_64.AppImage.zsync
- name: upload artifact
- uses: actions/upload-artifact@v6
+ uses: actions/upload-artifact@v7
with:
name: AppImage
path: './*.AppImage*'
- name: Release
- uses: softprops/action-gh-release@v2
+ uses: softprops/action-gh-release@v3
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
diff --git a/.github/workflows/package-macos.yml b/.github/workflows/package-macos.yml
index 7d56f76..7bdf9ea 100644
--- a/.github/workflows/package-macos.yml
+++ b/.github/workflows/package-macos.yml
@@ -80,12 +80,12 @@ jobs:
run: |
python setup.py build_binary
- name: upload build
- uses: actions/upload-artifact@v6
+ uses: actions/upload-artifact@v7
with:
name: mac-os-build-${{ runner.arch }}
path: dist/*.dmg
- name: Release
- uses: softprops/action-gh-release@v2
+ uses: softprops/action-gh-release@v3
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
diff --git a/.github/workflows/package-osx-legacy.yml b/.github/workflows/package-osx-legacy.yml
index 8094d3b..57c0118 100644
--- a/.github/workflows/package-osx-legacy.yml
+++ b/.github/workflows/package-osx-legacy.yml
@@ -51,12 +51,12 @@ jobs:
run: |
python3 setup.py build_binary
- name: upload build
- uses: actions/upload-artifact@v6
+ uses: actions/upload-artifact@v7
with:
name: osx-build-${{ runner.arch }}
path: dist/*.dmg
- name: Release
- uses: softprops/action-gh-release@v2
+ uses: softprops/action-gh-release@v3
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
diff --git a/.github/workflows/package-windows.yml b/.github/workflows/package-windows.yml
index 7653218..6dfbd73 100644
--- a/.github/workflows/package-windows.yml
+++ b/.github/workflows/package-windows.yml
@@ -53,12 +53,12 @@ jobs:
python setup.py ${{ matrix.command }}
- name: upload-unsigned-artifact
id: upload-unsigned-artifact
- uses: actions/upload-artifact@v6
+ uses: actions/upload-artifact@v7
with:
name: windows-build-${{ matrix.entry }}
path: dist/*.exe
- id: optional_step_id
- uses: signpath/github-action-submit-signing-request@v2.0
+ uses: signpath/github-action-submit-signing-request@v2.2
if: ${{ github.repository == 'ciromattia/kcc' }}
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
@@ -69,7 +69,7 @@ jobs:
wait-for-completion: true
output-artifact-directory: 'dist/'
- name: Release
- uses: softprops/action-gh-release@v2
+ uses: softprops/action-gh-release@v3
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
diff --git a/.github/workflows/package-windows7.yml b/.github/workflows/package-windows7.yml
index 5e55c27..adbb476 100644
--- a/.github/workflows/package-windows7.yml
+++ b/.github/workflows/package-windows7.yml
@@ -46,12 +46,12 @@ jobs:
python setup.py build_binary
- name: upload-unsigned-artifact
id: upload-unsigned-artifact
- uses: actions/upload-artifact@v6
+ uses: actions/upload-artifact@v7
with:
name: windows7-build
path: dist/*.exe
- id: optional_step_id
- uses: signpath/github-action-submit-signing-request@v2.0
+ uses: signpath/github-action-submit-signing-request@v2.2
if: ${{ github.repository == 'ciromattia/kcc' }}
with:
api-token: '${{ secrets.SIGNPATH_API_TOKEN }}'
@@ -62,7 +62,7 @@ jobs:
wait-for-completion: true
output-artifact-directory: 'dist/'
- name: Release
- uses: softprops/action-gh-release@v2
+ uses: softprops/action-gh-release@v3
if: startsWith(github.ref, 'refs/tags/')
with:
prerelease: true
diff --git a/.gitignore b/.gitignore
index 0f952a0..a27db6f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,6 @@
Pipfile
Pipfile.lock
setup.bat
-kindlecomicconverter/sentry.py
other/windows/kindlegen.exe
dist/
build/
diff --git a/README.md b/README.md
index 7624d58..6ff5197 100644
--- a/README.md
+++ b/README.md
@@ -247,7 +247,7 @@ MAIN:
PROCESSING:
-n, --noprocessing Do not modify image and ignore any profile or processing option
- --pdfextract Use legacy PDF image extraction method from KCC 8 and earlier.
+ --legacyextract Use legacy PDF/EPUB image extraction method from earlier KCC versions.
--pdfwidth Render vector PDFs based on device width instead of height.
-u, --upscale Resize images smaller than device's resolution
-s, --stretch Stretch images to device's resolution
@@ -297,6 +297,7 @@ OUTPUT SETTINGS:
-b BATCHSPLIT, --batchsplit BATCHSPLIT
Split output into multiple files. 0: Don't split 1: Automatic mode 2: Consider every subdirectory as separate volume [Default=0]
--spreadshift Shift first page to opposite side in landscape for two page spread alignment
+ --onepagelandscape Show a single centered page in landscape
--norotate Do not rotate double page spreads in spread splitter option.
--rotateright Rotate double page spreads in opposite direction.
--rotatefirst Put rotated spread first in spread splitter option.
@@ -442,7 +443,6 @@ Older links (dead):
## PRIVACY
**KCC** is initiating internet connections in two cases:
* During startup - Version check and announcement check.
-* When error occurs - Automatic reporting on Windows and macOS.
## KNOWN ISSUES
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).
diff --git a/gui/KCC.ui b/gui/KCC.ui
index 9cc41d3..17e749d 100644
--- a/gui/KCC.ui
+++ b/gui/KCC.ui
@@ -750,14 +750,12 @@ Higher values are larger and higher quality, and may resolve blank page issues.<
-
-
+
- Use the PDF image extraction method from KCC 8 and earlier.
-
-Useful for really weird PDFs.
+ <html><head/><body><p>Use the PDF/EPUB image extraction method from older KCC versions.</p><p><br/></p><p>Use if standard extraction fails for whatever reason.</p></body></html>
- PDF Legacy Extract
+ Legacy Extract
@@ -885,7 +883,7 @@ Ignored for Kindle EPUB/MOBI and all PDF.
- -
+
-
<html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - Main Drive<br/></span>Use dedicated temporary directory on main OS drive.</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - Source File Drive<br/></span>Create temporary file directory on source file drive.</p></body></html>
@@ -895,6 +893,16 @@ Ignored for Kindle EPUB/MOBI and all PDF.
+ -
+
+
+ <html><head/><body><p><span style=" font-weight:600; text-decoration: underline;">Unchecked - 2 page landscape<br/></span>2 viewports for left and right pages</p><p><span style=" font-weight:600; text-decoration: underline;">Checked - 1 page landscape<br/></span>A single centered viewport for 1 page</p></body></html>
+
+
+ 1 Page Landscape
+
+
+
diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py
index bc24c60..82d3bf3 100644
--- a/kindlecomicconverter/KCC_gui.py
+++ b/kindlecomicconverter/KCC_gui.py
@@ -38,7 +38,6 @@ from xml.sax.saxutils import escape
from psutil import Process
from copy import copy
from packaging.version import Version
-from raven import Client
from tempfile import gettempdir
from .shared import HTMLStripper, sanitizeTrace, walkLevel, subprocess_run
@@ -327,8 +326,8 @@ class WorkerThread(QThread):
options.maximizestrips = True
if GUI.disableProcessingBox.isChecked():
options.noprocessing = True
- if GUI.pdfExtractBox.isChecked():
- options.pdfextract = True
+ if GUI.legacyExtractBox.isChecked():
+ options.legacyextract = True
if GUI.pdfWidthBox.isChecked():
options.pdfwidth = True
if GUI.smartCoverCropBox.isChecked():
@@ -345,6 +344,8 @@ class WorkerThread(QThread):
options.tempdir = True
if GUI.spreadShiftBox.isChecked():
options.spreadshift = True
+ if GUI.onePageLandscapeBox.isChecked():
+ options.onepagelandscape = True
if GUI.fileFusionBox.isChecked():
options.filefusion = True
else:
@@ -445,8 +446,6 @@ class WorkerThread(QThread):
_, _, traceback = sys.exc_info()
MW.showDialog.emit("Error during conversion %s:\n\n%s\n\nTraceback:\n%s"
% (jobargv[-1], str(err), sanitizeTrace(traceback)), 'error')
- if ' is corrupted.' not in str(err):
- GUI.sentry.captureException()
MW.addMessage.emit('Error during conversion! Please consult '
'wiki '
'for more details.', 'error', False)
@@ -564,6 +563,7 @@ class WorkerThread(QThread):
os.remove(path)
elif os.path.isdir(path):
rmtree(path, True)
+ comic2ebook.checkPre('LLL-')
GUI.progress.content = ''
GUI.progress.stop()
MW.hideProgressBar.emit()
@@ -627,7 +627,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
GUI.jobList.clear()
if self.tar or self.sevenzip:
fnames = QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
- 'Comic (*.cbz *.cbr *.cb7 *.zip *.rar *.7z *.pdf);;All (*.*)')
+ 'Comic (*.cbz *.cbr *.cb7 *.zip *.rar *.7z *.epub *.pdf);;All (*.*)')
else:
fnames = QFileDialog.getOpenFileNames(MW, 'Select file', self.lastPath,
'Comic (*.pdf);;All (*.*)')
@@ -699,7 +699,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.editor.loadData(files)
except Exception as err:
_, _, traceback = sys.exc_info()
- GUI.sentry.captureException()
self.showDialog("Failed to parse metadata!\n\n%s\n\nTraceback:\n%s"
% (str(err), sanitizeTrace(traceback)), 'error')
else:
@@ -1101,7 +1100,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
'colorBox': GUI.colorBox.checkState(),
'eraseRainbowBox': GUI.eraseRainbowBox.checkState(),
'disableProcessingBox': GUI.disableProcessingBox.checkState(),
- 'pdfExtractBox': GUI.pdfExtractBox.checkState(),
+ 'legacyExtractBox': GUI.legacyExtractBox.checkState(),
'pdfWidthBox': GUI.pdfWidthBox.checkState(),
'smartCoverCropBox': GUI.smartCoverCropBox.checkState(),
'coverFillBox': GUI.coverFillBox.checkState(),
@@ -1118,6 +1117,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
'deleteBox': GUI.deleteBox.checkState(),
'tempDirBox': GUI.tempDirBox.checkState(),
'spreadShiftBox': GUI.spreadShiftBox.checkState(),
+ 'onePageLandscapeBox': GUI.onePageLandscapeBox.checkState(),
'fileFusionBox': GUI.fileFusionBox.checkState(),
'defaultOutputFolderBox': GUI.defaultOutputFolderBox.checkState(),
'noRotateBox': GUI.noRotateBox.checkState(),
@@ -1141,7 +1141,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
GUI.jobList.clear()
formats = ['.pdf']
if self.tar or self.sevenzip:
- formats.extend(['.cb7', '.7z', '.cbz', '.zip', '.cbr', '.rar'])
+ formats.extend(['.cb7', '.7z', '.cbz', '.zip', '.cbr', '.rar', '.epub'])
if os.path.isdir(message):
GUI.jobList.addItem(message)
GUI.jobList.scrollToBottom()
@@ -1228,7 +1228,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
self.croppingPowerValue = 1.0
self.currentMode = 1
self.targetDirectory = ''
- self.sentry = Client(release=__version__)
if sys.platform.startswith('win'):
# noinspection PyUnresolvedReferences
from psutil import BELOW_NORMAL_PRIORITY_CLASS
@@ -1775,7 +1774,6 @@ class KCCGUI_MetaEditor(KCC_ui_editor.Ui_editorDialog):
self.parser.saveXML()
except Exception as err:
_, _, traceback = sys.exc_info()
- GUI.sentry.captureException()
GUI.showDialog("Failed to save metadata!\n\n%s\n\nTraceback:\n%s"
% (str(err), sanitizeTrace(traceback)), 'error')
self.ui.close()
diff --git a/kindlecomicconverter/KCC_ui.py b/kindlecomicconverter/KCC_ui.py
index 62e9d29..525fdb2 100644
--- a/kindlecomicconverter/KCC_ui.py
+++ b/kindlecomicconverter/KCC_ui.py
@@ -389,10 +389,10 @@ class Ui_mainWindow(object):
self.gridLayout_2.addWidget(self.qualityBox, 1, 2, 1, 1)
- self.pdfExtractBox = QCheckBox(self.optionWidget)
- self.pdfExtractBox.setObjectName(u"pdfExtractBox")
+ self.legacyExtractBox = QCheckBox(self.optionWidget)
+ self.legacyExtractBox.setObjectName(u"legacyExtractBox")
- self.gridLayout_2.addWidget(self.pdfExtractBox, 9, 0, 1, 1)
+ self.gridLayout_2.addWidget(self.legacyExtractBox, 9, 0, 1, 1)
self.colorBox = QCheckBox(self.optionWidget)
self.colorBox.setObjectName(u"colorBox")
@@ -453,7 +453,12 @@ class Ui_mainWindow(object):
self.tempDirBox = QCheckBox(self.optionWidget)
self.tempDirBox.setObjectName(u"tempDirBox")
- self.gridLayout_2.addWidget(self.tempDirBox, 12, 1, 1, 1)
+ self.gridLayout_2.addWidget(self.tempDirBox, 12, 2, 1, 1)
+
+ self.onePageLandscapeBox = QCheckBox(self.optionWidget)
+ self.onePageLandscapeBox.setObjectName(u"onePageLandscapeBox")
+
+ self.gridLayout_2.addWidget(self.onePageLandscapeBox, 12, 1, 1, 1)
self.gridLayout.addWidget(self.optionWidget, 5, 0, 1, 2)
@@ -785,11 +790,9 @@ class Ui_mainWindow(object):
#endif // QT_CONFIG(tooltip)
self.qualityBox.setText(QCoreApplication.translate("mainWindow", u"Panel View 4/2/HQ", None))
#if QT_CONFIG(tooltip)
- self.pdfExtractBox.setToolTip(QCoreApplication.translate("mainWindow", u"Use the PDF image extraction method from KCC 8 and earlier.\n"
-"\n"
-"Useful for really weird PDFs.", None))
+ self.legacyExtractBox.setToolTip(QCoreApplication.translate("mainWindow", u"
Use the PDF/EPUB image extraction method from older KCC versions.
Use if standard extraction fails for whatever reason.
", None))
#endif // QT_CONFIG(tooltip)
- self.pdfExtractBox.setText(QCoreApplication.translate("mainWindow", u"PDF Legacy Extract", None))
+ self.legacyExtractBox.setText(QCoreApplication.translate("mainWindow", u"Legacy Extract", None))
#if QT_CONFIG(tooltip)
self.colorBox.setToolTip(QCoreApplication.translate("mainWindow", u"Disable conversion to grayscale.
", None))
#endif // QT_CONFIG(tooltip)
@@ -830,6 +833,10 @@ class Ui_mainWindow(object):
self.tempDirBox.setToolTip(QCoreApplication.translate("mainWindow", u"Unchecked - Main Drive
Use dedicated temporary directory on main OS drive.
Checked - Source File Drive
Create temporary file directory on source file drive.
", None))
#endif // QT_CONFIG(tooltip)
self.tempDirBox.setText(QCoreApplication.translate("mainWindow", u"Temp Directory", None))
+#if QT_CONFIG(tooltip)
+ self.onePageLandscapeBox.setToolTip(QCoreApplication.translate("mainWindow", u"Unchecked - 2 page landscape
2 viewports for left and right pages
Checked - 1 page landscape
A single centered viewport for 1 page
", None))
+#endif // QT_CONFIG(tooltip)
+ self.onePageLandscapeBox.setText(QCoreApplication.translate("mainWindow", u"1 Page Landscape", None))
#if QT_CONFIG(tooltip)
self.convertButton.setToolTip(QCoreApplication.translate("mainWindow", u"Shift+Click to select the output directory for this list.
", None))
#endif // QT_CONFIG(tooltip)
diff --git a/kindlecomicconverter/comic2ebook.py b/kindlecomicconverter/comic2ebook.py
index 8cd316c..28744d0 100755
--- a/kindlecomicconverter/comic2ebook.py
+++ b/kindlecomicconverter/comic2ebook.py
@@ -22,7 +22,9 @@ from collections import Counter
import os
import pathlib
import re
+import shutil
import sys
+import xml.etree.ElementTree as ET
from argparse import ArgumentParser
from time import perf_counter, strftime, gmtime
from copy import copy
@@ -30,8 +32,8 @@ from glob import glob, escape
from re import sub
from stat import S_IWRITE, S_IREAD, S_IEXEC
from typing import List
-from zipfile import ZipFile, ZIP_STORED, ZIP_DEFLATED
-from tempfile import mkdtemp, gettempdir, TemporaryFile
+from zipfile import ZipFile, ZIP_STORED
+from tempfile import mkdtemp, gettempdir
from shutil import move, copytree, rmtree, copyfile
from multiprocessing import Pool, cpu_count
from uuid import uuid4
@@ -90,6 +92,7 @@ def main(argv=None):
os.remove(path)
elif os.path.isdir(path):
rmtree(path, True)
+ checkPre('LLL-')
return 0
@@ -466,6 +469,8 @@ def buildOPF(dstdir, title, filelist, originalpath, cover=None):
pageside = "right"
for entry, prop in zip(reflist, page_spread_property_list):
+ if options.onepagelandscape:
+ prop = 'center'
f.write(f'\n')
f.write("\n\n")
@@ -892,9 +897,12 @@ def getWorkFolder(afile, workdir=None):
fullPath = os.path.join(workdir, 'OEBPS', 'Images')
else:
fullPath = workdir
- check_path = gettempdir()
+
if options.tempdir:
check_path = os.path.dirname(afile)
+ else:
+ check_path = gettempdir()
+
if os.path.isdir(afile):
if disk_usage(check_path)[2] < getDirectorySize(afile) * 2.5:
raise UserWarning("Not enough disk space to perform conversion.")
@@ -913,7 +921,7 @@ def getWorkFolder(afile, workdir=None):
os.makedirs(fullPath)
path = workdir
sanitizePermissions(path)
- if options.pdfextract:
+ if options.legacyextract:
pdf = pdfjpgextract.PdfJpgExtract(afile, fullPath)
njpg = pdf.extract()
if njpg == 0:
@@ -952,11 +960,68 @@ def getWorkFolder(afile, workdir=None):
for file in os.listdir(os.path.join(fullPath, tdir[0])):
move(os.path.join(fullPath, tdir[0], file), fullPath)
os.rmdir(os.path.join(fullPath, tdir[0]))
+
+ if options.legacyextract:
+ return workdir
+
+ if afile.lower().endswith('.epub'):
+ container = ET.parse(os.path.join(path, 'META-INF', 'container.xml'))
+ opf_path = container.find(r'.//{*}rootfile').attrib['full-path']
+ opf_path = os.path.join(path, opf_path)
+ opf = ET.parse(opf_path)
+ spine = []
+ for spine_item in opf.findall(r'.//{*}itemref'):
+ spine.append(spine_item.attrib.get('idref'))
+ manifest_dict = {}
+ for manifest_item in opf.findall(".//*[@media-type='application/xhtml+xml']"):
+ manifest_dict[manifest_item.attrib.get('id')] = manifest_item.attrib.get('href')
+ ordered_image_paths = []
+ for i, spine_item in enumerate(spine):
+ if spine_item not in manifest_dict:
+ continue
+ page_path = os.path.join(os.path.dirname(opf_path), manifest_dict[spine_item])
+ page = ET.parse(page_path)
+ imgs = page.findall(r'.//{*}img') + page.findall(r'.//{*}image')
+
+ largest_size = 0
+ img_path = None
+ for img in imgs:
+ for key in img.attrib:
+ if 'src' in key or 'href' in key:
+ temp_img_path = img.attrib[key]
+ if temp_img_path.startswith('..'):
+ temp_img_path = os.path.join(os.path.dirname(opf_path), os.path.dirname(manifest_dict[spine_item]), temp_img_path)
+ else:
+ temp_img_path = os.path.join(os.path.dirname(opf_path), os.path.dirname(manifest_dict[spine_item]), temp_img_path)
+ try:
+ temp_size = os.path.getsize(temp_img_path)
+ if temp_size > largest_size:
+ largest_size = temp_size
+ img_path = temp_img_path
+ except OSError:
+ pass
+ # TODO empty image
+ if img_path:
+ ordered_image_paths.append(img_path)
+ # fallback if naive spine extraction fails
+ if not ordered_image_paths:
+ return workdir
+
+ if options.tempdir:
+ workdir2 = mkdtemp('', 'KCC-', os.path.dirname(afile))
+ else:
+ workdir2 = mkdtemp('', 'KCC-')
+ for i, img_path in enumerate(ordered_image_paths):
+ _, ext = os.path.splitext(img_path)
+ fullpath2 = os.path.join(workdir2, 'OEBPS', 'Images')
+ os.makedirs(fullpath2, exist_ok=True)
+ shutil.copyfile(img_path, os.path.join(fullpath2, f"{i}{ext}"))
+ rmtree(workdir, True)
+ return workdir2
+
return workdir
-
- except OSError as e:
- rmtree(workdir, True)
- raise UserWarning(e)
+ finally:
+ pass
else:
raise UserWarning("Failed to open source file/directory.")
@@ -1393,6 +1458,8 @@ def makeParser():
"2: Consider every subdirectory as separate volume [Default=0]")
output_options.add_argument("--spreadshift", action="store_true", dest="spreadshift", default=False,
help="Shift first page to opposite side in landscape for spread alignment")
+ output_options.add_argument("--onepagelandscape", action="store_true", dest="onepagelandscape", default=False,
+ help="Show a single centered page in landscape")
output_options.add_argument("--norotate", action="store_true", dest="norotate", default=False,
help="Do not rotate double page spreads in spread splitter option.")
output_options.add_argument("--rotateright", action="store_true", dest="rotateright", default=False,
@@ -1402,8 +1469,8 @@ def makeParser():
processing_options.add_argument("-n", "--noprocessing", action="store_true", dest="noprocessing", default=False,
help="Do not modify image and ignore any profile or processing option")
- processing_options.add_argument("--pdfextract", action="store_true", dest="pdfextract", default=False,
- help="Use the legacy PDF image extraction method from KCC 8 and earlier")
+ processing_options.add_argument("--legacyextract", action="store_true", dest="legacyextract", default=False,
+ help="Use the legacy PDF/EPUB image extraction method from older KCC versions")
processing_options.add_argument("--pdfwidth", action="store_true", dest="pdfwidth", default=False,
help="Render vector PDFs to device width instead of height.")
processing_options.add_argument("--smartcovercrop", action="store_true", dest="smartcovercrop", default=False,
@@ -1609,33 +1676,30 @@ def checkTools(source):
sys.exit(1)
-def checkPre(source):
+def checkPre(source='KCC-'):
# Make sure that all temporary files are gone
for root, dirs, _ in walkLevel(gettempdir(), 0):
for tempdir in dirs:
- if tempdir.startswith('KCC-'):
+ if tempdir.startswith(source):
rmtree(os.path.join(root, tempdir), True)
- # Make sure that target directory is writable
- if os.path.isdir(source):
- src = os.path.abspath(os.path.join(source, '..'))
- else:
- src = os.path.dirname(source)
- try:
- with TemporaryFile(prefix='KCC-', dir=src):
- pass
- except Exception:
- raise UserWarning("Target directory is not writable.")
-
def makeFusion(sources: List[str]):
if len(sources) < 2:
raise UserWarning('Fusion requires at least 2 sources. Did you forget to uncheck fusion?')
start = perf_counter()
first_path = Path(sources[0])
- if first_path.is_file():
- fusion_path = first_path.parent.joinpath(first_path.stem + ' [fused]')
+
+ if options.tempdir:
+ fusion_parent = first_path.parent
else:
- fusion_path = first_path.parent.joinpath(first_path.name + ' [fused]')
+ # LLL is after KCC
+ checkPre('LLL-')
+ fusion_parent = Path(mkdtemp('', 'LLL-'))
+
+ if first_path.is_file():
+ fusion_path = fusion_parent.joinpath(first_path.stem + ' [fused]')
+ else:
+ fusion_path = fusion_parent.joinpath(first_path.name + ' [fused]')
print("Running Fusion")
# Check if prefix is needed when user-specified ordering differs from OS natural sorting
@@ -1644,7 +1708,6 @@ def makeFusion(sources: List[str]):
for index, source in enumerate(sources, start=1):
print(f"Processing {source}...")
- checkPre(source)
print("Checking images...")
source_path = Path(source)
# Add the fusion_0001_ prefix to maintain user-specified order if needed
@@ -1676,7 +1739,9 @@ def makeBook(source, qtgui=None, job_progress=''):
GUI.progressBarTick.emit('1')
else:
checkTools(source)
- checkPre(source)
+ checkPre()
+ if not options.filefusion:
+ checkPre('LLL-')
print(f"{job_progress}Preparing source images...")
path = getWorkFolder(source)
print(f"{job_progress}Checking images...")
diff --git a/kindlecomicconverter/shared.py b/kindlecomicconverter/shared.py
index 857b6cc..1214317 100644
--- a/kindlecomicconverter/shared.py
+++ b/kindlecomicconverter/shared.py
@@ -122,10 +122,6 @@ def dependencyCheck(level):
missing.append('PySide 6.0.0')
except ImportError:
missing.append('PySide 6.0.0+')
- try:
- import raven
- except ImportError:
- missing.append('raven 6.0.0+')
if level > 1:
try:
from psutil import __version__ as psutilVersion
diff --git a/requirements-docker.txt b/requirements-docker.txt
index 077a006..193bb24 100644
--- a/requirements-docker.txt
+++ b/requirements-docker.txt
@@ -1,8 +1,8 @@
Pillow>=11.3.0
psutil>=5.9.5
-requests>=2.31.0
-python-slugify>=1.2.1
-packaging>=23.2
+requests>=2.34.2
+python-slugify>=8.0.4
+packaging>=26.2
mozjpeg-lossless-optimization>=1.2.0
natsort>=8.4.0
distro>=1.8.0
diff --git a/requirements-osx-legacy.txt b/requirements-osx-legacy.txt
index 6e4d643..90eb637 100644
--- a/requirements-osx-legacy.txt
+++ b/requirements-osx-legacy.txt
@@ -1,10 +1,9 @@
PySide6==6.4.3
Pillow>=11.3.0
psutil>=5.9.5
-requests>=2.31.0
-python-slugify>=1.2.1
-raven>=6.0.0
-packaging>=23.2
+requests>=2.34.2
+python-slugify>=8.0.4
+packaging>=26.2
mozjpeg-lossless-optimization>=1.2.0
natsort>=8.4.0
distro>=1.8.0
diff --git a/requirements-win7.txt b/requirements-win7.txt
index 47717d4..637f428 100644
--- a/requirements-win7.txt
+++ b/requirements-win7.txt
@@ -1,10 +1,9 @@
PySide6==6.1.3
Pillow>=9
psutil>=5.9.5
-requests>=2.31.0
-python-slugify>=1.2.1
-raven>=6.0.0
-packaging>=23.2
+requests>=2.34.2
+python-slugify>=8.0.4
+packaging>=26.2
mozjpeg-lossless-optimization>=1.2.0
natsort>=8.4.0
distro>=1.8.0
diff --git a/requirements.txt b/requirements.txt
index 8edccd8..ca8358b 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,10 +1,9 @@
PySide6<6.10
Pillow>=11.3.0
psutil>=5.9.5
-requests>=2.31.0
-python-slugify>=1.2.1,<9.0.0
-raven>=6.0.0
-packaging>=23.2
+requests>=2.34.2
+python-slugify>=8.0.4,<9.0.0
+packaging>=26.2
mozjpeg-lossless-optimization>=1.2.0
natsort>=8.4.0
distro>=1.8.0
diff --git a/setup.py b/setup.py
index f791414..daf2276 100644
--- a/setup.py
+++ b/setup.py
@@ -153,11 +153,11 @@ setuptools.setup(
'psutil>=5.9.5',
'requests>=2.31.0',
'python-slugify>=1.2.1,<9.0.0',
- 'raven>=6.0.0',
'mozjpeg-lossless-optimization>=1.2.0',
'natsort>=8.4.0',
'distro>=1.8.0',
'numpy>=1.22.4',
+ 'packaging>=23.2',
'PyMuPDF>=1.16.1',
],
classifiers=[],