1
0
mirror of https://github.com/ciromattia/kcc synced 2026-04-21 08:28:59 +00:00

Compare commits

...

10 Commits
4.6 ... 4.6.2

Author SHA1 Message Date
Paweł Jastrzębski
c65e1c8dea Merge pull request #150 from ciromattia/dev
4.6.2
2015-07-14 18:01:51 +02:00
Paweł Jastrzębski
677622c103 Updated README + version bump 2015-07-14 18:01:02 +02:00
Paweł Jastrzębski
af0ebb85a0 Escape HTML in metadata (close #148) 2015-07-14 17:58:59 +02:00
Paweł Jastrzębski
8af029ac92 Fixed MOBI header (close #149) 2015-07-14 17:40:33 +02:00
Paweł Jastrzębski
a268e12a90 Merge pull request #147 from ciromattia/dev
4.6.1
2015-07-05 12:16:27 +02:00
Paweł Jastrzębski
d621335e6c Updated README + version bump 2015-07-05 12:15:35 +02:00
Paweł Jastrzębski
ec1d9c2d93 Added ComicRack Summary field parsing (close #146) 2015-07-05 07:49:48 +02:00
Paweł Jastrzębski
85b9dbbf83 Detect too small input images 2015-07-05 06:57:56 +02:00
Paweł Jastrzębski
feeced44bf Tweaked KEPUB renamer (close #144) 2015-06-28 19:20:38 +02:00
Paweł Jastrzębski
cbea18398b Fixed Kobo TOC (close #145) 2015-06-28 18:31:47 +02:00
5 changed files with 66 additions and 28 deletions

View File

@@ -156,6 +156,16 @@ The app relies and includes the following scripts:
* [Kobo Aura H2O](http://kcc.iosphe.re/Samples/Ubunchu-KoAH2O.kepub.epub)
## CHANGELOG
####4.6.2:
* Fixed critical MOBI header bug
* Fixed metadata encoding error
####4.6.1:
* Fixed KEPUB TOC generator
* Added warning about too small input files
* ComicRack Summary metadata field is now parsed
* Small tweaks of KEPUB output
####4.6:
* KEPUB is now default output for all Kobo profiles
* EPUB output now produce fully valid EPUB 3.0.1

View File

@@ -1,5 +1,5 @@
#define MyAppName "Kindle Comic Converter"
#define MyAppVersion "4.6"
#define MyAppVersion "4.6.2"
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
#define MyAppURL "http://kcc.iosphe.re/"
#define MyAppExeName "KCC.exe"

View File

@@ -1,4 +1,4 @@
__version__ = '4.6'
__version__ = '4.6.2'
__license__ = 'ISC'
__copyright__ = '2012-2015, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
__docformat__ = 'restructuredtext en'

View File

@@ -38,6 +38,7 @@ from PIL import Image
from subprocess import STDOUT, PIPE
from psutil import Popen, virtual_memory
from scandir import walk
from html import escape
try:
from PyQt5 import QtCore
except ImportError:
@@ -260,7 +261,16 @@ def buildNAV(dstdir, title, chapters, chapterNames):
"</head>\n",
"<body>\n",
"<nav xmlns:epub=\"http://www.idpf.org/2007/ops\" epub:type=\"toc\" id=\"toc\">\n",
"<ol></ol>\n",
"<ol>\n"])
for chapter in chapters:
folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')
filename = getImageFileName(os.path.join(folder, chapter[1]))
if options.chapters:
title = chapterNames[chapter[1]]
elif os.path.basename(folder) != "Text":
title = chapterNames[os.path.basename(folder)]
f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".html\">" + title + "</a></li>\n")
f.writelines(["</ol>\n",
"</nav>\n",
"<nav epub:type=\"page-list\">\n",
"<ol>\n"
@@ -294,7 +304,8 @@ def buildOPF(dstdir, title, filelist, cover=None):
"<dc:title>", title, "</dc:title>\n",
"<dc:language>en-US</dc:language>\n",
"<dc:identifier id=\"BookID\">urn:uuid:", options.uuid, "</dc:identifier>\n",
"<dc:contributor id=\"contributor\">KindleComicConverter-" + __version__ + "</dc:contributor>\n"])
"<dc:contributor id=\"contributor\">KindleComicConverter-" + __version__ + "</dc:contributor>\n",
"<dc:description>", options.summary, "</dc:description>\n"])
for author in options.authors:
f.writelines(["<dc:creator>", author, "</dc:creator>\n"])
f.writelines(["<meta property=\"dcterms:modified\">" + strftime("%Y-%m-%dT%H:%M:%SZ", gmtime()) + "</meta>\n",
@@ -303,18 +314,15 @@ def buildOPF(dstdir, title, filelist, cover=None):
"<meta property=\"rendition:spread\">portrait</meta>\n",
"<meta property=\"rendition:layout\">pre-paginated</meta>\n"])
if options.iskindle and options.profile != 'Custom':
f.writelines(["<meta property=\"RegionMagnification\">true</meta>\n",
"<meta property=\"region-mag\">true</meta>\n",
"<meta property=\"book-type\">comic</meta>\n",
"<meta property=\"zero-gutter\">true</meta>\n",
"<meta property=\"zero-margin\">true</meta>\n",
"<meta property=\"fixed-layout\">true</meta>\n",
"<meta property=\"orientation-lock\">portrait</meta>\n",
"<meta property=\"original-resolution\">",
str(deviceres[0]) + "x" + str(deviceres[1]) + "</meta>\n",
"<meta property=\"primary-writing-mode\">" + writingmode + "</meta>\n",
"<meta property=\"ke-border-color\">#ffffff</meta>\n",
"<meta property=\"ke-border-width\">0</meta>\n"])
f.writelines(["<meta name=\"original-resolution\" content=\"",
str(deviceres[0]) + "x" + str(deviceres[1]) + "\"/>\n",
"<meta name=\"book-type\" content=\"comic\"/>\n",
"<meta name=\"RegionMagnification\" content=\"true\"/>\n",
"<meta name=\"primary-writing-mode\" content=\"" + writingmode + "\"/>\n",
"<meta name=\"zero-gutter\" content=\"true\"/>\n",
"<meta name=\"zero-margin\" content=\"true\"/>\n",
"<meta name=\"ke-border-color\" content=\"#ffffff\"/>\n",
"<meta name=\"ke-border-width\" content=\"0\"/>\n"])
f.writelines(["</metadata>\n<manifest>\n<item id=\"ncx\" href=\"toc.ncx\" ",
"media-type=\"application/x-dtbncx+xml\"/>\n",
"<item id=\"nav\" href=\"nav.xhtml\" ",
@@ -682,8 +690,8 @@ def getWorkFolder(afile):
def getOutputFilename(srcpath, wantedname, ext, tomeNumber):
if srcpath[-1] == os.path.sep:
srcpath = srcpath[:-1]
if not ext.startswith('.'):
ext = '.' + ext
if 'Ko' in options.profile and options.format == 'EPUB':
ext = '.kepub.epub'
if wantedname is not None:
if wantedname.endswith(ext):
filename = os.path.abspath(wantedname)
@@ -695,7 +703,14 @@ def getOutputFilename(srcpath, wantedname, ext, tomeNumber):
elif os.path.isdir(srcpath):
filename = srcpath + tomeNumber + ext
else:
filename = os.path.splitext(srcpath)[0] + tomeNumber + ext
if 'Ko' in options.profile and options.format == 'EPUB':
path = srcpath.split(os.path.sep)
path[-1] = ''.join(e for e in path[-1].split('.')[0] if e.isalnum()) + tomeNumber + ext
if not path[-1].split('.')[0]:
path[-1] = 'KCCPlaceholder' + tomeNumber + ext
filename = os.path.sep.join(path)
else:
filename = os.path.splitext(srcpath)[0] + tomeNumber + ext
if os.path.isfile(filename):
counter = 0
basename = os.path.splitext(filename)[0]
@@ -710,6 +725,7 @@ def getComicInfo(path, originalPath):
options.authors = ['KCC']
options.remoteCovers = {}
options.chapters = []
options.summary = ''
titleSuffix = ''
if options.title == 'defaulttitle':
defaultTitle = True
@@ -728,7 +744,7 @@ def getComicInfo(path, originalPath):
options.authors = []
if defaultTitle:
if xml.data['Series']:
options.title = xml.data['Series']
options.title = escape(xml.data['Series'])
if xml.data['Volume']:
titleSuffix += ' V' + xml.data['Volume']
if xml.data['Number']:
@@ -736,7 +752,7 @@ def getComicInfo(path, originalPath):
options.title += titleSuffix
for field in ['Writers', 'Pencillers', 'Inkers', 'Colorists']:
for person in xml.data[field]:
options.authors.append(person)
options.authors.append(escape(person))
if len(options.authors) > 0:
options.authors = list(set(options.authors))
options.authors.sort()
@@ -746,6 +762,8 @@ def getComicInfo(path, originalPath):
options.remoteCovers = getCoversFromMCB(xml.data['MUid'])
if xml.data['Bookmarks']:
options.chapters = xml.data['Bookmarks']
if xml.data['Summary']:
options.summary = escape(xml.data['Summary'])
os.remove(xmlPath)
@@ -948,6 +966,8 @@ def splitProcess(path, mode):
def detectCorruption(tmpPath, orgPath):
imageNumber = 0
imageSmaller = 0
for root, dirs, files in walk(tmpPath, False):
for name in files:
if getImageFileName(name) is not None:
@@ -961,6 +981,9 @@ def detectCorruption(tmpPath, orgPath):
img.verify()
img = Image.open(path)
img.load()
imageNumber += 1
if options.profileData[1][0] > img.size[0] and options.profileData[1][1] > img.size[1]:
imageSmaller += 1
except Exception as err:
rmtree(os.path.join(tmpPath, '..', '..'), True)
if 'decoder' in err and 'not available' in err:
@@ -969,6 +992,13 @@ def detectCorruption(tmpPath, orgPath):
raise RuntimeError('Image file %s is corrupted.' % pathOrg)
else:
os.remove(os.path.join(root, name))
if imageSmaller > imageNumber * 0.5 and not options.upscale and not options.stretch:
print("\nMore than half of images are smaller than target device resolution. "
"Consider enabling stretching or upscaling to improve readability.")
if GUI:
GUI.addMessage.emit('More than half of images are smaller than target device resolution.', 'warning', False)
GUI.addMessage.emit('Consider enabling stretching or upscaling to improve readability.', 'warning', False)
GUI.addMessage.emit('', '', False)
def detectMargins(path):
@@ -1239,11 +1269,6 @@ def makeBook(source, qtGUI=None):
filepath.append(getOutputFilename(source, options.output, '.epub', ''))
makeZIP(tome + '_comic', tome, True)
move(tome + '_comic.zip', filepath[-1])
if 'Ko' in options.profile:
filename = filepath[-1].split(os.path.sep)
filename[-1] = ''.join(e for e in filename[-1].split('.')[0] if e.isalnum()) + '.kepub.epub'
filename = os.path.sep.join(filename)
move(filepath[-1], filename)
rmtree(tome, True)
if GUI:
GUI.progressBarTick.emit('tick')

View File

@@ -38,6 +38,7 @@ class MetadataParser:
'Pencillers': [],
'Inkers': [],
'Colorists': [],
'Summary': '',
'MUid': '',
'Bookmarks': []}
self.rawdata = None
@@ -90,6 +91,8 @@ class MetadataParser:
self.data['Volume'] = self.rawdata.getElementsByTagName('Volume')[0].firstChild.nodeValue
if len(self.rawdata.getElementsByTagName('Number')) != 0:
self.data['Number'] = self.rawdata.getElementsByTagName('Number')[0].firstChild.nodeValue
if len(self.rawdata.getElementsByTagName('Summary')) != 0:
self.data['Summary'] = self.rawdata.getElementsByTagName('Summary')[0].firstChild.nodeValue
for field in ['Writer', 'Penciller', 'Inker', 'Colorist']:
if len(self.rawdata.getElementsByTagName(field)) != 0:
for person in self.rawdata.getElementsByTagName(field)[0].firstChild.nodeValue.split(', '):
@@ -113,7 +116,7 @@ class MetadataParser:
for row in (['Series', self.data['Series']], ['Volume', self.data['Volume']],
['Number', self.data['Number']], ['Writer', ', '.join(self.data['Writers'])],
['Penciller', ', '.join(self.data['Pencillers'])], ['Inker', ', '.join(self.data['Inkers'])],
['Colorist', ', '.join(self.data['Colorists'])],
['Colorist', ', '.join(self.data['Colorists'])], ['Summary', self.data['Summary']],
['ScanInformation', 'MCD(' + self.data['MUid'] + ')' if self.data['MUid'] else '']):
if self.rawdata.getElementsByTagName(row[0]):
node = self.rawdata.getElementsByTagName(row[0])[0]
@@ -135,7 +138,7 @@ class MetadataParser:
for row in (['Series', self.data['Series']], ['Volume', self.data['Volume']],
['Number', self.data['Number']], ['Writer', ', '.join(self.data['Writers'])],
['Penciller', ', '.join(self.data['Pencillers'])], ['Inker', ', '.join(self.data['Inkers'])],
['Colorist', ', '.join(self.data['Colorists'])],
['Colorist', ', '.join(self.data['Colorists'])], ['Summary', self.data['Summary']],
['ScanInformation', 'MCD(' + self.data['MUid'] + ')' if self.data['MUid'] else '']):
if row[1]:
main = doc.createElement(row[0])