1
0
mirror of https://github.com/ciromattia/kcc synced 2026-04-25 02:19:00 +00:00

Compare commits

..

11 Commits
kfx ... master

Author SHA1 Message Date
Alex Xu
d5dde46989 CBZ defaults to partially checked w/b borders (#1310) 2026-04-24 16:40:44 -07:00
Alex Xu
92c85c18e9 rename autocontrast box to custom autocontrast (#1308) 2026-04-24 12:11:38 -07:00
Alex Xu
e5122cc188 prevent creating non Kindle MOBI (#1307) 2026-04-24 07:44:56 -07:00
Alex Xu
61be6aa78e bump to 10.0.1 2026-04-23 14:56:04 -07:00
フィルターペーパー
d6834063c1 avoid orphan dir in tempdir and fix disk size check with tempdir (#1302)
* Use tempdir option for fusion path

* Update makeFusion to use the same temporary directory location
* Avoid creating an orphan "KCC-" in TMPDIR when --tempdir is set

* Ensure disk space check follows --tempdir setting

* revert some things

* revert some things
2026-04-23 14:53:45 -07:00
Alex Xu
1a8d74de4a fix webtoon smartcover (#1305) 2026-04-23 13:36:49 -07:00
Alex Xu
a0a194ecf1 bump to 10.0.0 2026-04-22 18:01:43 -07:00
Alex Xu
290578d66e enable upscale box for webtoon and scribe 2026-04-22 17:58:40 -07:00
Alex Xu
f97398d481 remove getTopMargin from EPUBs 2026-04-22 17:58:40 -07:00
Alex Xu
a7a9f35686 Update README.md 2026-04-19 10:27:52 -07:00
Alex Xu
d5146d02fc Update README.md 2026-04-19 10:10:18 -07:00
6 changed files with 43 additions and 37 deletions

View File

@@ -11,7 +11,7 @@
like Kindle, Kobo, ReMarkable, and more. like Kindle, Kobo, ReMarkable, and more.
Pages display in fullscreen without margins, Pages display in fullscreen without margins,
with proper fixed layout support. with proper fixed layout support.
Supported input formats include JPG/PNG image files in folders, archives, or PDFs. Supported input formats include JPG/PNG image files in folders, archives like CBZ, or PDFs.
Supported output formats include MOBI/AZW3, EPUB, KEPUB, CBZ, and PDF. Supported output formats include MOBI/AZW3, EPUB, KEPUB, CBZ, and PDF.
KCC runs on Windows, macOS, and Linux. KCC runs on Windows, macOS, and Linux.
@@ -115,15 +115,14 @@ For flatpak, Docker, and AppImage versions, refer to the wiki: https://github.co
## FAQ ## FAQ
- Should I use Calibre? - Should I use Calibre?
- No. Calibre doesn't properly support fixed layout EPUB/MOBI, so modifying KCC output (even just metadata!) in Calibre can break the formatting. - No. Calibre doesn't properly support fixed layout EPUB/MOBI, so modifying KCC output (even just metadata!) in Calibre can break the formatting.
Additionally, it will break page numbers.
Viewing KCC output in Calibre will also not work properly. Viewing KCC output in Calibre will also not work properly.
On 7th gen and later Kindles running firmware 5.15.1+, you can get cover thumbnails simply by USB dropping into documents folder. Direct USB dropping is reccomended.
On 6th gen and older, you can get cover thumbnails by keeping Kindle plugged in during conversion.
If you are careful to not modify the file however, you can still use Calibre, but direct USB dropping is reccomended.
- Blank pages? - Blank pages?
- May happen when [using PNG with Kindle Scribe](https://github.com/ciromattia/kcc/issues/665) or [any format with a Kindle Colorsoft](https://github.com/ciromattia/kcc/issues/768). Solve by using JPG with Kindle Scribe or buying a Kobo Colour. Happens more often when turning pages really fast. - May happen when [using PNG with Kindle Scribe](https://github.com/ciromattia/kcc/issues/665) or [any format with a Kindle Colorsoft](https://github.com/ciromattia/kcc/issues/768). Solve by using JPG with Kindle Scribe or buying a Kobo Colour. Happens more often when turning pages really fast. You can try PDF output.
Going back a few pages and exiting and re-entering book should fix it temporarily. Going back a few pages and exiting and re-entering book should fix it temporarily.
- What output format should I use? - What output format should I use?
- MOBI for Kindles. CBZ for Kindle DX. CBZ for Koreader. KEPUB for Kobo. PDF for ReMarkable. - MOBI for Kindles. CBZ for Kindle DX. CBZ for Koreader. KEPUB for Kobo. PDF for ReMarkable or Kindle Scribe 2025.
- All options have additional information in tooltips if you hover over the option. - All options have additional information in tooltips if you hover over the option.
- To get the converted book onto your Kindle/Kobo, just drag and drop the mobi/kepub into the documents folder on your Kindle/Kobo via USB - To get the converted book onto your Kindle/Kobo, just drag and drop the mobi/kepub into the documents folder on your Kindle/Kobo via USB
- Kindle panel view not working? - Kindle panel view not working?
@@ -137,9 +136,6 @@ For flatpak, Docker, and AppImage versions, refer to the wiki: https://github.co
(no login required). Works much better than previously recommended Android File Transfer. Cannot run simutaneously with other transfer apps. (no login required). Works much better than previously recommended Android File Transfer. Cannot run simutaneously with other transfer apps.
- How to make AZW3 instead of MOBI? - How to make AZW3 instead of MOBI?
- The `.mobi` file generated by KCC is a dual filetype, it's both MOBI and AZW3. The file extension is `.mobi` for compatibility reasons. - The `.mobi` file generated by KCC is a dual filetype, it's both MOBI and AZW3. The file extension is `.mobi` for compatibility reasons.
- [Windows 7 support](https://github.com/ciromattia/kcc/issues/678)
- Image too dark?
- The default gamma correction of 1.8 makes the image darker, and is useful for faded/gray artwork/text. Disable by setting gamma = 1.0
- Huge margins / slow page turns? - Huge margins / slow page turns?
- You likely modified the file during transfer using a 3rd party app. Try simply dragging and dropping the final mobi/kepub file into the Kindle documents folder via USB. - You likely modified the file during transfer using a 3rd party app. Try simply dragging and dropping the final mobi/kepub file into the Kindle documents folder via USB.
@@ -198,8 +194,9 @@ sudo apt-get install python3 p7zip-full python3-pil python3-psutil python3-slugi
'KV': ("Kindle Voyage", (1072, 1448), Palette16, 1.0), 'KV': ("Kindle Voyage", (1072, 1448), Palette16, 1.0),
'KPW34': ("Kindle Paperwhite 3/4", (1072, 1448), Palette16, 1.0), 'KPW34': ("Kindle Paperwhite 3/4", (1072, 1448), Palette16, 1.0),
'KPW5': ("Kindle Paperwhite 5/Signature Edition", (1236, 1648), Palette16, 1.0), 'KPW5': ("Kindle Paperwhite 5/Signature Edition", (1236, 1648), Palette16, 1.0),
'KO': ("Kindle Oasis 2/3/Paperwhite 12", (1264, 1680), Palette16, 1.0), 'KPW6': ("Kindle Paperwhite 6", (1272, 1696), Palette16, 1.0),
'KCS': ("Kindle Colorsoft", (1264, 1680), Palette16, 1.0), 'KO': ("Kindle Oasis 2/3", (1264, 1680), Palette16, 1.0),
'KCS': ("Kindle Colorsoft", (1272, 1696), Palette16, 1.0),
'KS1860': ("Kindle 1860", (1860, 1920), Palette16, 1.0), 'KS1860': ("Kindle 1860", (1860, 1920), Palette16, 1.0),
'KS1920': ("Kindle 1920", (1920, 1920), Palette16, 1.0), 'KS1920': ("Kindle 1920", (1920, 1920), Palette16, 1.0),
'KS': ("Kindle Scribe 1/2", (1860, 2480), Palette16, 1.0), 'KS': ("Kindle Scribe 1/2", (1860, 2480), Palette16, 1.0),

View File

@@ -866,7 +866,7 @@ Useful if you plan to crop a little off the top and bottom to fill screen.</stri
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - BW only&lt;br/&gt;&lt;/span&gt;Only autocontrast bw pages. Ignored for pages where near blacks or whites don't exist.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Disabled&lt;br/&gt;&lt;/span&gt;Disable autocontrast&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - BW and Color&lt;br/&gt;&lt;/span&gt;BW and color images will be autocontrasted. Ignored for pages where near blacks or whites don't exist.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> <string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Unchecked - BW only&lt;br/&gt;&lt;/span&gt;Only autocontrast bw pages. Ignored for pages where near blacks or whites don't exist.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Indeterminate - Disabled&lt;br/&gt;&lt;/span&gt;Disable autocontrast&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:600; text-decoration: underline;&quot;&gt;Checked - BW and Color&lt;br/&gt;&lt;/span&gt;BW and color images will be autocontrasted. Ignored for pages where near blacks or whites don't exist.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Autocontrast</string> <string>Custom Autocontrast</string>
</property> </property>
<property name="tristate"> <property name="tristate">
<bool>true</bool> <bool>true</bool>

View File

@@ -795,8 +795,8 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
GUI.rotateBox.setChecked(False) GUI.rotateBox.setChecked(False)
GUI.borderBox.setEnabled(False) GUI.borderBox.setEnabled(False)
GUI.borderBox.setCheckState(Qt.CheckState.PartiallyChecked) GUI.borderBox.setCheckState(Qt.CheckState.PartiallyChecked)
GUI.upscaleBox.setEnabled(False) # GUI.upscaleBox.setEnabled(False)
GUI.upscaleBox.setChecked(False) # GUI.upscaleBox.setChecked(False)
GUI.croppingBox.setEnabled(False) GUI.croppingBox.setEnabled(False)
GUI.croppingBox.setChecked(False) GUI.croppingBox.setChecked(False)
GUI.interPanelCropBox.setEnabled(False) GUI.interPanelCropBox.setEnabled(False)
@@ -813,7 +813,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
GUI.rotateBox.setEnabled(True) GUI.rotateBox.setEnabled(True)
GUI.borderBox.setEnabled(True) GUI.borderBox.setEnabled(True)
profile = GUI.profiles[str(GUI.deviceBox.currentText())] profile = GUI.profiles[str(GUI.deviceBox.currentText())]
if not profile['Label'].startswith('KS'): if not profile['Label'].startswith('KS') or True:
GUI.upscaleBox.setEnabled(True) GUI.upscaleBox.setEnabled(True)
GUI.croppingBox.setEnabled(True) GUI.croppingBox.setEnabled(True)
GUI.interPanelCropBox.setEnabled(True) GUI.interPanelCropBox.setEnabled(True)
@@ -908,10 +908,10 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
if not GUI.webtoonBox.isChecked(): if not GUI.webtoonBox.isChecked():
GUI.qualityBox.setEnabled(profile['PVOptions']) GUI.qualityBox.setEnabled(profile['PVOptions'])
GUI.upscaleBox.setChecked(profile['DefaultUpscale']) GUI.upscaleBox.setChecked(profile['DefaultUpscale'])
if profile['Label'].startswith('KS'): if profile['Label'].startswith('KS') and False:
GUI.upscaleBox.setDisabled(True) GUI.upscaleBox.setDisabled(True)
else: else:
if not GUI.webtoonBox.isChecked(): if not GUI.webtoonBox.isChecked() or True:
GUI.upscaleBox.setEnabled(True) GUI.upscaleBox.setEnabled(True)
if profile['Label'] == 'KCS': if profile['Label'] == 'KCS':
current_format = GUI.formats[str(GUI.formatBox.currentText())]['format'] current_format = GUI.formats[str(GUI.formatBox.currentText())]['format']
@@ -950,6 +950,9 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
GUI.chunkSizeCheckBox.setEnabled(True) GUI.chunkSizeCheckBox.setEnabled(True)
if GUI.formats[str(GUI.formatBox.currentText())]['format'] in ('CBZ', 'PDF') and not GUI.webtoonBox.isChecked(): if GUI.formats[str(GUI.formatBox.currentText())]['format'] in ('CBZ', 'PDF') and not GUI.webtoonBox.isChecked():
self.addMessage("Partially check W/B Margins if you don't want KCC to extend the image margins.", 'info') self.addMessage("Partially check W/B Margins if you don't want KCC to extend the image margins.", 'info')
GUI.borderBox.setCheckState(Qt.CheckState.PartiallyChecked)
else:
GUI.borderBox.setCheckState(Qt.CheckState.Unchecked)
def stripTags(self, html): def stripTags(self, html):
s = HTMLStripper() s = HTMLStripper()

View File

@@ -819,7 +819,7 @@ class Ui_mainWindow(object):
#if QT_CONFIG(tooltip) #if QT_CONFIG(tooltip)
self.autocontrastBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - BW only<br/></span>Only autocontrast bw pages. Ignored for pages where near blacks or whites don't exist.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Disabled<br/></span>Disable autocontrast</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - BW and Color<br/></span>BW and color images will be autocontrasted. Ignored for pages where near blacks or whites don't exist.</p></body></html>", None)) self.autocontrastBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - BW only<br/></span>Only autocontrast bw pages. Ignored for pages where near blacks or whites don't exist.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - Disabled<br/></span>Disable autocontrast</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - BW and Color<br/></span>BW and color images will be autocontrasted. Ignored for pages where near blacks or whites don't exist.</p></body></html>", None))
#endif // QT_CONFIG(tooltip) #endif // QT_CONFIG(tooltip)
self.autocontrastBox.setText(QCoreApplication.translate("mainWindow", u"Autocontrast", None)) self.autocontrastBox.setText(QCoreApplication.translate("mainWindow", u"Custom Autocontrast", None))
#if QT_CONFIG(tooltip) #if QT_CONFIG(tooltip)
self.webpBox.setToolTip(QCoreApplication.translate("mainWindow", u"Replace JPG with lossy WebP and PNG with lossless WebP. This includes the JPG Quality.\n" self.webpBox.setToolTip(QCoreApplication.translate("mainWindow", u"Replace JPG with lossy WebP and PNG with lossless WebP. This includes the JPG Quality.\n"
"\n" "\n"

View File

@@ -1,4 +1,4 @@
__version__ = '9.7.2' __version__ = '10.0.1'
__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'

View File

@@ -136,14 +136,14 @@ def buildHTML(path, imgfile, imgfilepath, imgfile2=None):
"content=\"width=" + str(imgsizeframe[0]) + ", height=" + str(imgsizeframe[1]) + "\"/>\n" "content=\"width=" + str(imgsizeframe[0]) + ", height=" + str(imgsizeframe[1]) + "\"/>\n"
"</head>\n", "</head>\n",
"<body style=\"" + additionalStyle + "\">\n", "<body style=\"" + additionalStyle + "\">\n",
"<div style=\"text-align:center;top:" + getTopMargin(deviceres, imgsizeframe) + "%;\">\n", "<div style=\"text-align:center;\">\n",
]) ])
if options.iskindle: if options.iskindle:
# this display none div fixes formatting issues with virtual panel mode, for some reason # this display none div fixes formatting issues with virtual panel mode, for some reason
f.write('<div style="display:none;">.</div>\n') f.write('<div style="display:none;">.</div>\n')
f.write(f'<img width="{imgsize[0]}" height="{imgsize[1]}" src="{"../" * backref}Images/{postfix}{imgfile}"/>\n') f.write(f'<img width="{imgsize[0]}" height="{imgsize[1]}" src="{"../" * backref}Images/{postfix}{imgfile}"/>\n')
if imgfile2: if imgfile2:
f.write(f'<img width="{imgsize2[0]}" height="{imgsize2[1]}" src="{"../" * backref}Images/{postfix}{imgfile2}"/>\n') f.write(f'<img style="bottom: 0" width="{imgsize2[0]}" height="{imgsize2[1]}" src="{"../" * backref}Images/{postfix}{imgfile2}"/>\n')
f.write("</div>\n") f.write("</div>\n")
if options.iskindle and options.panelview: if options.iskindle and options.panelview:
if options.autoscale: if options.autoscale:
@@ -324,8 +324,8 @@ def buildOPF(dstdir, title, filelist, originalpath, cover=None):
f.write("<meta name=\"cover\" content=\"cover\"/>\n") f.write("<meta name=\"cover\" content=\"cover\"/>\n")
if options.iskindle and options.profile != 'Custom': if options.iskindle and options.profile != 'Custom':
f.writelines(["<meta name=\"fixed-layout\" content=\"true\"/>\n", f.writelines(["<meta name=\"fixed-layout\" content=\"true\"/>\n",
# "<meta name=\"original-resolution\" content=\"", "<meta name=\"original-resolution\" content=\"",
# str(deviceres[0]) + "x" + str(deviceres[1]) + "\"/>\n", str(deviceres[0]) + "x" + str(deviceres[1]) + "\"/>\n",
"<meta name=\"book-type\" content=\"comic\"/>\n", "<meta name=\"book-type\" content=\"comic\"/>\n",
"<meta name=\"primary-writing-mode\" content=\"" + writingmode + "\"/>\n", "<meta name=\"primary-writing-mode\" content=\"" + writingmode + "\"/>\n",
"<meta name=\"zero-gutter\" content=\"true\"/>\n", "<meta name=\"zero-gutter\" content=\"true\"/>\n",
@@ -873,14 +873,18 @@ def mupdf_pdf_process_pages_parallel(filename, output_dir, target_width, target_
def getWorkFolder(afile, workdir=None): def getWorkFolder(afile, workdir=None):
if not workdir: if not workdir:
workdir = mkdtemp('', 'KCC-')
if options.tempdir: if options.tempdir:
workdir = mkdtemp('', 'KCC-', os.path.dirname(afile)) workdir = mkdtemp('', 'KCC-', os.path.dirname(afile))
else:
workdir = mkdtemp('', 'KCC-')
fullPath = os.path.join(workdir, 'OEBPS', 'Images') fullPath = os.path.join(workdir, 'OEBPS', 'Images')
else: else:
fullPath = workdir fullPath = workdir
check_path = gettempdir()
if options.tempdir:
check_path = os.path.dirname(afile)
if os.path.isdir(afile): if os.path.isdir(afile):
if disk_usage(gettempdir())[2] < getDirectorySize(afile) * 2.5: if disk_usage(check_path)[2] < getDirectorySize(afile) * 2.5:
raise UserWarning("Not enough disk space to perform conversion.") raise UserWarning("Not enough disk space to perform conversion.")
try: try:
copytree(afile, fullPath) copytree(afile, fullPath)
@@ -890,7 +894,7 @@ def getWorkFolder(afile, workdir=None):
rmtree(workdir, True) rmtree(workdir, True)
raise UserWarning("Failed to prepare a workspace.") raise UserWarning("Failed to prepare a workspace.")
elif os.path.isfile(afile): elif os.path.isfile(afile):
if disk_usage(gettempdir())[2] < os.path.getsize(afile) * 2.5: if disk_usage(check_path)[2]< os.path.getsize(afile) * 2.5:
raise UserWarning("Not enough disk space to perform conversion.") raise UserWarning("Not enough disk space to perform conversion.")
if afile.lower().endswith('.pdf'): if afile.lower().endswith('.pdf'):
if not os.path.exists(fullPath): if not os.path.exists(fullPath):
@@ -1075,11 +1079,6 @@ def getDirectorySize(start_path='.'):
return total_size return total_size
def getTopMargin(deviceres, size):
y = int((deviceres[1] - size[1]) / 2) / deviceres[1] * 100
return str(round(y, 1))
def getPanelViewResolution(imagesize, deviceres): def getPanelViewResolution(imagesize, deviceres):
scale = float(deviceres[0]) / float(imagesize[0]) scale = float(deviceres[0]) / float(imagesize[0])
return int(deviceres[0]), int(scale * imagesize[1]) return int(deviceres[0]), int(scale * imagesize[1])
@@ -1471,6 +1470,15 @@ def checkOptions(options):
options.isKobo = False options.isKobo = False
options.bordersColor = None options.bordersColor = None
options.keep_epub = False options.keep_epub = False
if options.profile in image.ProfileData.ProfilesKindle.keys():
options.iskindle = True
else:
options.isKobo = True
if not options.iskindle and ('MOBI' in options.format or 'EPUB-200MB' in options.format):
raise UserWarning('MOBI/EPUB-200MB not supported for non-Kindle profiles')
if options.format == 'PDF-200MB': if options.format == 'PDF-200MB':
options.targetsize = 195 options.targetsize = 195
options.format = 'PDF' options.format = 'PDF'
@@ -1502,10 +1510,7 @@ def checkOptions(options):
options.format = 'PDF' options.format = 'PDF'
else: else:
options.format = 'EPUB' options.format = 'EPUB'
if options.profile in image.ProfileData.ProfilesKindle.keys():
options.iskindle = True
else:
options.isKobo = True
if options.white_borders: if options.white_borders:
options.bordersColor = 'white' options.bordersColor = 'white'
if options.black_borders: if options.black_borders:
@@ -1557,6 +1562,7 @@ def checkOptions(options):
options.jpegquality = 90 options.jpegquality = 90
else: else:
options.jpegquality = 85 options.jpegquality = 85
options.kindle_azw3 = options.iskindle and ('MOBI' in options.format or 'EPUB' in options.format) options.kindle_azw3 = options.iskindle and ('MOBI' in options.format or 'EPUB' in options.format)
options.kindle_scribe_azw3 = options.profile.startswith('KS') and options.kindle_azw3 options.kindle_scribe_azw3 = options.profile.startswith('KS') and options.kindle_azw3
@@ -1715,7 +1721,7 @@ def makeBook(source, qtgui=None, job_progress=''):
filepath.append(getOutputFilename(source, options.output, '.cbz', ' ' + str(tomeNumber))) filepath.append(getOutputFilename(source, options.output, '.cbz', ' ' + str(tomeNumber)))
else: else:
filepath.append(getOutputFilename(source, options.output, '.cbz', '')) filepath.append(getOutputFilename(source, options.output, '.cbz', ''))
if cover.smartcover: if cover and cover.smartcover:
cover.save_to_folder(os.path.join(tome, 'OEBPS', 'Images', 'cover.jpg'), tomeNumber, len(tomes)) 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) makeZIP(tome + '_comic', os.path.join(tome, "OEBPS", "Images"), job_progress)
elif options.format == 'PDF': elif options.format == 'PDF':
@@ -1723,7 +1729,7 @@ def makeBook(source, qtgui=None, job_progress=''):
# determine output filename based on source and tome count # determine output filename based on source and tome count
suffix = (' ' + str(tomeNumber)) if len(tomes) > 1 else '' suffix = (' ' + str(tomeNumber)) if len(tomes) > 1 else ''
output_file = getOutputFilename(source, options.output, '.pdf', suffix) output_file = getOutputFilename(source, options.output, '.pdf', suffix)
if cover.smartcover: if cover and cover.smartcover:
cover.save_to_folder(os.path.join(tome, 'OEBPS', 'Images', 'cover.jpg'), tomeNumber, len(tomes)) cover.save_to_folder(os.path.join(tome, 'OEBPS', 'Images', 'cover.jpg'), tomeNumber, len(tomes))
# use optimized buildPDF logic with streaming and compression # use optimized buildPDF logic with streaming and compression
output_pdf = buildPDF(tome, options.title, job_progress, None, output_file) output_pdf = buildPDF(tome, options.title, job_progress, None, output_file)