From 3e3710dd76fc73b9dccfc4eb455199ea334b007c Mon Sep 17 00:00:00 2001 From: Alex Xu Date: Thu, 3 Apr 2025 10:11:14 -0700 Subject: [PATCH] Add preserve margin % toggle (#886) * preserve margin * set ratio to 0.5 * add preserve margin GUI * increase step size to 5 * remove clear * fix save * save preserveMarginBox * math * max 99 --- README.md | 1 + gui/KCC.ui | 35 +++++++++++++++-- kindlecomicconverter/KCC_gui.py | 3 ++ kindlecomicconverter/KCC_rc.py | 38 +++++++++--------- kindlecomicconverter/KCC_ui.py | 60 ++++++++++++++++++++--------- kindlecomicconverter/comic2ebook.py | 2 + kindlecomicconverter/image.py | 5 +++ 7 files changed, 103 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index a66de4d..6bc76bf 100644 --- a/README.md +++ b/README.md @@ -181,6 +181,7 @@ PROCESSING: Set cropping mode. 0: Disabled 1: Margins 2: Margins + page numbers [Default=2] --cp CROPPINGP, --croppingpower CROPPINGP Set cropping power [Default=1.0] + --preservemargin After calculating crop, "back up" a specified percentage amount [Default=0] --cm CROPPINGM, --croppingminimum CROPPINGM Set cropping minimum area ratio [Default=0.0] --ipc INTERPANELCROP, --interpanelcrop INTERPANELCROP diff --git a/gui/KCC.ui b/gui/KCC.ui index 3abefaf..9c9bd58 100644 --- a/gui/KCC.ui +++ b/gui/KCC.ui @@ -330,7 +330,7 @@ false - + 0 @@ -343,14 +343,24 @@ 0 - + + + + <html><head/><body><p>After calculating the cropping boundaries, &quot;back up&quot; a specified percentage amount.</p></body></html> + + + Preserve Margin % + + + + Cropping power: - + 300 @@ -363,6 +373,25 @@ + + + + + 0 + 0 + + + + 99 + + + 5 + + + 0 + + + diff --git a/kindlecomicconverter/KCC_gui.py b/kindlecomicconverter/KCC_gui.py index db299b5..f78a066 100644 --- a/kindlecomicconverter/KCC_gui.py +++ b/kindlecomicconverter/KCC_gui.py @@ -246,6 +246,7 @@ class WorkerThread(QThread): options.cropping = GUI.croppingBox.checkState().value if GUI.croppingBox.checkState() != Qt.CheckState.Unchecked: options.croppingp = float(GUI.croppingPowerValue) + options.preservemargin = GUI.preserveMarginBox.value() options.interpanelcrop = GUI.interPanelCropBox.checkState().value if GUI.borderBox.checkState() == Qt.CheckState.PartiallyChecked: options.white_borders = True @@ -803,6 +804,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow): 'gammaBox': GUI.gammaBox.checkState().value, 'croppingBox': GUI.croppingBox.checkState().value, 'croppingPowerSlider': float(self.croppingPowerValue) * 100, + 'preserveMarginBox': self.preserveMarginBox.value(), 'interPanelCropBox': GUI.interPanelCropBox.checkState().value, 'upscaleBox': GUI.upscaleBox.checkState().value, 'borderBox': GUI.borderBox.checkState().value, @@ -1159,6 +1161,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow): if GUI.croppingPowerSlider.isEnabled(): GUI.croppingPowerSlider.setValue(int(self.options[option])) self.changeCroppingPower(int(self.options[option])) + GUI.preserveMarginBox.setValue(self.options.get('preserveMarginBox', 0)) elif str(option) == "chunkSizeBox": GUI.chunkSizeBox.setValue(int(self.options[option])) else: diff --git a/kindlecomicconverter/KCC_rc.py b/kindlecomicconverter/KCC_rc.py index 6ba25c0..bc8aa29 100644 --- a/kindlecomicconverter/KCC_rc.py +++ b/kindlecomicconverter/KCC_rc.py @@ -11612,51 +11612,51 @@ qt_resource_struct = b"\ \x00\x00\x00X\x00\x02\x00\x00\x00\x04\x00\x00\x00\x07\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x01\xc0\x00\x00\x00\x00\x00\x01\x00\x02.\xed\ -\x00\x00\x01\x95\xcf\xe3\x00\xfc\ +\x00\x00\x01\x88;p\xbcB\ \x00\x00\x01\xfe\x00\x00\x00\x00\x00\x01\x00\x02\x83\x87\ -\x00\x00\x01\x95\xcf\xe3\x00\xfb\ +\x00\x00\x01\x88;p\xbcB\ \x00\x00\x01\xea\x00\x00\x00\x00\x00\x01\x00\x02Y\x8c\ -\x00\x00\x01\x95\xcf\xe3\x00\xfb\ +\x00\x00\x01\x88;p\xbcB\ \x00\x00\x01\xd6\x00\x00\x00\x00\x00\x01\x00\x02N)\ -\x00\x00\x01\x95\xcf\xe3\x00\xfb\ +\x00\x00\x01\x89\x89D9.\ \x00\x00\x00X\x00\x02\x00\x00\x00\x04\x00\x00\x00\x0c\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x01(\x97\ -\x00\x00\x01\x95\xcf\xe3\x00\xfc\ +\x00\x00\x01\x88;p\xbcB\ \x00\x00\x00\xbc\x00\x00\x00\x00\x00\x01\x00\x011\xef\ -\x00\x00\x01\x95\xcf\xe3\x00\xfd\ +\x00\x00\x01\x94\x1a\xa2\xa2\x92\ \x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x01\x1d\x90\ -\x00\x00\x01\x95\xcf\xe3\x00\xfc\ +\x00\x00\x01\x88;p\xbcB\ \x00\x00\x00\xd0\x00\x00\x00\x00\x00\x01\x00\x01:\x05\ -\x00\x00\x01\x95\xcf\xe3\x00\xfd\ +\x00\x00\x01\x88;p\xbcB\ \x00\x00\x00X\x00\x02\x00\x00\x00\x03\x00\x00\x00\x11\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x02B\x00\x00\x00\x00\x00\x01\x00\x02\xb5\xd3\ -\x00\x00\x01\x95\xcf\xe3\x01\x0c\ +\x00\x00\x01\x88;p\xbcJ\ \x00\x00\x02\x14\x00\x00\x00\x00\x00\x01\x00\x02\x9f\xd6\ -\x00\x00\x01\x95\xcf\xe3\x01\x0a\ +\x00\x00\x01\x88;p\xbcI\ \x00\x00\x02*\x00\x00\x00\x00\x00\x01\x00\x02\xa93\ -\x00\x00\x01\x95\xcf\xe3\x01\x09\ +\x00\x00\x01\x88;p\xbcI\ \x00\x00\x00X\x00\x02\x00\x00\x00\x07\x00\x00\x00\x15\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x01P\xb1\ -\x00\x00\x01\x95\xcf\xe3\x01\x0c\ +\x00\x00\x01\x88;p\xbcJ\ \x00\x00\x012\x00\x00\x00\x00\x00\x01\x00\x01yY\ -\x00\x00\x01\x95\xcf\xe3\x01\x0a\ +\x00\x00\x01\x88;p\xbcI\ \x00\x00\x01\x94\x00\x00\x00\x00\x00\x01\x00\x01\xd2-\ -\x00\x00\x01\x95\xcf\xe3\x01\x0a\ +\x00\x00\x01\x94\xb4\xd4\xf0a\ \x00\x00\x01z\x00\x00\x00\x00\x00\x01\x00\x01\x8c\xe6\ -\x00\x00\x01\x95\xcf\xe3\x01\x09\ +\x00\x00\x01\x88;p\xbcH\ \x00\x00\x01\x04\x00\x00\x00\x00\x00\x01\x00\x01LR\ -\x00\x00\x01\x95\xcf\xe3\x01\x02\ +\x00\x00\x01\x88;p\xbcF\ \x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x01?\xe9\ -\x00\x00\x01\x95\xcf\xe3\x01\x08\ +\x00\x00\x01\x88;p\xbcH\ \x00\x00\x01T\x00\x00\x00\x00\x00\x01\x00\x01\x82\xb0\ -\x00\x00\x01\x95\xcf\xe3\x01\x09\ +\x00\x00\x01\x88;p\xbcH\ \x00\x00\x00X\x00\x02\x00\x00\x00\x01\x00\x00\x00\x1d\ \x00\x00\x00\x00\x00\x00\x00\x00\ \x00\x00\x00h\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ -\x00\x00\x01\x95\xcf\xe3\x01\x08\ +\x00\x00\x01\x88;p\xbcH\ " def qInitResources(): diff --git a/kindlecomicconverter/KCC_ui.py b/kindlecomicconverter/KCC_ui.py index 7811ffd..34a50c3 100644 --- a/kindlecomicconverter/KCC_ui.py +++ b/kindlecomicconverter/KCC_ui.py @@ -190,13 +190,18 @@ class Ui_mainWindow(object): self.croppingWidget = QWidget(self.centralWidget) self.croppingWidget.setObjectName(u"croppingWidget") self.croppingWidget.setVisible(False) - self.horizontalLayout_3 = QHBoxLayout(self.croppingWidget) - self.horizontalLayout_3.setObjectName(u"horizontalLayout_3") - self.horizontalLayout_3.setContentsMargins(0, 0, 0, 0) + self.gridLayout_5 = QGridLayout(self.croppingWidget) + self.gridLayout_5.setObjectName(u"gridLayout_5") + self.gridLayout_5.setContentsMargins(0, 0, 0, 0) + self.preserveMarginLabel = QLabel(self.croppingWidget) + self.preserveMarginLabel.setObjectName(u"preserveMarginLabel") + + self.gridLayout_5.addWidget(self.preserveMarginLabel, 1, 0, 1, 1) + self.croppingPowerLabel = QLabel(self.croppingWidget) self.croppingPowerLabel.setObjectName(u"croppingPowerLabel") - self.horizontalLayout_3.addWidget(self.croppingPowerLabel) + self.gridLayout_5.addWidget(self.croppingPowerLabel, 0, 0, 1, 1) self.croppingPowerSlider = QSlider(self.croppingWidget) self.croppingPowerSlider.setObjectName(u"croppingPowerSlider") @@ -204,7 +209,20 @@ class Ui_mainWindow(object): self.croppingPowerSlider.setSingleStep(1) self.croppingPowerSlider.setOrientation(Qt.Orientation.Horizontal) - self.horizontalLayout_3.addWidget(self.croppingPowerSlider) + self.gridLayout_5.addWidget(self.croppingPowerSlider, 0, 1, 1, 1) + + self.preserveMarginBox = QSpinBox(self.croppingWidget) + self.preserveMarginBox.setObjectName(u"preserveMarginBox") + sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) + sizePolicy2.setHorizontalStretch(0) + sizePolicy2.setVerticalStretch(0) + sizePolicy2.setHeightForWidth(self.preserveMarginBox.sizePolicy().hasHeightForWidth()) + self.preserveMarginBox.setSizePolicy(sizePolicy2) + self.preserveMarginBox.setMaximum(99) + self.preserveMarginBox.setSingleStep(5) + self.preserveMarginBox.setValue(0) + + self.gridLayout_5.addWidget(self.preserveMarginBox, 1, 1, 1, 1) self.gridLayout.addWidget(self.croppingWidget, 9, 0, 1, 2) @@ -276,11 +294,11 @@ class Ui_mainWindow(object): self.authorEdit = QLineEdit(self.optionWidget) self.authorEdit.setObjectName(u"authorEdit") - sizePolicy2 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) - sizePolicy2.setHorizontalStretch(0) - sizePolicy2.setVerticalStretch(0) - sizePolicy2.setHeightForWidth(self.authorEdit.sizePolicy().hasHeightForWidth()) - self.authorEdit.setSizePolicy(sizePolicy2) + sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Fixed) + sizePolicy3.setHorizontalStretch(0) + sizePolicy3.setVerticalStretch(0) + sizePolicy3.setHeightForWidth(self.authorEdit.sizePolicy().hasHeightForWidth()) + self.authorEdit.setSizePolicy(sizePolicy3) self.authorEdit.setFocusPolicy(Qt.FocusPolicy.ClickFocus) self.authorEdit.setClearButtonEnabled(False) @@ -355,8 +373,8 @@ class Ui_mainWindow(object): self.chunkSizeWidget = QWidget(self.centralWidget) self.chunkSizeWidget.setObjectName(u"chunkSizeWidget") - sizePolicy2.setHeightForWidth(self.chunkSizeWidget.sizePolicy().hasHeightForWidth()) - self.chunkSizeWidget.setSizePolicy(sizePolicy2) + sizePolicy3.setHeightForWidth(self.chunkSizeWidget.sizePolicy().hasHeightForWidth()) + self.chunkSizeWidget.setSizePolicy(sizePolicy3) self.chunkSizeWidget.setVisible(False) self.horizontalLayout_4 = QHBoxLayout(self.chunkSizeWidget) self.horizontalLayout_4.setSpacing(0) @@ -364,11 +382,11 @@ class Ui_mainWindow(object): self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0) self.chunkSizeLabel = QLabel(self.chunkSizeWidget) self.chunkSizeLabel.setObjectName(u"chunkSizeLabel") - sizePolicy3 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Preferred) - sizePolicy3.setHorizontalStretch(0) - sizePolicy3.setVerticalStretch(0) - sizePolicy3.setHeightForWidth(self.chunkSizeLabel.sizePolicy().hasHeightForWidth()) - self.chunkSizeLabel.setSizePolicy(sizePolicy3) + sizePolicy4 = QSizePolicy(QSizePolicy.Policy.Minimum, QSizePolicy.Policy.Preferred) + sizePolicy4.setHorizontalStretch(0) + sizePolicy4.setVerticalStretch(0) + sizePolicy4.setHeightForWidth(self.chunkSizeLabel.sizePolicy().hasHeightForWidth()) + self.chunkSizeLabel.setSizePolicy(sizePolicy4) self.horizontalLayout_4.addWidget(self.chunkSizeLabel) @@ -382,8 +400,8 @@ class Ui_mainWindow(object): self.chunkSizeWarnLabel = QLabel(self.chunkSizeWidget) self.chunkSizeWarnLabel.setObjectName(u"chunkSizeWarnLabel") - sizePolicy3.setHeightForWidth(self.chunkSizeWarnLabel.sizePolicy().hasHeightForWidth()) - self.chunkSizeWarnLabel.setSizePolicy(sizePolicy3) + sizePolicy4.setHeightForWidth(self.chunkSizeWarnLabel.sizePolicy().hasHeightForWidth()) + self.chunkSizeWarnLabel.setSizePolicy(sizePolicy4) self.horizontalLayout_4.addWidget(self.chunkSizeWarnLabel) @@ -472,6 +490,10 @@ class Ui_mainWindow(object): #if QT_CONFIG(tooltip) self.heightBox.setToolTip(QCoreApplication.translate("mainWindow", u"

Resolution of the target device.

", None)) #endif // QT_CONFIG(tooltip) +#if QT_CONFIG(tooltip) + self.preserveMarginLabel.setToolTip(QCoreApplication.translate("mainWindow", u"

After calculating the cropping boundaries, "back up" a specified percentage amount.

", None)) +#endif // QT_CONFIG(tooltip) + self.preserveMarginLabel.setText(QCoreApplication.translate("mainWindow", u"Preserve Margin %", None)) self.croppingPowerLabel.setText(QCoreApplication.translate("mainWindow", u"Cropping power:", None)) #if QT_CONFIG(tooltip) self.croppingBox.setToolTip(QCoreApplication.translate("mainWindow", u"

Unchecked - Disabled

Disabled

Indeterminate - Margins
Margins

Checked - Margins + page numbers
Margins +page numbers

", None)) diff --git a/kindlecomicconverter/comic2ebook.py b/kindlecomicconverter/comic2ebook.py index 85bad15..9f092b3 100755 --- a/kindlecomicconverter/comic2ebook.py +++ b/kindlecomicconverter/comic2ebook.py @@ -1050,6 +1050,8 @@ def makeParser(): help="Set cropping mode. 0: Disabled 1: Margins 2: Margins + page numbers [Default=2]") processing_options.add_argument("--cp", "--croppingpower", type=float, dest="croppingp", default="1.0", help="Set cropping power [Default=1.0]") + processing_options.add_argument("--preservemargin", type=int, dest="preservemargin", default="0", + help="After calculating crop, back up specified percentage amount. [Default=0]") processing_options.add_argument("--cm", "--croppingminimum", type=float, dest="croppingm", default="0.0", help="Set cropping minimum area ratio [Default=0.0]") processing_options.add_argument("--ipc", "--interpanelcrop", type=int, dest="interpanelcrop", default="0", diff --git a/kindlecomicconverter/image.py b/kindlecomicconverter/image.py index fde911a..a99e222 100755 --- a/kindlecomicconverter/image.py +++ b/kindlecomicconverter/image.py @@ -390,6 +390,11 @@ class ComicPage: return Image.Resampling.LANCZOS def maybeCrop(self, box, minimum): + w, h = self.image.size + left, upper, right, lower = box + if self.opt.preservemargin: + ratio = 1 - self.opt.preservemargin / 100 + box = left * ratio, upper * ratio, right + (w - right) * (1 - ratio), lower + (h - lower) * (1 - ratio) box_area = (box[2] - box[0]) * (box[3] - box[1]) image_area = self.image.size[0] * self.image.size[1] if (box_area / image_area) >= minimum: