mirror of
https://github.com/ciromattia/kcc
synced 2025-12-15 18:56:28 +00:00
Merge pull request #1071 from axu2/pdf-metadata
PDF input/output Metadata support
This commit is contained in:
@@ -256,7 +256,7 @@ OUTPUT SETTINGS:
|
|||||||
Output generated file to specified directory or file
|
Output generated file to specified directory or file
|
||||||
-t TITLE, --title TITLE
|
-t TITLE, --title TITLE
|
||||||
Comic title [Default=filename or directory name]
|
Comic title [Default=filename or directory name]
|
||||||
--comicinfotitle Write title from ComicInfo.xml
|
--metadatatitle Write title from ComicInfo.xml or other embedded metadata
|
||||||
-a AUTHOR, --author AUTHOR
|
-a AUTHOR, --author AUTHOR
|
||||||
Author name [Default=KCC]
|
Author name [Default=KCC]
|
||||||
-f FORMAT, --format FORMAT
|
-f FORMAT, --format FORMAT
|
||||||
|
|||||||
@@ -585,12 +585,12 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="7" column="0">
|
<item row="7" column="0">
|
||||||
<widget class="QCheckBox" name="comicinfoTitleBox">
|
<widget class="QCheckBox" name="metadataTitleBox">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>Write Title from ComicInfo.xml</string>
|
<string><html><head/><body><p>Write Title from ComicInfo.xml or other embedded metadata.</p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>ComicInfo Title</string>
|
<string>Metadata Title</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -268,8 +268,8 @@ class WorkerThread(QThread):
|
|||||||
options.maximizestrips = True
|
options.maximizestrips = True
|
||||||
if GUI.disableProcessingBox.isChecked():
|
if GUI.disableProcessingBox.isChecked():
|
||||||
options.noprocessing = True
|
options.noprocessing = True
|
||||||
if GUI.comicinfoTitleBox.isChecked():
|
if GUI.metadataTitleBox.isChecked():
|
||||||
options.comicinfotitle = True
|
options.metadatatitle = True
|
||||||
if GUI.deleteBox.isChecked():
|
if GUI.deleteBox.isChecked():
|
||||||
options.delete = True
|
options.delete = True
|
||||||
if GUI.spreadShiftBox.isChecked():
|
if GUI.spreadShiftBox.isChecked():
|
||||||
@@ -882,7 +882,7 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
'colorBox': GUI.colorBox.checkState().value,
|
'colorBox': GUI.colorBox.checkState().value,
|
||||||
'eraseRainbowBox': GUI.eraseRainbowBox.checkState().value,
|
'eraseRainbowBox': GUI.eraseRainbowBox.checkState().value,
|
||||||
'disableProcessingBox': GUI.disableProcessingBox.checkState().value,
|
'disableProcessingBox': GUI.disableProcessingBox.checkState().value,
|
||||||
'comicinfoTitleBox': GUI.comicinfoTitleBox.checkState().value,
|
'metadataTitleBox': GUI.metadataTitleBox.checkState().value,
|
||||||
'mozJpegBox': GUI.mozJpegBox.checkState().value,
|
'mozJpegBox': GUI.mozJpegBox.checkState().value,
|
||||||
'widthBox': GUI.widthBox.value(),
|
'widthBox': GUI.widthBox.value(),
|
||||||
'heightBox': GUI.heightBox.value(),
|
'heightBox': GUI.heightBox.value(),
|
||||||
|
|||||||
@@ -12198,53 +12198,53 @@ qt_resource_struct = b"\
|
|||||||
\x00\x00\x00X\x00\x02\x00\x00\x00\x04\x00\x00\x00\x07\
|
\x00\x00\x00X\x00\x02\x00\x00\x00\x04\x00\x00\x00\x07\
|
||||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||||
\x00\x00\x01\xe4\x00\x00\x00\x00\x00\x01\x00\x02S.\
|
\x00\x00\x01\xe4\x00\x00\x00\x00\x00\x01\x00\x02S.\
|
||||||
\x00\x00\x01\x88;p\xbcB\
|
\x00\x00\x01\x97\x0a\xfc2A\
|
||||||
\x00\x00\x02\x22\x00\x00\x00\x00\x00\x01\x00\x02\xa7\xc8\
|
\x00\x00\x02\x22\x00\x00\x00\x00\x00\x01\x00\x02\xa7\xc8\
|
||||||
\x00\x00\x01\x88;p\xbcB\
|
\x00\x00\x01\x97\x0a\xfc2@\
|
||||||
\x00\x00\x02\x0e\x00\x00\x00\x00\x00\x01\x00\x02}\xcd\
|
\x00\x00\x02\x0e\x00\x00\x00\x00\x00\x01\x00\x02}\xcd\
|
||||||
\x00\x00\x01\x88;p\xbcB\
|
\x00\x00\x01\x97\x0a\xfc2@\
|
||||||
\x00\x00\x01\xfa\x00\x00\x00\x00\x00\x01\x00\x02rj\
|
\x00\x00\x01\xfa\x00\x00\x00\x00\x00\x01\x00\x02rj\
|
||||||
\x00\x00\x01\x89\x89D9.\
|
\x00\x00\x01\x97\x0a\xfc2@\
|
||||||
\x00\x00\x00X\x00\x02\x00\x00\x00\x04\x00\x00\x00\x0c\
|
\x00\x00\x00X\x00\x02\x00\x00\x00\x04\x00\x00\x00\x0c\
|
||||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||||
\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x01(\x97\
|
\x00\x00\x00\xa6\x00\x00\x00\x00\x00\x01\x00\x01(\x97\
|
||||||
\x00\x00\x01\x88;p\xbcB\
|
\x00\x00\x01\x97\x0a\xfc2A\
|
||||||
\x00\x00\x00\xbc\x00\x00\x00\x00\x00\x01\x00\x011\xef\
|
\x00\x00\x00\xbc\x00\x00\x00\x00\x00\x01\x00\x011\xef\
|
||||||
\x00\x00\x01\x96\x16b\x1f\x99\
|
\x00\x00\x01\x97\x0a\xfc2A\
|
||||||
\x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x01\x1d\x90\
|
\x00\x00\x00\x8c\x00\x00\x00\x00\x00\x01\x00\x01\x1d\x90\
|
||||||
\x00\x00\x01\x88;p\xbcB\
|
\x00\x00\x01\x97\x0a\xfc2A\
|
||||||
\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x01\x00\x01:\x05\
|
\x00\x00\x00\xd0\x00\x00\x00\x00\x00\x01\x00\x01:\x05\
|
||||||
\x00\x00\x01\x88;p\xbcB\
|
\x00\x00\x01\x97\x0a\xfc2A\
|
||||||
\x00\x00\x00X\x00\x02\x00\x00\x00\x03\x00\x00\x00\x11\
|
\x00\x00\x00X\x00\x02\x00\x00\x00\x03\x00\x00\x00\x11\
|
||||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||||
\x00\x00\x02f\x00\x00\x00\x00\x00\x01\x00\x02\xda\x14\
|
\x00\x00\x02f\x00\x00\x00\x00\x00\x01\x00\x02\xda\x14\
|
||||||
\x00\x00\x01\x88;p\xbcJ\
|
\x00\x00\x01\x97\x0a\xfc2D\
|
||||||
\x00\x00\x028\x00\x00\x00\x00\x00\x01\x00\x02\xc4\x17\
|
\x00\x00\x028\x00\x00\x00\x00\x00\x01\x00\x02\xc4\x17\
|
||||||
\x00\x00\x01\x88;p\xbcI\
|
\x00\x00\x01\x97\x0a\xfc2D\
|
||||||
\x00\x00\x02N\x00\x00\x00\x00\x00\x01\x00\x02\xcdt\
|
\x00\x00\x02N\x00\x00\x00\x00\x00\x01\x00\x02\xcdt\
|
||||||
\x00\x00\x01\x88;p\xbcI\
|
\x00\x00\x01\x97\x0a\xfc2D\
|
||||||
\x00\x00\x00X\x00\x02\x00\x00\x00\x08\x00\x00\x00\x15\
|
\x00\x00\x00X\x00\x02\x00\x00\x00\x08\x00\x00\x00\x15\
|
||||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||||
\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x01P\xb1\
|
\x00\x00\x01\x1c\x00\x00\x00\x00\x00\x01\x00\x01P\xb1\
|
||||||
\x00\x00\x01\x88;p\xbcJ\
|
\x00\x00\x01\x97\x0a\xfc2D\
|
||||||
\x00\x00\x012\x00\x00\x00\x00\x00\x01\x00\x01yY\
|
\x00\x00\x012\x00\x00\x00\x00\x00\x01\x00\x01yY\
|
||||||
\x00\x00\x01\x97\xc9|\x88\xde\
|
\x00\x00\x01\x98\x1f\x9862\
|
||||||
\x00\x00\x01V\x00\x00\x00\x00\x00\x01\x00\x01\x9d\x9a\
|
\x00\x00\x01V\x00\x00\x00\x00\x00\x01\x00\x01\x9d\x9a\
|
||||||
\x00\x00\x01\x88;p\xbcI\
|
\x00\x00\x01\x97\x0a\xfc2D\
|
||||||
\x00\x00\x01\xb8\x00\x00\x00\x00\x00\x01\x00\x01\xf6n\
|
\x00\x00\x01\xb8\x00\x00\x00\x00\x00\x01\x00\x01\xf6n\
|
||||||
\x00\x00\x01\x94\xb4\xd4\xf0a\
|
\x00\x00\x01\x97\x0a\xfc2D\
|
||||||
\x00\x00\x01\x9e\x00\x00\x00\x00\x00\x01\x00\x01\xb1'\
|
\x00\x00\x01\x9e\x00\x00\x00\x00\x00\x01\x00\x01\xb1'\
|
||||||
\x00\x00\x01\x88;p\xbcH\
|
\x00\x00\x01\x97\x0a\xfc2C\
|
||||||
\x00\x00\x01\x04\x00\x00\x00\x00\x00\x01\x00\x01LR\
|
\x00\x00\x01\x04\x00\x00\x00\x00\x00\x01\x00\x01LR\
|
||||||
\x00\x00\x01\x88;p\xbcF\
|
\x00\x00\x01\x97\x0a\xfc2B\
|
||||||
\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x01?\xe9\
|
\x00\x00\x00\xe8\x00\x00\x00\x00\x00\x01\x00\x01?\xe9\
|
||||||
\x00\x00\x01\x88;p\xbcH\
|
\x00\x00\x01\x97\x0a\xfc2C\
|
||||||
\x00\x00\x01x\x00\x00\x00\x00\x00\x01\x00\x01\xa6\xf1\
|
\x00\x00\x01x\x00\x00\x00\x00\x00\x01\x00\x01\xa6\xf1\
|
||||||
\x00\x00\x01\x88;p\xbcH\
|
\x00\x00\x01\x97\x0a\xfc2C\
|
||||||
\x00\x00\x00X\x00\x02\x00\x00\x00\x01\x00\x00\x00\x1e\
|
\x00\x00\x00X\x00\x02\x00\x00\x00\x01\x00\x00\x00\x1e\
|
||||||
\x00\x00\x00\x00\x00\x00\x00\x00\
|
\x00\x00\x00\x00\x00\x00\x00\x00\
|
||||||
\x00\x00\x00h\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
\x00\x00\x00h\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
|
||||||
\x00\x00\x01\x88;p\xbcH\
|
\x00\x00\x01\x97\x0a\xfc2C\
|
||||||
"
|
"
|
||||||
|
|
||||||
def qInitResources():
|
def qInitResources():
|
||||||
|
|||||||
@@ -316,10 +316,10 @@ class Ui_mainWindow(object):
|
|||||||
|
|
||||||
self.gridLayout_2.addWidget(self.outputSplit, 3, 1, 1, 1)
|
self.gridLayout_2.addWidget(self.outputSplit, 3, 1, 1, 1)
|
||||||
|
|
||||||
self.comicinfoTitleBox = QCheckBox(self.optionWidget)
|
self.metadataTitleBox = QCheckBox(self.optionWidget)
|
||||||
self.comicinfoTitleBox.setObjectName(u"comicinfoTitleBox")
|
self.metadataTitleBox.setObjectName(u"metadataTitleBox")
|
||||||
|
|
||||||
self.gridLayout_2.addWidget(self.comicinfoTitleBox, 7, 0, 1, 1)
|
self.gridLayout_2.addWidget(self.metadataTitleBox, 7, 0, 1, 1)
|
||||||
|
|
||||||
self.qualityBox = QCheckBox(self.optionWidget)
|
self.qualityBox = QCheckBox(self.optionWidget)
|
||||||
self.qualityBox.setObjectName(u"qualityBox")
|
self.qualityBox.setObjectName(u"qualityBox")
|
||||||
@@ -582,9 +582,9 @@ class Ui_mainWindow(object):
|
|||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
self.outputSplit.setText(QCoreApplication.translate("mainWindow", u"Output split", None))
|
self.outputSplit.setText(QCoreApplication.translate("mainWindow", u"Output split", None))
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.comicinfoTitleBox.setToolTip(QCoreApplication.translate("mainWindow", u"Write Title from ComicInfo.xml", None))
|
self.metadataTitleBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p>Write Title from ComicInfo.xml or other embedded metadata.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
self.comicinfoTitleBox.setText(QCoreApplication.translate("mainWindow", u"ComicInfo Title", None))
|
self.metadataTitleBox.setText(QCoreApplication.translate("mainWindow", u"Metadata Title", None))
|
||||||
#if QT_CONFIG(tooltip)
|
#if QT_CONFIG(tooltip)
|
||||||
self.qualityBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 4 panels<br/></span>Zoom each corner separately.</p><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - 2 panels<br/></span>Zoom only the top and bottom of the page.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 4 high-quality panels<br/></span>Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.</p></body></html>", None))
|
self.qualityBox.setToolTip(QCoreApplication.translate("mainWindow", u"<html><head/><body><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Unchecked - 4 panels<br/></span>Zoom each corner separately.</p><p style='white-space:pre'><span style=\" font-weight:600; text-decoration: underline;\">Indeterminate - 2 panels<br/></span>Zoom only the top and bottom of the page.</p><p><span style=\" font-weight:600; text-decoration: underline;\">Checked - 4 high-quality panels<br/></span>Zoom each corner separately. Try to increase the quality of magnification. Check wiki for more details.</p></body></html>", None))
|
||||||
#endif // QT_CONFIG(tooltip)
|
#endif // QT_CONFIG(tooltip)
|
||||||
|
|||||||
@@ -590,6 +590,7 @@ def buildPDF(path, title, cover=None, output_file=None):
|
|||||||
start = perf_counter()
|
start = perf_counter()
|
||||||
# open empty PDF
|
# open empty PDF
|
||||||
with pymupdf.open() as doc:
|
with pymupdf.open() as doc:
|
||||||
|
doc.set_metadata({'title': title, 'author': options.authors[0]})
|
||||||
# Stream images to PDF
|
# Stream images to PDF
|
||||||
for root, dirs, files in os.walk(os.path.join(path, "OEBPS", "Images")):
|
for root, dirs, files in os.walk(os.path.join(path, "OEBPS", "Images")):
|
||||||
files.sort(key=OS_SORT_KEY)
|
files.sort(key=OS_SORT_KEY)
|
||||||
@@ -920,7 +921,7 @@ def getOutputFilename(srcpath, wantedname, ext, tomenumber):
|
|||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
def getComicInfo(path, originalpath):
|
def getMetadata(path, originalpath):
|
||||||
xmlPath = os.path.join(path, 'ComicInfo.xml')
|
xmlPath = os.path.join(path, 'ComicInfo.xml')
|
||||||
options.comicinfo_chapters = []
|
options.comicinfo_chapters = []
|
||||||
options.summary = ''
|
options.summary = ''
|
||||||
@@ -939,13 +940,14 @@ def getComicInfo(path, originalpath):
|
|||||||
else:
|
else:
|
||||||
defaultAuthor = False
|
defaultAuthor = False
|
||||||
options.authors = [options.author]
|
options.authors = [options.author]
|
||||||
|
|
||||||
if os.path.exists(xmlPath):
|
if os.path.exists(xmlPath):
|
||||||
try:
|
try:
|
||||||
xml = metadata.MetadataParser(xmlPath)
|
xml = metadata.MetadataParser(xmlPath)
|
||||||
except Exception:
|
except Exception:
|
||||||
os.remove(xmlPath)
|
os.remove(xmlPath)
|
||||||
return
|
return
|
||||||
if options.comicinfotitle:
|
if options.metadatatitle:
|
||||||
options.title = xml.data['Title']
|
options.title = xml.data['Title']
|
||||||
elif defaultTitle:
|
elif defaultTitle:
|
||||||
if xml.data['Series']:
|
if xml.data['Series']:
|
||||||
@@ -971,6 +973,13 @@ def getComicInfo(path, originalpath):
|
|||||||
options.summary = xml.data['Summary']
|
options.summary = xml.data['Summary']
|
||||||
os.remove(xmlPath)
|
os.remove(xmlPath)
|
||||||
|
|
||||||
|
if originalpath.lower().endswith('.pdf'):
|
||||||
|
with pymupdf.open(originalpath) as doc:
|
||||||
|
if options.metadatatitle and doc.metadata['title']:
|
||||||
|
options.title = doc.metadata['title']
|
||||||
|
if defaultAuthor and doc.metadata['author']:
|
||||||
|
options.authors = [doc.metadata['author']]
|
||||||
|
|
||||||
|
|
||||||
def getDirectorySize(start_path='.'):
|
def getDirectorySize(start_path='.'):
|
||||||
total_size = 0
|
total_size = 0
|
||||||
@@ -1270,8 +1279,8 @@ def makeParser():
|
|||||||
help="Output generated file to specified directory or file")
|
help="Output generated file to specified directory or file")
|
||||||
output_options.add_argument("-t", "--title", action="store", dest="title", default="defaulttitle",
|
output_options.add_argument("-t", "--title", action="store", dest="title", default="defaulttitle",
|
||||||
help="Comic title [Default=filename or directory name]")
|
help="Comic title [Default=filename or directory name]")
|
||||||
output_options.add_argument("--comicinfotitle", action="store_true", dest="comicinfotitle", default=False,
|
output_options.add_argument("--metadatatitle", action="store_true", dest="metadatatitle", default=False,
|
||||||
help="Write Title from ComicInfo.xml")
|
help="Write Title from ComicInfo.xml or other embedded metadata")
|
||||||
output_options.add_argument("-a", "--author", action="store", dest="author", default="defaultauthor",
|
output_options.add_argument("-a", "--author", action="store", dest="author", default="defaultauthor",
|
||||||
help="Author name [Default=KCC]")
|
help="Author name [Default=KCC]")
|
||||||
output_options.add_argument("-f", "--format", action="store", dest="format", default="Auto",
|
output_options.add_argument("-f", "--format", action="store", dest="format", default="Auto",
|
||||||
@@ -1503,7 +1512,7 @@ def makeBook(source, qtgui=None):
|
|||||||
print("Preparing source images...")
|
print("Preparing source images...")
|
||||||
path = getWorkFolder(source)
|
path = getWorkFolder(source)
|
||||||
print("Checking images...")
|
print("Checking images...")
|
||||||
getComicInfo(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'))
|
chapterNames, cover_path = sanitizeTree(os.path.join(path, 'OEBPS', 'Images'))
|
||||||
|
|||||||
Reference in New Issue
Block a user