mirror of
https://github.com/ciromattia/kcc
synced 2026-08-02 10:01:29 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7206c0cd48 |
@@ -71,7 +71,7 @@ jobs:
|
|||||||
# apply provisioning profile
|
# apply provisioning profile
|
||||||
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
|
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
|
||||||
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
|
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@v7
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 16
|
||||||
- run: npm install -g appdmg
|
- run: npm install -g appdmg
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ jobs:
|
|||||||
pip3 install --upgrade pip pyinstaller certifi
|
pip3 install --upgrade pip pyinstaller certifi
|
||||||
pip3 install --upgrade -r requirements-osx-legacy.txt
|
pip3 install --upgrade -r requirements-osx-legacy.txt
|
||||||
./gen_ui_files.sh
|
./gen_ui_files.sh
|
||||||
- uses: actions/setup-node@v6
|
- uses: actions/setup-node@v7
|
||||||
with:
|
with:
|
||||||
node-version: 16
|
node-version: 16
|
||||||
- run: npm install -g appdmg
|
- run: npm install -g appdmg
|
||||||
|
|||||||
@@ -42,7 +42,6 @@ KCC avoids many common formatting issues (some of which occur [even on the Kindl
|
|||||||
4) incorrect page turn direction for manga that's read right to left
|
4) incorrect page turn direction for manga that's read right to left
|
||||||
5) unaligned two page spreads in landscape, where pages are shifted over by 1
|
5) unaligned two page spreads in landscape, where pages are shifted over by 1
|
||||||
6) Removing without blur the rainbow effect on color eink Kaleido 3 due to manga screentones
|
6) Removing without blur the rainbow effect on color eink Kaleido 3 due to manga screentones
|
||||||
7) Fixing page order problems due to Windows sort being different than Kindle/Kobo sort
|
|
||||||
|
|
||||||
The GUI looks like this, built in Qt6, with my most commonly used settings:
|
The GUI looks like this, built in Qt6, with my most commonly used settings:
|
||||||
|
|
||||||
|
|||||||
+63
-76
@@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>649</width>
|
<width>644</width>
|
||||||
<height>706</height>
|
<height>706</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@@ -711,27 +711,7 @@ Keeping this file may crash some readers like the Kobo native CBZ reader.</strin
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="0" column="0">
|
<item row="0" column="2">
|
||||||
<widget class="QPushButton" name="editorButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p style='white-space:pre'>Shift+Click to edit directory.</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Metadata Editor</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="KCC.qrc">
|
|
||||||
<normaloff>:/Other/icons/editor.png</normaloff>:/Other/icons/editor.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
|
||||||
<widget class="QPushButton" name="humbleButton">
|
<widget class="QPushButton" name="humbleButton">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
@@ -748,7 +728,7 @@ Keeping this file may crash some readers like the Kobo native CBZ reader.</strin
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2">
|
<item row="0" column="1">
|
||||||
<widget class="QPushButton" name="kofiButton">
|
<widget class="QPushButton" name="kofiButton">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
@@ -771,16 +751,23 @@ Keeping this file may crash some readers like the Kobo native CBZ reader.</strin
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="0">
|
||||||
<widget class="QPushButton" name="labelSpreadsButton">
|
<widget class="QPushButton" name="editorButton">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>0</width>
|
<width>0</width>
|
||||||
<height>30</height>
|
<height>30</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p style='white-space:pre'>Shift+Click to edit directory.</p></body></html></string>
|
||||||
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Label Spreads</string>
|
<string>Metadata Editor</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/editor.png</normaloff>:/Other/icons/editor.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -1087,56 +1074,6 @@ Keeping this file may crash some readers like the Kobo native CBZ reader.</strin
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item row="1" column="1">
|
|
||||||
<widget class="QComboBox" name="deviceBox">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>28</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p style='white-space:pre'>Target device.</p></body></html></string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="3">
|
|
||||||
<widget class="QPushButton" name="clearButton">
|
|
||||||
<property name="minimumSize">
|
|
||||||
<size>
|
|
||||||
<width>0</width>
|
|
||||||
<height>30</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Clear list</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="KCC.qrc">
|
|
||||||
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="0" column="4">
|
|
||||||
<widget class="QPushButton" name="directoryButton">
|
|
||||||
<property name="sizePolicy">
|
|
||||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
|
||||||
<horstretch>0</horstretch>
|
|
||||||
<verstretch>0</verstretch>
|
|
||||||
</sizepolicy>
|
|
||||||
</property>
|
|
||||||
<property name="toolTip">
|
|
||||||
<string><html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=" font-weight:600;">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html></string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>Add input folder(s)</string>
|
|
||||||
</property>
|
|
||||||
<property name="icon">
|
|
||||||
<iconset resource="KCC.qrc">
|
|
||||||
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item row="1" column="3">
|
<item row="1" column="3">
|
||||||
<widget class="QPushButton" name="convertButton">
|
<widget class="QPushButton" name="convertButton">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@@ -1162,6 +1099,36 @@ Keeping this file may crash some readers like the Kobo native CBZ reader.</strin
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="3">
|
||||||
|
<widget class="QPushButton" name="clearButton">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>30</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear list</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/clear.png</normaloff>:/Other/icons/clear.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QComboBox" name="deviceBox">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>28</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p style='white-space:pre'>Target device.</p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="0" column="1">
|
<item row="0" column="1">
|
||||||
<widget class="QPushButton" name="fileButton">
|
<widget class="QPushButton" name="fileButton">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@@ -1182,6 +1149,26 @@ Keeping this file may crash some readers like the Kobo native CBZ reader.</strin
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="0" column="4">
|
||||||
|
<widget class="QPushButton" name="directoryButton">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string><html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=" font-weight:600;">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Add input folder(s)</string>
|
||||||
|
</property>
|
||||||
|
<property name="icon">
|
||||||
|
<iconset resource="KCC.qrc">
|
||||||
|
<normaloff>:/Other/icons/folder_new.png</normaloff>:/Other/icons/folder_new.png</iconset>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item row="1" column="4">
|
<item row="1" column="4">
|
||||||
<widget class="QComboBox" name="formatBox">
|
<widget class="QComboBox" name="formatBox">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
|
|||||||
+131
-214
@@ -19,11 +19,10 @@
|
|||||||
|
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
import itertools
|
import itertools
|
||||||
import json
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PySide6.QtCore import (QSize, QUrl, Qt, Signal, QIODeviceBase, QEvent, QThread, QSettings)
|
from PySide6.QtCore import (QSize, QUrl, Qt, Signal, QIODeviceBase, QEvent, QThread, QSettings)
|
||||||
from PySide6.QtGui import (QColor, QIcon, QImage, QKeyEvent, QPixmap, QDesktopServices)
|
from PySide6.QtGui import (QColor, QIcon, QPixmap, QDesktopServices)
|
||||||
from PySide6.QtWidgets import (QApplication, QDialogButtonBox, QHBoxLayout, QLabel, QListWidgetItem, QMainWindow, QSizePolicy, QSystemTrayIcon, QFileDialog, QMessageBox, QDialog, QAbstractItemView, QListView, QTreeView, QWidget)
|
from PySide6.QtWidgets import (QApplication, QLabel, QListWidgetItem, QMainWindow, QSystemTrayIcon, QFileDialog, QMessageBox, QDialog, QAbstractItemView, QListView, QTreeView)
|
||||||
from PySide6.QtNetwork import (QLocalSocket, QLocalServer)
|
from PySide6.QtNetwork import (QLocalSocket, QLocalServer)
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -39,15 +38,10 @@ from xml.sax.saxutils import escape
|
|||||||
from psutil import Process
|
from psutil import Process
|
||||||
from copy import copy
|
from copy import copy
|
||||||
from packaging.version import Version
|
from packaging.version import Version
|
||||||
from tempfile import gettempdir, mkdtemp
|
from tempfile import gettempdir
|
||||||
from PIL import Image
|
|
||||||
from PIL.Image import Dither
|
|
||||||
|
|
||||||
from .KCC_spread_label import LabelSpreadsDialog
|
|
||||||
|
|
||||||
from .shared import HTMLStripper, sanitizeTrace, walkLevel, subprocess_run
|
from .shared import HTMLStripper, sanitizeTrace, walkLevel, subprocess_run
|
||||||
from .comicarchive import SEVENZIP, TAR, available_archive_tools
|
from .comicarchive import SEVENZIP, TAR, available_archive_tools
|
||||||
from .comic2ebook import OS_SORT_KEY, flattenTree, getWorkFolder, removeNonImages, sanitizeTree
|
|
||||||
from . import __version__
|
from . import __version__
|
||||||
from . import comic2ebook
|
from . import comic2ebook
|
||||||
from . import metadata
|
from . import metadata
|
||||||
@@ -240,138 +234,6 @@ class ProgressThread(QThread):
|
|||||||
self.running = False
|
self.running = False
|
||||||
|
|
||||||
|
|
||||||
def get_options():
|
|
||||||
parser = comic2ebook.makeParser()
|
|
||||||
options = parser.parse_args()
|
|
||||||
|
|
||||||
options.profile = GUI.profiles[str(GUI.deviceBox.currentText())]['Label']
|
|
||||||
gui_current_format = GUI.formats[str(GUI.formatBox.currentText())]['format']
|
|
||||||
options.format = gui_current_format
|
|
||||||
if GUI.mangaBox.isChecked():
|
|
||||||
options.righttoleft = True
|
|
||||||
if GUI.lightnovelBox.isChecked():
|
|
||||||
options.lightnovel = True
|
|
||||||
if GUI.ebokBox.isChecked():
|
|
||||||
options.ebok = True
|
|
||||||
if GUI.invertDirectionBox.isChecked():
|
|
||||||
options.invertdirection = True
|
|
||||||
if GUI.rotateBox.checkState() == Qt.CheckState.PartiallyChecked:
|
|
||||||
options.splitter = 2
|
|
||||||
elif GUI.rotateBox.checkState() == Qt.CheckState.Checked:
|
|
||||||
options.splitter = 1
|
|
||||||
if GUI.qualityBox.checkState() == Qt.CheckState.PartiallyChecked:
|
|
||||||
options.autoscale = True
|
|
||||||
elif GUI.qualityBox.checkState() == Qt.CheckState.Checked:
|
|
||||||
options.hq = True
|
|
||||||
if GUI.vertical4PanelBox.isChecked():
|
|
||||||
options.vertical4panel = True
|
|
||||||
if GUI.webtoonBox.isChecked():
|
|
||||||
options.webtoon = True
|
|
||||||
if GUI.upscaleBox.checkState() == Qt.CheckState.PartiallyChecked:
|
|
||||||
options.stretch = True
|
|
||||||
elif GUI.upscaleBox.checkState() == Qt.CheckState.Checked:
|
|
||||||
options.upscale = True
|
|
||||||
if GUI.gammaBox.isChecked() and float(GUI.gammaValue) > 0.09:
|
|
||||||
options.gamma = float(GUI.gammaValue)
|
|
||||||
if GUI.autoLevelBox.isChecked():
|
|
||||||
options.autolevel = True
|
|
||||||
if GUI.autocontrastBox.checkState() == Qt.CheckState.PartiallyChecked:
|
|
||||||
options.noautocontrast = True
|
|
||||||
elif GUI.autocontrastBox.checkState() == Qt.CheckState.Checked:
|
|
||||||
options.colorautocontrast = True
|
|
||||||
if GUI.croppingBox.isChecked():
|
|
||||||
if GUI.croppingBox.checkState() == Qt.CheckState.PartiallyChecked:
|
|
||||||
options.cropping = 1
|
|
||||||
else:
|
|
||||||
options.cropping = 2
|
|
||||||
else:
|
|
||||||
options.cropping = 0
|
|
||||||
if GUI.croppingBox.checkState() != Qt.CheckState.Unchecked:
|
|
||||||
options.croppingp = float(GUI.croppingPowerValue)
|
|
||||||
options.preservemargin = GUI.preserveMarginBox.value()
|
|
||||||
if GUI.interPanelCropBox.isChecked():
|
|
||||||
if GUI.interPanelCropBox.checkState() == Qt.CheckState.PartiallyChecked:
|
|
||||||
options.interpanelcrop = 1
|
|
||||||
else:
|
|
||||||
options.interpanelcrop = 2
|
|
||||||
else:
|
|
||||||
options.interpanelcrop = 0
|
|
||||||
if GUI.borderBox.checkState() == Qt.CheckState.PartiallyChecked:
|
|
||||||
options.white_borders = True
|
|
||||||
elif GUI.borderBox.checkState() == Qt.CheckState.Checked:
|
|
||||||
options.black_borders = True
|
|
||||||
if GUI.outputSplit.isChecked():
|
|
||||||
options.batchsplit = 2
|
|
||||||
if GUI.colorBox.isChecked():
|
|
||||||
options.forcecolor = True
|
|
||||||
if GUI.eraseRainbowBox.isChecked():
|
|
||||||
options.eraserainbow = True
|
|
||||||
if GUI.maximizeStrips.isChecked():
|
|
||||||
options.maximizestrips = True
|
|
||||||
if GUI.disableProcessingBox.isChecked():
|
|
||||||
options.noprocessing = True
|
|
||||||
if GUI.legacyExtractBox.isChecked():
|
|
||||||
options.legacyextract = True
|
|
||||||
if GUI.pdfWidthBox.isChecked():
|
|
||||||
options.pdfwidth = True
|
|
||||||
if GUI.smartCoverCropBox.isChecked():
|
|
||||||
options.smartcovercrop = True
|
|
||||||
if GUI.coverFillBox.isChecked():
|
|
||||||
options.coverfill = True
|
|
||||||
if GUI.metadataTitleBox.checkState() == Qt.CheckState.PartiallyChecked:
|
|
||||||
options.metadatatitle = 1
|
|
||||||
elif GUI.metadataTitleBox.checkState() == Qt.CheckState.Checked:
|
|
||||||
options.metadatatitle = 2
|
|
||||||
if GUI.keepComicInfoBox.isChecked():
|
|
||||||
options.keepcomicinfo = True
|
|
||||||
if GUI.deleteBox.isChecked():
|
|
||||||
options.delete = True
|
|
||||||
if GUI.tempDirBox.isChecked():
|
|
||||||
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:
|
|
||||||
options.filefusion = False
|
|
||||||
if GUI.noRotateBox.isChecked():
|
|
||||||
options.norotate = True
|
|
||||||
if GUI.rotateRightBox.isChecked():
|
|
||||||
options.rotateright = True
|
|
||||||
if GUI.rotateFirstBox.isChecked():
|
|
||||||
options.rotatefirst = True
|
|
||||||
if GUI.forcePngRgbBox.isChecked():
|
|
||||||
options.force_png_rgb = True
|
|
||||||
if GUI.mozJpegBox.checkState() == Qt.CheckState.PartiallyChecked:
|
|
||||||
options.forcepng = True
|
|
||||||
elif GUI.mozJpegBox.checkState() == Qt.CheckState.Checked:
|
|
||||||
options.mozjpeg = True
|
|
||||||
if GUI.webpBox.isChecked():
|
|
||||||
options.webp = True
|
|
||||||
if GUI.pngLegacyBox.isChecked():
|
|
||||||
options.pnglegacy = True
|
|
||||||
if GUI.noQuantizeBox.isChecked():
|
|
||||||
options.noquantize = True
|
|
||||||
if GUI.jpegQualityBox.isChecked():
|
|
||||||
options.jpegquality = GUI.jpegQualitySpinBox.value()
|
|
||||||
if GUI.currentMode > 2:
|
|
||||||
options.customwidth = str(GUI.widthBox.value())
|
|
||||||
options.customheight = str(GUI.heightBox.value())
|
|
||||||
if GUI.targetDirectory != '':
|
|
||||||
options.output = GUI.targetDirectory
|
|
||||||
if GUI.titleEdit.text():
|
|
||||||
options.title = str(GUI.titleEdit.text())
|
|
||||||
if GUI.authorEdit.text():
|
|
||||||
options.author = str(GUI.authorEdit.text())
|
|
||||||
if GUI.languageEdit.text():
|
|
||||||
options.language = str(GUI.languageEdit.text())
|
|
||||||
if GUI.chunkSizeCheckBox.isChecked():
|
|
||||||
options.targetsize = int(GUI.chunkSizeBox.value())
|
|
||||||
|
|
||||||
return options, gui_current_format
|
|
||||||
|
|
||||||
class WorkerThread(QThread):
|
class WorkerThread(QThread):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
QThread.__init__(self)
|
QThread.__init__(self)
|
||||||
@@ -401,9 +263,136 @@ class WorkerThread(QThread):
|
|||||||
def run(self):
|
def run(self):
|
||||||
MW.modeConvert.emit(0)
|
MW.modeConvert.emit(0)
|
||||||
|
|
||||||
|
parser = comic2ebook.makeParser()
|
||||||
|
options = parser.parse_args()
|
||||||
argv = ''
|
argv = ''
|
||||||
currentJobs = []
|
currentJobs = []
|
||||||
options, gui_current_format = get_options()
|
|
||||||
|
options.profile = GUI.profiles[str(GUI.deviceBox.currentText())]['Label']
|
||||||
|
gui_current_format = GUI.formats[str(GUI.formatBox.currentText())]['format']
|
||||||
|
options.format = gui_current_format
|
||||||
|
if GUI.mangaBox.isChecked():
|
||||||
|
options.righttoleft = True
|
||||||
|
if GUI.lightnovelBox.isChecked():
|
||||||
|
options.lightnovel = True
|
||||||
|
if GUI.ebokBox.isChecked():
|
||||||
|
options.ebok = True
|
||||||
|
if GUI.invertDirectionBox.isChecked():
|
||||||
|
options.invertdirection = True
|
||||||
|
if GUI.rotateBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||||
|
options.splitter = 2
|
||||||
|
elif GUI.rotateBox.checkState() == Qt.CheckState.Checked:
|
||||||
|
options.splitter = 1
|
||||||
|
if GUI.qualityBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||||
|
options.autoscale = True
|
||||||
|
elif GUI.qualityBox.checkState() == Qt.CheckState.Checked:
|
||||||
|
options.hq = True
|
||||||
|
if GUI.vertical4PanelBox.isChecked():
|
||||||
|
options.vertical4panel = True
|
||||||
|
if GUI.webtoonBox.isChecked():
|
||||||
|
options.webtoon = True
|
||||||
|
if GUI.upscaleBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||||
|
options.stretch = True
|
||||||
|
elif GUI.upscaleBox.checkState() == Qt.CheckState.Checked:
|
||||||
|
options.upscale = True
|
||||||
|
if GUI.gammaBox.isChecked() and float(GUI.gammaValue) > 0.09:
|
||||||
|
options.gamma = float(GUI.gammaValue)
|
||||||
|
if GUI.autoLevelBox.isChecked():
|
||||||
|
options.autolevel = True
|
||||||
|
if GUI.autocontrastBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||||
|
options.noautocontrast = True
|
||||||
|
elif GUI.autocontrastBox.checkState() == Qt.CheckState.Checked:
|
||||||
|
options.colorautocontrast = True
|
||||||
|
if GUI.croppingBox.isChecked():
|
||||||
|
if GUI.croppingBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||||
|
options.cropping = 1
|
||||||
|
else:
|
||||||
|
options.cropping = 2
|
||||||
|
else:
|
||||||
|
options.cropping = 0
|
||||||
|
if GUI.croppingBox.checkState() != Qt.CheckState.Unchecked:
|
||||||
|
options.croppingp = float(GUI.croppingPowerValue)
|
||||||
|
options.preservemargin = GUI.preserveMarginBox.value()
|
||||||
|
if GUI.interPanelCropBox.isChecked():
|
||||||
|
if GUI.interPanelCropBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||||
|
options.interpanelcrop = 1
|
||||||
|
else:
|
||||||
|
options.interpanelcrop = 2
|
||||||
|
else:
|
||||||
|
options.interpanelcrop = 0
|
||||||
|
if GUI.borderBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||||
|
options.white_borders = True
|
||||||
|
elif GUI.borderBox.checkState() == Qt.CheckState.Checked:
|
||||||
|
options.black_borders = True
|
||||||
|
if GUI.outputSplit.isChecked():
|
||||||
|
options.batchsplit = 2
|
||||||
|
if GUI.colorBox.isChecked():
|
||||||
|
options.forcecolor = True
|
||||||
|
if GUI.eraseRainbowBox.isChecked():
|
||||||
|
options.eraserainbow = True
|
||||||
|
if GUI.maximizeStrips.isChecked():
|
||||||
|
options.maximizestrips = True
|
||||||
|
if GUI.disableProcessingBox.isChecked():
|
||||||
|
options.noprocessing = True
|
||||||
|
if GUI.legacyExtractBox.isChecked():
|
||||||
|
options.legacyextract = True
|
||||||
|
if GUI.pdfWidthBox.isChecked():
|
||||||
|
options.pdfwidth = True
|
||||||
|
if GUI.smartCoverCropBox.isChecked():
|
||||||
|
options.smartcovercrop = True
|
||||||
|
if GUI.coverFillBox.isChecked():
|
||||||
|
options.coverfill = True
|
||||||
|
if GUI.metadataTitleBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||||
|
options.metadatatitle = 1
|
||||||
|
elif GUI.metadataTitleBox.checkState() == Qt.CheckState.Checked:
|
||||||
|
options.metadatatitle = 2
|
||||||
|
if GUI.keepComicInfoBox.isChecked():
|
||||||
|
options.keepcomicinfo = True
|
||||||
|
if GUI.deleteBox.isChecked():
|
||||||
|
options.delete = True
|
||||||
|
if GUI.tempDirBox.isChecked():
|
||||||
|
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:
|
||||||
|
options.filefusion = False
|
||||||
|
if GUI.noRotateBox.isChecked():
|
||||||
|
options.norotate = True
|
||||||
|
if GUI.rotateRightBox.isChecked():
|
||||||
|
options.rotateright = True
|
||||||
|
if GUI.rotateFirstBox.isChecked():
|
||||||
|
options.rotatefirst = True
|
||||||
|
if GUI.forcePngRgbBox.isChecked():
|
||||||
|
options.force_png_rgb = True
|
||||||
|
if GUI.mozJpegBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||||
|
options.forcepng = True
|
||||||
|
elif GUI.mozJpegBox.checkState() == Qt.CheckState.Checked:
|
||||||
|
options.mozjpeg = True
|
||||||
|
if GUI.webpBox.isChecked():
|
||||||
|
options.webp = True
|
||||||
|
if GUI.pngLegacyBox.isChecked():
|
||||||
|
options.pnglegacy = True
|
||||||
|
if GUI.noQuantizeBox.isChecked():
|
||||||
|
options.noquantize = True
|
||||||
|
if GUI.jpegQualityBox.isChecked():
|
||||||
|
options.jpegquality = GUI.jpegQualitySpinBox.value()
|
||||||
|
if GUI.currentMode > 2:
|
||||||
|
options.customwidth = str(GUI.widthBox.value())
|
||||||
|
options.customheight = str(GUI.heightBox.value())
|
||||||
|
if GUI.targetDirectory != '':
|
||||||
|
options.output = GUI.targetDirectory
|
||||||
|
if GUI.titleEdit.text():
|
||||||
|
options.title = str(GUI.titleEdit.text())
|
||||||
|
if GUI.authorEdit.text():
|
||||||
|
options.author = str(GUI.authorEdit.text())
|
||||||
|
if GUI.languageEdit.text():
|
||||||
|
options.language = str(GUI.languageEdit.text())
|
||||||
|
if GUI.chunkSizeCheckBox.isChecked():
|
||||||
|
options.targetsize = int(GUI.chunkSizeBox.value())
|
||||||
|
|
||||||
for i in range(GUI.jobList.count()):
|
for i in range(GUI.jobList.count()):
|
||||||
# Make sure that we don't consider any system message as job to do
|
# Make sure that we don't consider any system message as job to do
|
||||||
@@ -670,76 +659,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
GUI.jobList.addItem(dname)
|
GUI.jobList.addItem(dname)
|
||||||
GUI.jobList.scrollToBottom()
|
GUI.jobList.scrollToBottom()
|
||||||
|
|
||||||
def labelSpreadsStart(self):
|
|
||||||
currentJobs = []
|
|
||||||
# TODO: make this a function since it's copy pasted
|
|
||||||
for i in range(GUI.jobList.count()):
|
|
||||||
# Make sure that we don't consider any system message as job to do
|
|
||||||
if GUI.jobList.item(i).icon().isNull():
|
|
||||||
currentJobs.append(str(GUI.jobList.item(i).text()))
|
|
||||||
for job in currentJobs:
|
|
||||||
images = []
|
|
||||||
spreads = []
|
|
||||||
options, _ = get_options()
|
|
||||||
options.profileData = [(600, 800), (600,800)]
|
|
||||||
path = getWorkFolder(job, options)
|
|
||||||
removeNonImages(path)
|
|
||||||
sanitizeTree(path, options)
|
|
||||||
flattenTree(path)
|
|
||||||
|
|
||||||
if options.tempdir:
|
|
||||||
workdir = mkdtemp('', 'KCC-', os.path.dirname(job))
|
|
||||||
else:
|
|
||||||
workdir = mkdtemp('', 'KCC-')
|
|
||||||
|
|
||||||
for root, _, files in os.walk(path):
|
|
||||||
files.sort(key=OS_SORT_KEY)
|
|
||||||
start_index = 0
|
|
||||||
if job.endswith('.pdf') or job.endswith('.epub'):
|
|
||||||
start_index = 1
|
|
||||||
if options.spreadshift:
|
|
||||||
start_index = 0 if start_index == 1 else 1
|
|
||||||
for i in range(start_index, len(files), 2):
|
|
||||||
if i == len(files) - 1:
|
|
||||||
continue
|
|
||||||
# TODO: with statements
|
|
||||||
# TODO: ignore 1% of top and bottom too?
|
|
||||||
im1 = Image.open(os.path.join(root, files[i])).convert('1', dither=Dither.NONE)
|
|
||||||
size1 = im1.size
|
|
||||||
crop1 = im1.crop((0, 0, 0.2*size1[0], size1[1]))
|
|
||||||
crop11 = im1.crop((0.01*size1[0], 0, 0.04*size1[0], size1[1]))
|
|
||||||
#crop1 = crop11
|
|
||||||
im2 = Image.open(os.path.join(root, files[i+1])).convert('1', dither=Dither.NONE)
|
|
||||||
size2 = im2.size
|
|
||||||
crop2 = im2.crop((0.8*size2[0], 0, size2[0], size2[1]))
|
|
||||||
crop22 = im2.crop((0.96*size2[0], 0, .99* size2[0], size2[1]))
|
|
||||||
#crop2 = crop22
|
|
||||||
# dst = Image.new('1', (im1.width + im2.width, im1.height))
|
|
||||||
# dst.paste(im2, (0, 0))
|
|
||||||
# dst.paste(im1, (im1.width, 0))
|
|
||||||
hist1 = crop11.histogram()
|
|
||||||
hist2 = crop22.histogram()
|
|
||||||
# TODO: small percentage instead of zero
|
|
||||||
if hist1[0] == 0 or hist1[-1] == 0 or hist2[0] == 0 or hist2[-1] == 0:
|
|
||||||
continue
|
|
||||||
|
|
||||||
dst = Image.new('1', (crop1.width + crop2.width, crop1.height))
|
|
||||||
|
|
||||||
dst.paste(crop2, (0, 0))
|
|
||||||
dst.paste(crop1, (crop1.width, 0))
|
|
||||||
dst.save(os.path.join(workdir, f'label-{i:04}.png'))
|
|
||||||
images.append(os.path.join(workdir, f'label-{i:04}.png'))
|
|
||||||
|
|
||||||
if images:
|
|
||||||
dlg = LabelSpreadsDialog(APP.primaryScreen().availableGeometry().height(), images, spreads)
|
|
||||||
dlg.setWindowTitle(job)
|
|
||||||
if dlg.exec() == 1:
|
|
||||||
with open(job+'.json', "w") as fp:
|
|
||||||
# TODO: not very clean to grab index from filename
|
|
||||||
spreads = [int(filename[6:10]) for filename in spreads]
|
|
||||||
json.dump({'spreads': sorted(set(spreads))} , fp)
|
|
||||||
rmtree(path, True)
|
|
||||||
rmtree(workdir, True)
|
|
||||||
|
|
||||||
def selectFileMetaEditor(self, sname):
|
def selectFileMetaEditor(self, sname):
|
||||||
files = []
|
files = []
|
||||||
@@ -1517,7 +1436,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
'README': "https://github.com/ciromattia/kcc?tab=readme-ov-file#kcc",
|
'README': "https://github.com/ciromattia/kcc?tab=readme-ov-file#kcc",
|
||||||
'FAQ': "https://github.com/ciromattia/kcc/blob/master/README.md#faq",
|
'FAQ': "https://github.com/ciromattia/kcc/blob/master/README.md#faq",
|
||||||
'WIKI': "https://github.com/ciromattia/kcc/wiki",
|
'WIKI': "https://github.com/ciromattia/kcc/wiki",
|
||||||
'YOUTUBE': "https://www.youtube.com/@eink-dude",
|
|
||||||
'TUTORIAL': "https://youtu.be/QQ6zJcMF2Iw?si=80rfm6DU6OUJdFqa",
|
'TUTORIAL': "https://youtu.be/QQ6zJcMF2Iw?si=80rfm6DU6OUJdFqa",
|
||||||
'EMAIL': "https://github.com/ciromattia/kcc?tab=readme-ov-file#commissions",
|
'EMAIL': "https://github.com/ciromattia/kcc?tab=readme-ov-file#commissions",
|
||||||
'DONATE': "https://github.com/ciromattia/kcc/blob/master/README.md#issues--new-features--donations",
|
'DONATE': "https://github.com/ciromattia/kcc/blob/master/README.md#issues--new-features--donations",
|
||||||
@@ -1554,7 +1472,6 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
GUI.kofiButton.clicked.connect(self.openKofi)
|
GUI.kofiButton.clicked.connect(self.openKofi)
|
||||||
GUI.humbleButton.clicked.connect(self.openHumble)
|
GUI.humbleButton.clicked.connect(self.openHumble)
|
||||||
GUI.convertButton.clicked.connect(self.convertStart)
|
GUI.convertButton.clicked.connect(self.convertStart)
|
||||||
GUI.labelSpreadsButton.clicked.connect(self.labelSpreadsStart)
|
|
||||||
GUI.gammaSlider.valueChanged.connect(self.changeGamma)
|
GUI.gammaSlider.valueChanged.connect(self.changeGamma)
|
||||||
GUI.gammaBox.stateChanged.connect(self.togglegammaBox)
|
GUI.gammaBox.stateChanged.connect(self.togglegammaBox)
|
||||||
GUI.croppingBox.stateChanged.connect(self.togglecroppingBox)
|
GUI.croppingBox.stateChanged.connect(self.togglecroppingBox)
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
import os
|
|
||||||
|
|
||||||
from PySide6.QtCore import (Qt)
|
|
||||||
from PySide6.QtGui import (QKeyEvent, QPixmap)
|
|
||||||
from PySide6.QtWidgets import (QHBoxLayout, QLabel, QDialog)
|
|
||||||
|
|
||||||
class LabelSpreadsDialog(QDialog):
|
|
||||||
def __init__(self, available_height, images, spreads):
|
|
||||||
super().__init__()
|
|
||||||
self.index = 0
|
|
||||||
self.images = images
|
|
||||||
self.spreads = spreads
|
|
||||||
self.index2page = {i: os.path.basename(image) for i, image in enumerate(images)}
|
|
||||||
|
|
||||||
self.setWindowTitle("TODO: Filename goes here")
|
|
||||||
# self.setGeometry(APP.primaryScreen().availableGeometry())
|
|
||||||
# self.setMaximumSize(APP.primaryScreen().availableSize())
|
|
||||||
self.available_height = available_height
|
|
||||||
|
|
||||||
layout = QHBoxLayout()
|
|
||||||
self.setLayout(layout)
|
|
||||||
|
|
||||||
label = QLabel()
|
|
||||||
label2 = QLabel()
|
|
||||||
self.label = label
|
|
||||||
self.label2 = label2
|
|
||||||
layout.addWidget(label)
|
|
||||||
layout.addWidget(label2)
|
|
||||||
label2.setText("not a spread")
|
|
||||||
|
|
||||||
help_text = [
|
|
||||||
"Use arrows to change index.",
|
|
||||||
"Use space bar to confirm spreads.",
|
|
||||||
"Use spread shift option to offset by 1.",
|
|
||||||
"Use enter key to confirm all spreads."
|
|
||||||
"Close window to cancel."
|
|
||||||
]
|
|
||||||
buttonLabel = QLabel('\n'.join(help_text))
|
|
||||||
layout.addWidget(buttonLabel)
|
|
||||||
# print(label.size())
|
|
||||||
# print(label.maximumSize())
|
|
||||||
# l, t, r, b = layout.getContentsMargins()
|
|
||||||
|
|
||||||
#label.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
||||||
pixmap = QPixmap(images[0]).scaledToHeight(self.available_height * 0.9)
|
|
||||||
label.setPixmap(pixmap)
|
|
||||||
#label.setScaledContents(True)
|
|
||||||
|
|
||||||
#label2.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
|
||||||
# pixmap2 = QPixmap(images[0]).scaledToHeight(self.frameGeometry().height() - t - b - t - b)
|
|
||||||
# label2.setPixmap(pixmap2)
|
|
||||||
#label2.setScaledContents(True)
|
|
||||||
#self.resize(pixmap2.width(), pixmap2.height())
|
|
||||||
|
|
||||||
def keyReleaseEvent(self, event):
|
|
||||||
# t = 20
|
|
||||||
# b = 20
|
|
||||||
if isinstance(event, QKeyEvent):
|
|
||||||
if event.key() == Qt.Key.Key_Left:
|
|
||||||
self.index = max(0, self.index - 1)
|
|
||||||
if self.index2page[self.index] in self.spreads:
|
|
||||||
self.label2.setText('spread')
|
|
||||||
else:
|
|
||||||
self.label2.setText('not a spread')
|
|
||||||
pixmap = QPixmap(self.images[self.index]).scaledToHeight(self.available_height * 0.9)
|
|
||||||
self.label.setPixmap(pixmap)
|
|
||||||
# pixmap2 = QPixmap(images[self.index]).scaledToHeight(self.frameGeometry().height() - t - b - t - b)
|
|
||||||
# self.label2.setPixmap(pixmap2)
|
|
||||||
elif event.key() == Qt.Key.Key_Right:
|
|
||||||
self.index = min(self.index + 1, len(self.images) - 1)
|
|
||||||
if self.index2page[self.index] in self.spreads:
|
|
||||||
self.label2.setText('spread')
|
|
||||||
else:
|
|
||||||
self.label2.setText('not a spread')
|
|
||||||
|
|
||||||
pixmap = QPixmap(self.images[self.index]).scaledToHeight(self.available_height * 0.9)
|
|
||||||
self.label.setPixmap(pixmap)
|
|
||||||
# pixmap2 = QPixmap(images[self.index]).scaledToHeight(self.frameGeometry().height() - t - b - t - b)
|
|
||||||
# self.label2.setPixmap(pixmap2)
|
|
||||||
elif event.key() == Qt.Key.Key_Space:
|
|
||||||
if self.label2.text() == "not a spread":
|
|
||||||
self.spreads.append(os.path.basename(self.images[self.index]))
|
|
||||||
self.label2.setText('spread')
|
|
||||||
else:
|
|
||||||
self.spreads.remove(os.path.basename(self.images[self.index]))
|
|
||||||
self.label2.setText('not a spread')
|
|
||||||
elif event.key() == Qt.Key.Key_Return or event.key() == Qt.Key.Key_Enter:
|
|
||||||
self.accept()
|
|
||||||
else:
|
|
||||||
super().keyReleaseEvent(event)
|
|
||||||
else:
|
|
||||||
super().keyReleaseEvent(event)
|
|
||||||
@@ -26,7 +26,7 @@ class Ui_mainWindow(object):
|
|||||||
def setupUi(self, mainWindow):
|
def setupUi(self, mainWindow):
|
||||||
if not mainWindow.objectName():
|
if not mainWindow.objectName():
|
||||||
mainWindow.setObjectName(u"mainWindow")
|
mainWindow.setObjectName(u"mainWindow")
|
||||||
mainWindow.resize(649, 706)
|
mainWindow.resize(644, 706)
|
||||||
icon = QIcon()
|
icon = QIcon()
|
||||||
icon.addFile(u":/Icon/icons/comic2ebook.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
icon.addFile(u":/Icon/icons/comic2ebook.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||||
mainWindow.setWindowIcon(icon)
|
mainWindow.setWindowIcon(icon)
|
||||||
@@ -360,39 +360,33 @@ class Ui_mainWindow(object):
|
|||||||
self.gridLayout_6 = QGridLayout(self.toolWidget)
|
self.gridLayout_6 = QGridLayout(self.toolWidget)
|
||||||
self.gridLayout_6.setObjectName(u"gridLayout_6")
|
self.gridLayout_6.setObjectName(u"gridLayout_6")
|
||||||
self.gridLayout_6.setContentsMargins(0, 0, 0, 0)
|
self.gridLayout_6.setContentsMargins(0, 0, 0, 0)
|
||||||
self.editorButton = QPushButton(self.toolWidget)
|
|
||||||
self.editorButton.setObjectName(u"editorButton")
|
|
||||||
self.editorButton.setMinimumSize(QSize(0, 30))
|
|
||||||
icon2 = QIcon()
|
|
||||||
icon2.addFile(u":/Other/icons/editor.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
|
||||||
self.editorButton.setIcon(icon2)
|
|
||||||
|
|
||||||
self.gridLayout_6.addWidget(self.editorButton, 0, 0, 1, 1)
|
|
||||||
|
|
||||||
self.humbleButton = QPushButton(self.toolWidget)
|
self.humbleButton = QPushButton(self.toolWidget)
|
||||||
self.humbleButton.setObjectName(u"humbleButton")
|
self.humbleButton.setObjectName(u"humbleButton")
|
||||||
self.humbleButton.setMinimumSize(QSize(0, 30))
|
self.humbleButton.setMinimumSize(QSize(0, 30))
|
||||||
icon3 = QIcon()
|
icon2 = QIcon()
|
||||||
icon3.addFile(u":/Brand/icons/Humble_H-Red.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
icon2.addFile(u":/Brand/icons/Humble_H-Red.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||||
self.humbleButton.setIcon(icon3)
|
self.humbleButton.setIcon(icon2)
|
||||||
|
|
||||||
self.gridLayout_6.addWidget(self.humbleButton, 0, 3, 1, 1)
|
self.gridLayout_6.addWidget(self.humbleButton, 0, 2, 1, 1)
|
||||||
|
|
||||||
self.kofiButton = QPushButton(self.toolWidget)
|
self.kofiButton = QPushButton(self.toolWidget)
|
||||||
self.kofiButton.setObjectName(u"kofiButton")
|
self.kofiButton.setObjectName(u"kofiButton")
|
||||||
self.kofiButton.setMinimumSize(QSize(0, 30))
|
self.kofiButton.setMinimumSize(QSize(0, 30))
|
||||||
icon4 = QIcon()
|
icon3 = QIcon()
|
||||||
icon4.addFile(u":/Brand/icons/kofi_symbol.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
icon3.addFile(u":/Brand/icons/kofi_symbol.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||||
self.kofiButton.setIcon(icon4)
|
self.kofiButton.setIcon(icon3)
|
||||||
self.kofiButton.setIconSize(QSize(19, 16))
|
self.kofiButton.setIconSize(QSize(19, 16))
|
||||||
|
|
||||||
self.gridLayout_6.addWidget(self.kofiButton, 0, 2, 1, 1)
|
self.gridLayout_6.addWidget(self.kofiButton, 0, 1, 1, 1)
|
||||||
|
|
||||||
self.labelSpreadsButton = QPushButton(self.toolWidget)
|
self.editorButton = QPushButton(self.toolWidget)
|
||||||
self.labelSpreadsButton.setObjectName(u"labelSpreadsButton")
|
self.editorButton.setObjectName(u"editorButton")
|
||||||
self.labelSpreadsButton.setMinimumSize(QSize(0, 30))
|
self.editorButton.setMinimumSize(QSize(0, 30))
|
||||||
|
icon4 = QIcon()
|
||||||
|
icon4.addFile(u":/Other/icons/editor.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||||
|
self.editorButton.setIcon(icon4)
|
||||||
|
|
||||||
self.gridLayout_6.addWidget(self.labelSpreadsButton, 0, 1, 1, 1)
|
self.gridLayout_6.addWidget(self.editorButton, 0, 0, 1, 1)
|
||||||
|
|
||||||
|
|
||||||
self.gridLayout.addWidget(self.toolWidget, 0, 0, 1, 2)
|
self.gridLayout.addWidget(self.toolWidget, 0, 0, 1, 2)
|
||||||
@@ -549,20 +543,39 @@ class Ui_mainWindow(object):
|
|||||||
self.gridLayout_4 = QGridLayout(self.buttonWidget)
|
self.gridLayout_4 = QGridLayout(self.buttonWidget)
|
||||||
self.gridLayout_4.setObjectName(u"gridLayout_4")
|
self.gridLayout_4.setObjectName(u"gridLayout_4")
|
||||||
self.gridLayout_4.setContentsMargins(0, 0, 0, 0)
|
self.gridLayout_4.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.convertButton = QPushButton(self.buttonWidget)
|
||||||
|
self.convertButton.setObjectName(u"convertButton")
|
||||||
|
self.convertButton.setMinimumSize(QSize(0, 30))
|
||||||
|
self.convertButton.setFont(font)
|
||||||
|
icon5 = QIcon()
|
||||||
|
icon5.addFile(u":/Other/icons/convert.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||||
|
self.convertButton.setIcon(icon5)
|
||||||
|
|
||||||
|
self.gridLayout_4.addWidget(self.convertButton, 1, 3, 1, 1)
|
||||||
|
|
||||||
|
self.clearButton = QPushButton(self.buttonWidget)
|
||||||
|
self.clearButton.setObjectName(u"clearButton")
|
||||||
|
self.clearButton.setMinimumSize(QSize(0, 30))
|
||||||
|
icon6 = QIcon()
|
||||||
|
icon6.addFile(u":/Other/icons/clear.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||||
|
self.clearButton.setIcon(icon6)
|
||||||
|
|
||||||
|
self.gridLayout_4.addWidget(self.clearButton, 0, 3, 1, 1)
|
||||||
|
|
||||||
self.deviceBox = QComboBox(self.buttonWidget)
|
self.deviceBox = QComboBox(self.buttonWidget)
|
||||||
self.deviceBox.setObjectName(u"deviceBox")
|
self.deviceBox.setObjectName(u"deviceBox")
|
||||||
self.deviceBox.setMinimumSize(QSize(0, 28))
|
self.deviceBox.setMinimumSize(QSize(0, 28))
|
||||||
|
|
||||||
self.gridLayout_4.addWidget(self.deviceBox, 1, 1, 1, 1)
|
self.gridLayout_4.addWidget(self.deviceBox, 1, 1, 1, 1)
|
||||||
|
|
||||||
self.clearButton = QPushButton(self.buttonWidget)
|
self.fileButton = QPushButton(self.buttonWidget)
|
||||||
self.clearButton.setObjectName(u"clearButton")
|
self.fileButton.setObjectName(u"fileButton")
|
||||||
self.clearButton.setMinimumSize(QSize(0, 30))
|
self.fileButton.setMinimumSize(QSize(0, 30))
|
||||||
icon5 = QIcon()
|
icon7 = QIcon()
|
||||||
icon5.addFile(u":/Other/icons/clear.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
icon7.addFile(u":/Other/icons/document_new.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
||||||
self.clearButton.setIcon(icon5)
|
self.fileButton.setIcon(icon7)
|
||||||
|
|
||||||
self.gridLayout_4.addWidget(self.clearButton, 0, 3, 1, 1)
|
self.gridLayout_4.addWidget(self.fileButton, 0, 1, 1, 1)
|
||||||
|
|
||||||
self.directoryButton = QPushButton(self.buttonWidget)
|
self.directoryButton = QPushButton(self.buttonWidget)
|
||||||
self.directoryButton.setObjectName(u"directoryButton")
|
self.directoryButton.setObjectName(u"directoryButton")
|
||||||
@@ -575,25 +588,6 @@ class Ui_mainWindow(object):
|
|||||||
|
|
||||||
self.gridLayout_4.addWidget(self.directoryButton, 0, 4, 1, 1)
|
self.gridLayout_4.addWidget(self.directoryButton, 0, 4, 1, 1)
|
||||||
|
|
||||||
self.convertButton = QPushButton(self.buttonWidget)
|
|
||||||
self.convertButton.setObjectName(u"convertButton")
|
|
||||||
self.convertButton.setMinimumSize(QSize(0, 30))
|
|
||||||
self.convertButton.setFont(font)
|
|
||||||
icon6 = QIcon()
|
|
||||||
icon6.addFile(u":/Other/icons/convert.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
|
||||||
self.convertButton.setIcon(icon6)
|
|
||||||
|
|
||||||
self.gridLayout_4.addWidget(self.convertButton, 1, 3, 1, 1)
|
|
||||||
|
|
||||||
self.fileButton = QPushButton(self.buttonWidget)
|
|
||||||
self.fileButton.setObjectName(u"fileButton")
|
|
||||||
self.fileButton.setMinimumSize(QSize(0, 30))
|
|
||||||
icon7 = QIcon()
|
|
||||||
icon7.addFile(u":/Other/icons/document_new.png", QSize(), QIcon.Mode.Normal, QIcon.State.Off)
|
|
||||||
self.fileButton.setIcon(icon7)
|
|
||||||
|
|
||||||
self.gridLayout_4.addWidget(self.fileButton, 0, 1, 1, 1)
|
|
||||||
|
|
||||||
self.formatBox = QComboBox(self.buttonWidget)
|
self.formatBox = QComboBox(self.buttonWidget)
|
||||||
self.formatBox.setObjectName(u"formatBox")
|
self.formatBox.setObjectName(u"formatBox")
|
||||||
self.formatBox.setMinimumSize(QSize(0, 28))
|
self.formatBox.setMinimumSize(QSize(0, 28))
|
||||||
@@ -854,13 +848,12 @@ class Ui_mainWindow(object):
|
|||||||
"Keeping this file may crash some readers like the Kobo native CBZ reader.", None))
|
"Keeping this file may crash some readers like the Kobo native CBZ reader.", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
self.keepComicInfoBox.setText(QCoreApplication.translate("mainWindow", u"Keep ComicInfo.xml", None))
|
self.keepComicInfoBox.setText(QCoreApplication.translate("mainWindow", u"Keep ComicInfo.xml", None))
|
||||||
|
self.humbleButton.setText(QCoreApplication.translate("mainWindow", u"Humble Bundle Referral", None))
|
||||||
|
self.kofiButton.setText(QCoreApplication.translate("mainWindow", u"Support me on Ko-fi", None))
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.editorButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Shift+Click to edit directory.</p></body></html>", None))
|
self.editorButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Shift+Click to edit directory.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
self.editorButton.setText(QCoreApplication.translate("mainWindow", u"Metadata Editor", None))
|
self.editorButton.setText(QCoreApplication.translate("mainWindow", u"Metadata Editor", None))
|
||||||
self.humbleButton.setText(QCoreApplication.translate("mainWindow", u"Humble Bundle Referral", None))
|
|
||||||
self.kofiButton.setText(QCoreApplication.translate("mainWindow", u"Support me on Ko-fi", None))
|
|
||||||
self.labelSpreadsButton.setText(QCoreApplication.translate("mainWindow", u"Label Spreads", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.chunkSizeWidget.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p>Warning: chunk size greater than default may cause<br/>performance/battery issues, especially on older devices.</p></body></html>", None))
|
self.chunkSizeWidget.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p>Warning: chunk size greater than default may cause<br/>performance/battery issues, especially on older devices.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
@@ -885,22 +878,22 @@ class Ui_mainWindow(object):
|
|||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.heightBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
|
self.heightBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Resolution of the target device.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
#if QT_CONFIG(tooltip)
|
|
||||||
self.deviceBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Target device.</p></body></html>", None))
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
|
||||||
self.clearButton.setText(QCoreApplication.translate("mainWindow", u"Clear list", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
|
||||||
self.directoryButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=\" font-weight:600;\">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html>", None))
|
|
||||||
#endif // QT_CONFIG(tooltip)
|
|
||||||
self.directoryButton.setText(QCoreApplication.translate("mainWindow", u"Add input folder(s)", None))
|
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.convertButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory for this list.</p></body></html>", None))
|
self.convertButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Shift+Click to select the output directory for this list.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
self.convertButton.setText(QCoreApplication.translate("mainWindow", u"Convert", None))
|
self.convertButton.setText(QCoreApplication.translate("mainWindow", u"Convert", None))
|
||||||
|
self.clearButton.setText(QCoreApplication.translate("mainWindow", u"Clear list", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.deviceBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Target device.</p></body></html>", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.fileButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>", None))
|
self.fileButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Add CBR, CBZ, CB7 or PDF file to queue.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
self.fileButton.setText(QCoreApplication.translate("mainWindow", u"Add input file(s)", None))
|
self.fileButton.setText(QCoreApplication.translate("mainWindow", u"Add input file(s)", None))
|
||||||
|
#if QT_CONFIG(tooltip)
|
||||||
|
self.directoryButton.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Add directory containing JPG, PNG or GIF files to queue.<br/><span style=\" font-weight:600;\">CBR, CBZ and CB7 files inside will not be processed!</span></p></body></html>", None))
|
||||||
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
self.directoryButton.setText(QCoreApplication.translate("mainWindow", u"Add input folder(s)", None))
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.formatBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Output format.</p></body></html>", None))
|
self.formatBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'>Output format.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = '11.0.0'
|
__version__ = '10.4.0'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2022, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>, darodi'
|
__copyright__ = '2012-2022, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>, darodi'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|||||||
@@ -20,7 +20,6 @@
|
|||||||
|
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import pathlib
|
import pathlib
|
||||||
import re
|
import re
|
||||||
@@ -873,7 +872,7 @@ def extract_page(vector):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def mupdf_pdf_process_pages_parallel(filename, output_dir, target_width, target_height, pdfwidth):
|
def mupdf_pdf_process_pages_parallel(filename, output_dir, target_width, target_height):
|
||||||
render = False
|
render = False
|
||||||
with pymupdf.open(filename) as doc:
|
with pymupdf.open(filename) as doc:
|
||||||
for page in doc:
|
for page in doc:
|
||||||
@@ -893,7 +892,7 @@ def mupdf_pdf_process_pages_parallel(filename, output_dir, target_width, target_
|
|||||||
cpu = cpu_count()
|
cpu = cpu_count()
|
||||||
|
|
||||||
# make vectors of arguments for the processes
|
# make vectors of arguments for the processes
|
||||||
vectors = [(i, cpu, filename, output_dir, target_width, target_height, pdfwidth) for i in range(cpu)]
|
vectors = [(i, cpu, filename, output_dir, target_width, target_height, options.pdfwidth) for i in range(cpu)]
|
||||||
print("Starting %i processes for '%s'." % (cpu, filename))
|
print("Starting %i processes for '%s'." % (cpu, filename))
|
||||||
|
|
||||||
|
|
||||||
@@ -907,7 +906,7 @@ def mupdf_pdf_process_pages_parallel(filename, output_dir, target_width, target_
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getWorkFolder(afile, options, workdir=None):
|
def getWorkFolder(afile, workdir=None):
|
||||||
if not workdir:
|
if not workdir:
|
||||||
if options.tempdir:
|
if options.tempdir:
|
||||||
workdir = mkdtemp('', 'KCC-', os.path.dirname(afile))
|
workdir = mkdtemp('', 'KCC-', os.path.dirname(afile))
|
||||||
@@ -956,7 +955,7 @@ def getWorkFolder(afile, options, workdir=None):
|
|||||||
target_height *= 1.25 #Account for possible margin at the top and bottom with page number
|
target_height *= 1.25 #Account for possible margin at the top and bottom with page number
|
||||||
target_width *= 1.25
|
target_width *= 1.25
|
||||||
try:
|
try:
|
||||||
mupdf_pdf_process_pages_parallel(afile, fullPath, target_width, target_height, options.pdfwidth)
|
mupdf_pdf_process_pages_parallel(afile, fullPath, target_width, target_height)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
rmtree(path, True)
|
rmtree(path, True)
|
||||||
raise UserWarning(f"Failed to extract images from PDF file. {e}")
|
raise UserWarning(f"Failed to extract images from PDF file. {e}")
|
||||||
@@ -980,16 +979,9 @@ def getWorkFolder(afile, options, workdir=None):
|
|||||||
os.path.join(fullPath, tdir[0], 'ComicInfo.xml')
|
os.path.join(fullPath, tdir[0], 'ComicInfo.xml')
|
||||||
)
|
)
|
||||||
if len(tdir) == 1 and os.path.isdir(os.path.join(fullPath, tdir[0])):
|
if len(tdir) == 1 and os.path.isdir(os.path.join(fullPath, tdir[0])):
|
||||||
if options.tempdir:
|
|
||||||
workdir2 = mkdtemp('', 'KCC-', os.path.dirname(afile))
|
|
||||||
else:
|
|
||||||
workdir2 = mkdtemp('', 'KCC-')
|
|
||||||
fullPath2 = os.path.join(workdir2, 'OEBPS', 'Images')
|
|
||||||
os.makedirs(fullPath2, exist_ok=True)
|
|
||||||
for file in os.listdir(os.path.join(fullPath, tdir[0])):
|
for file in os.listdir(os.path.join(fullPath, tdir[0])):
|
||||||
move(os.path.join(fullPath, tdir[0], file), fullPath2)
|
move(os.path.join(fullPath, tdir[0], file), fullPath)
|
||||||
rmtree(workdir, True)
|
os.rmdir(os.path.join(fullPath, tdir[0]))
|
||||||
return workdir2
|
|
||||||
|
|
||||||
if options.legacyextract:
|
if options.legacyextract:
|
||||||
return workdir
|
return workdir
|
||||||
@@ -1230,7 +1222,7 @@ def removeNonImages(filetree):
|
|||||||
raise RuntimeError('\n'.join(warning))
|
raise RuntimeError('\n'.join(warning))
|
||||||
|
|
||||||
|
|
||||||
def sanitizeTree(filetree, options, prefix='kcc'):
|
def sanitizeTree(filetree, prefix='kcc'):
|
||||||
chapterNames = {}
|
chapterNames = {}
|
||||||
page = 1
|
page = 1
|
||||||
cover_path = None
|
cover_path = None
|
||||||
@@ -1255,7 +1247,7 @@ def sanitizeTree(filetree, options, prefix='kcc'):
|
|||||||
dirs.sort(key=OS_SORT_KEY)
|
dirs.sort(key=OS_SORT_KEY)
|
||||||
for i, name in enumerate(dirs):
|
for i, name in enumerate(dirs):
|
||||||
tmpName = name
|
tmpName = name
|
||||||
slugified = slugify(name, options, is_natural_sorted)
|
slugified = slugify(name, is_natural_sorted)
|
||||||
while os.path.exists(os.path.join(root, slugified)) and name.upper() != slugified.upper():
|
while os.path.exists(os.path.join(root, slugified)) and name.upper() != slugified.upper():
|
||||||
slugified += "A"
|
slugified += "A"
|
||||||
chapterNames[slugified] = tmpName
|
chapterNames[slugified] = tmpName
|
||||||
@@ -1418,7 +1410,7 @@ def createNewTome(parent):
|
|||||||
return tomePath, tomePathRoot
|
return tomePath, tomePathRoot
|
||||||
|
|
||||||
|
|
||||||
def slugify(value, options, is_natural_sorted):
|
def slugify(value, is_natural_sorted):
|
||||||
if options.format == 'CBZ' and is_natural_sorted:
|
if options.format == 'CBZ' and is_natural_sorted:
|
||||||
return value
|
return value
|
||||||
if options.format != 'CBZ':
|
if options.format != 'CBZ':
|
||||||
@@ -1783,10 +1775,10 @@ def makeFusion(sources: List[str]):
|
|||||||
else:
|
else:
|
||||||
targetpath = fusion_path.joinpath(f'{prefix}{source_path.name}')
|
targetpath = fusion_path.joinpath(f'{prefix}{source_path.name}')
|
||||||
|
|
||||||
path = getWorkFolder(source, options, str(targetpath))
|
path = getWorkFolder(source, str(targetpath))
|
||||||
if path != str(targetpath):
|
if path != str(targetpath):
|
||||||
move(os.path.join(path, 'OEBPS', 'Images'), targetpath)
|
move(os.path.join(path, 'OEBPS', 'Images'), targetpath)
|
||||||
sanitizeTree(targetpath, options, prefix='fusion')
|
sanitizeTree(targetpath, prefix='fusion')
|
||||||
# TODO: remove flattenTree when subchapters are supported
|
# TODO: remove flattenTree when subchapters are supported
|
||||||
flattenTree(targetpath)
|
flattenTree(targetpath)
|
||||||
|
|
||||||
@@ -1809,7 +1801,7 @@ def makeBook(source, qtgui=None, job_progress=''):
|
|||||||
if not options.filefusion:
|
if not options.filefusion:
|
||||||
checkPre('LLL-')
|
checkPre('LLL-')
|
||||||
print(f"{job_progress}Preparing source images...")
|
print(f"{job_progress}Preparing source images...")
|
||||||
path = getWorkFolder(source, options)
|
path = getWorkFolder(source)
|
||||||
print(f"{job_progress}Checking images...")
|
print(f"{job_progress}Checking images...")
|
||||||
|
|
||||||
if options.lightnovel:
|
if options.lightnovel:
|
||||||
@@ -1843,26 +1835,7 @@ def makeBook(source, qtgui=None, job_progress=''):
|
|||||||
getMetadata(os.path.join(path, "OEBPS", "Images"), source)
|
getMetadata(os.path.join(path, "OEBPS", "Images"), source)
|
||||||
removeNonImages(os.path.join(path, "OEBPS", "Images"))
|
removeNonImages(os.path.join(path, "OEBPS", "Images"))
|
||||||
detectSuboptimalProcessing(os.path.join(path, "OEBPS", "Images"), source)
|
detectSuboptimalProcessing(os.path.join(path, "OEBPS", "Images"), source)
|
||||||
chapterNames, cover_path = sanitizeTree(os.path.join(path, 'OEBPS', 'Images'), options)
|
chapterNames, cover_path = sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
|
||||||
|
|
||||||
if os.path.exists(source+'.json'):
|
|
||||||
flattenTree(os.path.join(path, 'OEBPS', 'Images'))
|
|
||||||
with open(source+'.json') as f:
|
|
||||||
data = json.load(f)
|
|
||||||
for root, _, files in os.walk(os.path.join(path, 'OEBPS', 'Images')):
|
|
||||||
sorted_files = os_sorted(files)
|
|
||||||
for i in range(len(files)):
|
|
||||||
if i in data['spreads']:
|
|
||||||
im1 = Image.open(os.path.join(root, sorted_files[i]))
|
|
||||||
im2 = Image.open(os.path.join(root, sorted_files[i+1]))
|
|
||||||
dst = Image.new('RGB', (im1.width + im2.width, im1.height))
|
|
||||||
dst.paste(im2, (0, 0))
|
|
||||||
dst.paste(im1, (im1.width, 0))
|
|
||||||
base, _ = os.path.splitext(os.path.basename(sorted_files[i]))
|
|
||||||
dst.save(os.path.join(path, 'OEBPS', 'Images', f'{base}-merged.png'))
|
|
||||||
os.remove(os.path.join(root, sorted_files[i]))
|
|
||||||
os.remove(os.path.join(root, sorted_files[i+1]))
|
|
||||||
|
|
||||||
if options.filefusion:
|
if options.filefusion:
|
||||||
# Strip the fusion_0001_ sort prefix from makeFusion if present
|
# Strip the fusion_0001_ sort prefix from makeFusion if present
|
||||||
chapterNames = {k: sub(r'^fusion_\d{4}_', '', v) for k, v in chapterNames.items()}
|
chapterNames = {k: sub(r'^fusion_\d{4}_', '', v) for k, v in chapterNames.items()}
|
||||||
|
|||||||
Reference in New Issue
Block a user