mirror of
https://github.com/ciromattia/kcc
synced 2026-04-17 14:38:47 +00:00
smart cover crop is default on and implemented for all formats (#1295)
This commit is contained in:
@@ -270,7 +270,7 @@ PROCESSING:
|
||||
Crop empty sections. 0: Disabled 1: Horizontally 2: Both [Default=0]
|
||||
--blackborders Disable autodetection and force black borders
|
||||
--whiteborders Disable autodetection and force white borders
|
||||
--smartcovercrop Attempt to crop main cover from wide image
|
||||
--nosmartcovercrop Disable attempt to crop main cover from wide image
|
||||
--coverfill Center-crop only the cover to fill target device screen
|
||||
--forcecolor Don't convert images to grayscale
|
||||
--forcepng Create PNG files instead JPEG for black and white images
|
||||
|
||||
@@ -655,12 +655,12 @@ Higher values are larger and higher quality, and may resolve blank page issues.<
|
||||
</widget>
|
||||
</item>
|
||||
<item row="11" column="1">
|
||||
<widget class="QCheckBox" name="smartCoverCropBox">
|
||||
<widget class="QCheckBox" name="noSmartCoverCropBox">
|
||||
<property name="toolTip">
|
||||
<string>Attempt to crop main cover from wide image.</string>
|
||||
<string>Disable attempt to crop main cover from wide image.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Smart Cover Crop</string>
|
||||
<string>No Smart Cover Crop</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
@@ -331,8 +331,8 @@ class WorkerThread(QThread):
|
||||
options.pdfextract = True
|
||||
if GUI.pdfWidthBox.isChecked():
|
||||
options.pdfwidth = True
|
||||
if GUI.smartCoverCropBox.isChecked():
|
||||
options.smartcovercrop = True
|
||||
if GUI.noSmartCoverCropBox.isChecked():
|
||||
options.nosmartcovercrop = True
|
||||
if GUI.coverFillBox.isChecked():
|
||||
options.coverfill = True
|
||||
if GUI.metadataTitleBox.checkState() == Qt.CheckState.PartiallyChecked:
|
||||
@@ -1077,7 +1077,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
||||
'disableProcessingBox': GUI.disableProcessingBox.checkState(),
|
||||
'pdfExtractBox': GUI.pdfExtractBox.checkState(),
|
||||
'pdfWidthBox': GUI.pdfWidthBox.checkState(),
|
||||
'smartCoverCropBox': GUI.smartCoverCropBox.checkState(),
|
||||
'noSmartCoverCropBox': GUI.noSmartCoverCropBox.checkState(),
|
||||
'coverFillBox': GUI.coverFillBox.checkState(),
|
||||
'metadataTitleBox': GUI.metadataTitleBox.checkState(),
|
||||
'mozJpegBox': GUI.mozJpegBox.checkState(),
|
||||
|
||||
@@ -344,10 +344,10 @@ class Ui_mainWindow(object):
|
||||
|
||||
self.gridLayout_2.addWidget(self.metadataTitleBox, 7, 0, 1, 1)
|
||||
|
||||
self.smartCoverCropBox = QCheckBox(self.optionWidget)
|
||||
self.smartCoverCropBox.setObjectName(u"smartCoverCropBox")
|
||||
self.noSmartCoverCropBox = QCheckBox(self.optionWidget)
|
||||
self.noSmartCoverCropBox.setObjectName(u"noSmartCoverCropBox")
|
||||
|
||||
self.gridLayout_2.addWidget(self.smartCoverCropBox, 11, 1, 1, 1)
|
||||
self.gridLayout_2.addWidget(self.noSmartCoverCropBox, 11, 1, 1, 1)
|
||||
|
||||
self.rotateFirstBox = QCheckBox(self.optionWidget)
|
||||
self.rotateFirstBox.setObjectName(u"rotateFirstBox")
|
||||
@@ -748,9 +748,9 @@ class Ui_mainWindow(object):
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
self.metadataTitleBox.setText(QCoreApplication.translate("mainWindow", u"Metadata Title", None))
|
||||
#if QT_CONFIG(tooltip)
|
||||
self.smartCoverCropBox.setToolTip(QCoreApplication.translate("mainWindow", u"Attempt to crop main cover from wide image.", None))
|
||||
self.noSmartCoverCropBox.setToolTip(QCoreApplication.translate("mainWindow", u"Disable attempt to crop main cover from wide image.", None))
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
self.smartCoverCropBox.setText(QCoreApplication.translate("mainWindow", u"Smart Cover Crop", None))
|
||||
self.noSmartCoverCropBox.setText(QCoreApplication.translate("mainWindow", u"No Smart Cover Crop", None))
|
||||
#if QT_CONFIG(tooltip)
|
||||
self.rotateFirstBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p>When the spread splitter option is partially checked,</p><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - Rotate Last<br/></span>Put the rotated 2 page spread after the split spreads.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - Rotate First<br/></span>Put the rotated 2 page spread before the split spreads.</p></body></html>", None))
|
||||
#endif // QT_CONFIG(tooltip)
|
||||
|
||||
@@ -556,7 +556,7 @@ def buildEPUB(path, chapternames, tomenumber, ischunked, cover: image.Cover, ori
|
||||
f.close()
|
||||
build_html_start = perf_counter()
|
||||
if cover:
|
||||
cover.save_to_epub(os.path.join(path, 'OEBPS', 'Images', 'cover.jpg'), tomenumber, len_tomes)
|
||||
cover.save_to_folder(os.path.join(path, 'OEBPS', 'Images', 'cover.jpg'), tomenumber, len_tomes)
|
||||
dot_clean(path)
|
||||
options.covers.append((cover, options.uuid))
|
||||
for dirpath, dirnames, filenames in os.walk(os.path.join(path, 'OEBPS', 'Images')):
|
||||
@@ -1394,8 +1394,8 @@ def makeParser():
|
||||
help="Use the legacy PDF image extraction method from KCC 8 and earlier")
|
||||
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,
|
||||
help="Attempt to crop main cover from wide image")
|
||||
processing_options.add_argument("--nosmartcovercrop", action="store_true", dest="nosmartcovercrop", default=False,
|
||||
help="Disable attempt to crop main cover from wide image")
|
||||
processing_options.add_argument("--coverfill", action="store_true", dest="coverfill", default=False,
|
||||
help="Crop cover to fill screen")
|
||||
processing_options.add_argument("-u", "--upscale", action="store_true", dest="upscale", default=False,
|
||||
@@ -1712,12 +1712,16 @@ def makeBook(source, qtgui=None, job_progress=''):
|
||||
filepath.append(getOutputFilename(source, options.output, '.cbz', ' ' + str(tomeNumber)))
|
||||
else:
|
||||
filepath.append(getOutputFilename(source, options.output, '.cbz', ''))
|
||||
if cover.smartcover:
|
||||
cover.save_to_folder(os.path.join(tome, 'OEBPS', 'Images', 'cover.jpg'), tomeNumber, len(tomes))
|
||||
makeZIP(tome + '_comic', os.path.join(tome, "OEBPS", "Images"), job_progress)
|
||||
elif options.format == 'PDF':
|
||||
print(f"{job_progress}Creating PDF file with PyMuPDF...")
|
||||
# determine output filename based on source and tome count
|
||||
suffix = (' ' + str(tomeNumber)) if len(tomes) > 1 else ''
|
||||
output_file = getOutputFilename(source, options.output, '.pdf', suffix)
|
||||
if cover.smartcover:
|
||||
cover.save_to_folder(os.path.join(tome, 'OEBPS', 'Images', 'cover.jpg'), tomeNumber, len(tomes))
|
||||
# use optimized buildPDF logic with streaming and compression
|
||||
output_pdf = buildPDF(tome, options.title, job_progress, None, output_file)
|
||||
filepath.append(output_pdf)
|
||||
|
||||
@@ -569,6 +569,7 @@ class Cover:
|
||||
self.options = opt
|
||||
self.source = source
|
||||
self.image = Image.open(source)
|
||||
self.smartcover = False
|
||||
# backwards compatibility for Pillow >9.1.0
|
||||
if not hasattr(Image, 'Resampling'):
|
||||
Image.Resampling = Image
|
||||
@@ -579,7 +580,7 @@ class Cover:
|
||||
self.image = ImageOps.autocontrast(self.image, preserve_tone=True)
|
||||
if not self.options.forcecolor:
|
||||
self.image = self.image.convert('L')
|
||||
if self.options.smartcovercrop:
|
||||
if not self.options.nosmartcovercrop:
|
||||
self.crop_main_cover()
|
||||
|
||||
size = list(self.options.profileData[1])
|
||||
@@ -595,17 +596,19 @@ class Cover:
|
||||
def crop_main_cover(self):
|
||||
w, h = self.image.size
|
||||
if w / h > 2:
|
||||
self.smartcover = True
|
||||
if self.options.righttoleft:
|
||||
self.image = self.image.crop((w/6, 0, w/2 - w * 0.02, h))
|
||||
else:
|
||||
self.image = self.image.crop((w/2 + w * 0.02, 0, 5/6 * w, h))
|
||||
elif w / h > 1.34:
|
||||
self.smartcover = True
|
||||
if self.options.righttoleft:
|
||||
self.image = self.image.crop((0, 0, w/2 - w * 0.03, h))
|
||||
else:
|
||||
self.image = self.image.crop((w/2 + w * 0.03, 0, w, h))
|
||||
|
||||
def save_to_epub(self, target, tomeid, len_tomes=0):
|
||||
def save_to_folder(self, target, tomeid, len_tomes=0):
|
||||
try:
|
||||
if tomeid == 0:
|
||||
self.image.save(target, "JPEG", optimize=1, quality=self.options.jpegquality)
|
||||
|
||||
Reference in New Issue
Block a user