mirror of
https://github.com/ciromattia/kcc
synced 2025-12-22 14:11:45 +00:00
7
.gitignore
vendored
7
.gitignore
vendored
@@ -1,16 +1,15 @@
|
|||||||
*.pyc
|
*.pyc
|
||||||
*.cbz
|
*.cbz
|
||||||
*.cbr
|
*.cbr
|
||||||
|
*.spec
|
||||||
.idea
|
.idea
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.python-version
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
dist
|
dist
|
||||||
Output
|
Output
|
||||||
test
|
|
||||||
solaio
|
|
||||||
kindlegen*
|
kindlegen*
|
||||||
*.spec
|
setup.bat
|
||||||
kindlecomicconverter/sentry.py
|
kindlecomicconverter/sentry.py
|
||||||
build/
|
build/
|
||||||
.python-version
|
|
||||||
KindleComicConverter.egg-info/
|
KindleComicConverter.egg-info/
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
# CHANGELOG
|
# CHANGELOG
|
||||||
|
#### 5.4.4:
|
||||||
|
* Minor bug fixes
|
||||||
|
|
||||||
#### 5.4.3:
|
#### 5.4.3:
|
||||||
* Fixed conversion crash on Windows
|
* Fixed conversion crash on Windows
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
ISC LICENSE
|
ISC LICENSE
|
||||||
|
|
||||||
Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
Copyright (c) 2013-2017 Paweł Jastrzębski <pawelj@iosphe.re>
|
Copyright (c) 2013-2018 Paweł Jastrzębski <pawelj@iosphe.re>
|
||||||
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for
|
Permission to use, copy, modify, and/or distribute this software for
|
||||||
any purpose with or without fee is hereby granted, provided that the
|
any purpose with or without fee is hereby granted, provided that the
|
||||||
|
|||||||
@@ -181,5 +181,5 @@ The app relies and includes the following scripts:
|
|||||||
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).
|
Please check [wiki page](https://github.com/ciromattia/kcc/wiki/Known-issues).
|
||||||
|
|
||||||
## COPYRIGHT
|
## COPYRIGHT
|
||||||
Copyright (c) 2012-2017 Ciro Mattia Gonano and Paweł Jastrzębski.
|
Copyright (c) 2012-2018 Ciro Mattia Gonano and Paweł Jastrzębski.
|
||||||
**KCC** is released under ISC LICENSE; see LICENSE.txt for further details.
|
**KCC** is released under ISC LICENSE; see LICENSE.txt for further details.
|
||||||
|
|||||||
@@ -7,15 +7,13 @@ install:
|
|||||||
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
|
- "%PYTHON%\\python.exe -m pip install -r requirements.txt"
|
||||||
- "%PYTHON%\\python.exe -m pip install certifi PyInstaller"
|
- "%PYTHON%\\python.exe -m pip install certifi PyInstaller"
|
||||||
- nuget install secure-file -ExcludeVersion
|
- nuget install secure-file -ExcludeVersion
|
||||||
- nuget install verpatch -ExcludeVersion
|
|
||||||
- secure-file\tools\secure-file -decrypt other\windows\Cert.pfx.enc -secret %ENCRYPTION%
|
|
||||||
- secure-file\tools\secure-file -decrypt other\windows\sentry.py.enc -out kindlecomicconverter\sentry.py -secret %ENCRYPTION%
|
- secure-file\tools\secure-file -decrypt other\windows\sentry.py.enc -out kindlecomicconverter\sentry.py -secret %ENCRYPTION%
|
||||||
|
|
||||||
build_script:
|
build_script:
|
||||||
- "%PYTHON%\\python.exe setup.py build_binary"
|
- "%PYTHON%\\python.exe setup.py build_binary"
|
||||||
|
|
||||||
after_build:
|
after_build:
|
||||||
- ps: Get-ChildItem .\dist\KindleComicConverter_win_* | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
- ps: Get-ChildItem .\dist\KCC* | % { Push-AppveyorArtifact $_.FullName -FileName $_.Name }
|
||||||
|
|
||||||
deploy:
|
deploy:
|
||||||
provider: S3
|
provider: S3
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
|
|||||||
4
kcc.iss
4
kcc.iss
@@ -1,5 +1,5 @@
|
|||||||
#define MyAppName "Kindle Comic Converter"
|
#define MyAppName "Kindle Comic Converter"
|
||||||
#define MyAppVersion "5.4.3"
|
#define MyAppVersion "5.4.4"
|
||||||
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
|
#define MyAppPublisher "Ciro Mattia Gonano, Paweł Jastrzębski"
|
||||||
#define MyAppURL "http://kcc.iosphe.re/"
|
#define MyAppURL "http://kcc.iosphe.re/"
|
||||||
#define MyAppExeName "KCC.exe"
|
#define MyAppExeName "KCC.exe"
|
||||||
@@ -12,7 +12,7 @@ AppPublisher={#MyAppPublisher}
|
|||||||
AppPublisherURL={#MyAppURL}
|
AppPublisherURL={#MyAppURL}
|
||||||
AppSupportURL={#MyAppURL}
|
AppSupportURL={#MyAppURL}
|
||||||
AppUpdatesURL={#MyAppURL}
|
AppUpdatesURL={#MyAppURL}
|
||||||
AppCopyright=Copyright (C) 2012-2017 Ciro Mattia Gonano and Paweł Jastrzębski
|
AppCopyright=Copyright (C) 2012-2018 Ciro Mattia Gonano and Paweł Jastrzębski
|
||||||
ArchitecturesAllowed=x64
|
ArchitecturesAllowed=x64
|
||||||
DefaultDirName={pf}\{#MyAppName}
|
DefaultDirName={pf}\{#MyAppName}
|
||||||
DefaultGroupName={#MyAppName}
|
DefaultGroupName={#MyAppName}
|
||||||
|
|||||||
22
kcc.py
22
kcc.py
@@ -2,7 +2,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -34,24 +34,6 @@ if sys.platform.startswith('darwin'):
|
|||||||
else:
|
else:
|
||||||
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/osx/:' + os.environ['PATH']
|
os.environ['PATH'] = os.path.dirname(os.path.abspath(__file__)) + '/other/osx/:' + os.environ['PATH']
|
||||||
elif sys.platform.startswith('win'):
|
elif sys.platform.startswith('win'):
|
||||||
'''
|
|
||||||
import multiprocessing.popen_spawn_win32 as forking
|
|
||||||
|
|
||||||
class _Popen(forking.Popen):
|
|
||||||
def __init__(self, *args, **kw):
|
|
||||||
if hasattr(sys, 'frozen'):
|
|
||||||
# noinspection PyUnresolvedReferences,PyProtectedMember
|
|
||||||
os.putenv('_MEIPASS2', sys._MEIPASS)
|
|
||||||
try:
|
|
||||||
super(_Popen, self).__init__(*args, **kw)
|
|
||||||
finally:
|
|
||||||
if hasattr(sys, 'frozen'):
|
|
||||||
if hasattr(os, 'unsetenv'):
|
|
||||||
os.unsetenv('_MEIPASS2')
|
|
||||||
else:
|
|
||||||
os.putenv('_MEIPASS2', '')
|
|
||||||
forking.Popen = _Popen
|
|
||||||
'''
|
|
||||||
if getattr(sys, 'frozen', False):
|
if getattr(sys, 'frozen', False):
|
||||||
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
|
os.chdir(os.path.dirname(os.path.abspath(sys.executable)))
|
||||||
else:
|
else:
|
||||||
@@ -61,7 +43,7 @@ elif sys.platform.startswith('win'):
|
|||||||
if getattr(sys, 'frozen', False):
|
if getattr(sys, 'frozen', False):
|
||||||
try:
|
try:
|
||||||
import kindlecomicconverter.sentry
|
import kindlecomicconverter.sentry
|
||||||
except:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
from multiprocessing import freeze_support
|
from multiprocessing import freeze_support
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -156,8 +156,8 @@ class VersionThread(QtCore.QThread):
|
|||||||
'(<a href="https://github.com/ciromattia/kcc/releases/">'
|
'(<a href="https://github.com/ciromattia/kcc/releases/">'
|
||||||
'Changelog</a>)', 'warning', False)
|
'Changelog</a>)', 'warning', False)
|
||||||
|
|
||||||
def setAnswer(self, dialogAnswer):
|
def setAnswer(self, dialoganswer):
|
||||||
self.answer = dialogAnswer
|
self.answer = dialoganswer
|
||||||
|
|
||||||
def getNewVersion(self):
|
def getNewVersion(self):
|
||||||
while self.answer is None:
|
while self.answer is None:
|
||||||
@@ -180,8 +180,8 @@ class VersionThread(QtCore.QThread):
|
|||||||
MW.hideProgressBar.emit()
|
MW.hideProgressBar.emit()
|
||||||
MW.modeConvert.emit(1)
|
MW.modeConvert.emit(1)
|
||||||
|
|
||||||
def getNewVersionTick(self, size, blockSize, totalSize):
|
def getNewVersionTick(self, size, blocksize, totalsize):
|
||||||
progress = int((size / (totalSize // blockSize)) * 100)
|
progress = int((size / (totalsize // blocksize)) * 100)
|
||||||
if size == 0:
|
if size == 0:
|
||||||
MW.progressBarTick.emit('100')
|
MW.progressBarTick.emit('100')
|
||||||
if progress > self.barProgress:
|
if progress > self.barProgress:
|
||||||
@@ -667,10 +667,10 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">'
|
self.addMessage('<a href="https://github.com/ciromattia/kcc/wiki/NonKindle-devices">'
|
||||||
'List of supported Non-Kindle devices.</a>', 'info')
|
'List of supported Non-Kindle devices.</a>', 'info')
|
||||||
|
|
||||||
def changeFormat(self, outputFormat=None):
|
def changeFormat(self, outputformat=None):
|
||||||
profile = GUI.profiles[str(GUI.deviceBox.currentText())]
|
profile = GUI.profiles[str(GUI.deviceBox.currentText())]
|
||||||
if outputFormat is not None:
|
if outputformat is not None:
|
||||||
GUI.formatBox.setCurrentIndex(outputFormat)
|
GUI.formatBox.setCurrentIndex(outputformat)
|
||||||
else:
|
else:
|
||||||
GUI.formatBox.setCurrentIndex(profile['DefaultFormat'])
|
GUI.formatBox.setCurrentIndex(profile['DefaultFormat'])
|
||||||
if not GUI.webtoonBox.isChecked():
|
if not GUI.webtoonBox.isChecked():
|
||||||
@@ -881,10 +881,10 @@ class KCCGUI(KCC_ui.Ui_mainWindow):
|
|||||||
else:
|
else:
|
||||||
self.addMessage('Download it and place executable in /usr/local/bin directory.', 'error')
|
self.addMessage('Download it and place executable in /usr/local/bin directory.', 'error')
|
||||||
|
|
||||||
def __init__(self, KCCAplication, KCCWindow):
|
def __init__(self, kccapp, kccwindow):
|
||||||
global APP, MW, GUI
|
global APP, MW, GUI
|
||||||
APP = KCCAplication
|
APP = kccapp
|
||||||
MW = KCCWindow
|
MW = kccwindow
|
||||||
GUI = self
|
GUI = self
|
||||||
self.setupUi(MW)
|
self.setupUi(MW)
|
||||||
self.editor = KCCGUI_MetaEditor()
|
self.editor = KCCGUI_MetaEditor()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
__version__ = '5.4.3'
|
__version__ = '5.4.4'
|
||||||
__license__ = 'ISC'
|
__license__ = 'ISC'
|
||||||
__copyright__ = '2012-2017, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
__copyright__ = '2012-2018, Ciro Mattia Gonano <ciromattia@gmail.com>, Pawel Jastrzebski <pawelj@iosphe.re>'
|
||||||
__docformat__ = 'restructuredtext en'
|
__docformat__ = 'restructuredtext en'
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -26,13 +26,13 @@ from .shared import check7ZFile as is_7zfile
|
|||||||
|
|
||||||
|
|
||||||
class CBxArchive:
|
class CBxArchive:
|
||||||
def __init__(self, origFileName):
|
def __init__(self, fname):
|
||||||
self.origFileName = origFileName
|
self.fname = fname
|
||||||
if is_zipfile(origFileName):
|
if is_zipfile(fname):
|
||||||
self.compressor = 'zip'
|
self.compressor = 'zip'
|
||||||
elif rarfile.is_rarfile(origFileName):
|
elif rarfile.is_rarfile(fname):
|
||||||
self.compressor = 'rar'
|
self.compressor = 'rar'
|
||||||
elif is_7zfile(origFileName):
|
elif is_7zfile(fname):
|
||||||
self.compressor = '7z'
|
self.compressor = '7z'
|
||||||
else:
|
else:
|
||||||
self.compressor = None
|
self.compressor = None
|
||||||
@@ -41,22 +41,19 @@ class CBxArchive:
|
|||||||
return self.compressor is not None
|
return self.compressor is not None
|
||||||
|
|
||||||
def extractCBZ(self, targetdir):
|
def extractCBZ(self, targetdir):
|
||||||
cbzFile = ZipFile(self.origFileName)
|
cbzFile = ZipFile(self.fname)
|
||||||
filelist = []
|
filelist = []
|
||||||
for f in cbzFile.namelist():
|
for f in cbzFile.namelist():
|
||||||
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('humbs.db'):
|
if f.startswith('__MACOSX') or f.endswith('.DS_Store') or f.endswith('humbs.db'):
|
||||||
pass
|
pass
|
||||||
elif f.endswith('/'):
|
elif f.endswith('/'):
|
||||||
try:
|
os.makedirs(os.path.join(targetdir, f), exist_ok=True)
|
||||||
os.makedirs(os.path.join(targetdir, f))
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
filelist.append(f)
|
filelist.append(f)
|
||||||
cbzFile.extractall(targetdir, filelist)
|
cbzFile.extractall(targetdir, filelist)
|
||||||
|
|
||||||
def extractCBR(self, targetdir):
|
def extractCBR(self, targetdir):
|
||||||
cbrFile = rarfile.RarFile(self.origFileName)
|
cbrFile = rarfile.RarFile(self.fname)
|
||||||
cbrFile.extractall(targetdir)
|
cbrFile.extractall(targetdir)
|
||||||
for root, _, filenames in os.walk(targetdir):
|
for root, _, filenames in os.walk(targetdir):
|
||||||
for filename in filenames:
|
for filename in filenames:
|
||||||
@@ -64,7 +61,7 @@ class CBxArchive:
|
|||||||
os.remove(os.path.join(root, filename))
|
os.remove(os.path.join(root, filename))
|
||||||
|
|
||||||
def extractCB7(self, targetdir):
|
def extractCB7(self, targetdir):
|
||||||
output = Popen('7za x "' + self.origFileName + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' +
|
output = Popen('7za x "' + self.fname + '" -xr!__MACOSX -xr!.DS_Store -xr!thumbs.db -xr!Thumbs.db -o"' +
|
||||||
targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
targetdir + '"', stdout=PIPE, stderr=STDOUT, stdin=PIPE, shell=True)
|
||||||
extracted = False
|
extracted = False
|
||||||
for line in output.stdout:
|
for line in output.stdout:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -88,7 +88,7 @@ def buildHTML(path, imgfile, imgfilepath):
|
|||||||
if "BlackBackground" in options.imgMetadata[imgfilepath]:
|
if "BlackBackground" in options.imgMetadata[imgfilepath]:
|
||||||
additionalStyle = 'background-color:#000000;'
|
additionalStyle = 'background-color:#000000;'
|
||||||
else:
|
else:
|
||||||
additionalStyle = 'background-color:#FFFFFF;'
|
additionalStyle = ''
|
||||||
postfix = ''
|
postfix = ''
|
||||||
backref = 1
|
backref = 1
|
||||||
head = path
|
head = path
|
||||||
@@ -198,7 +198,7 @@ def buildHTML(path, imgfile, imgfilepath):
|
|||||||
return path, imgfile
|
return path, imgfile
|
||||||
|
|
||||||
|
|
||||||
def buildNCX(dstdir, title, chapters, chapterNames):
|
def buildNCX(dstdir, title, chapters, chapternames):
|
||||||
ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx')
|
ncxfile = os.path.join(dstdir, 'OEBPS', 'toc.ncx')
|
||||||
f = open(ncxfile, "w", encoding='UTF-8')
|
f = open(ncxfile, "w", encoding='UTF-8')
|
||||||
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
f.writelines(["<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n",
|
||||||
@@ -217,10 +217,10 @@ def buildNCX(dstdir, title, chapters, chapterNames):
|
|||||||
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
||||||
navID = folder.replace('/', '_').replace('\\', '_')
|
navID = folder.replace('/', '_').replace('\\', '_')
|
||||||
if options.chapters:
|
if options.chapters:
|
||||||
title = chapterNames[chapter[1]]
|
title = chapternames[chapter[1]]
|
||||||
navID = filename[0].replace('/', '_').replace('\\', '_')
|
navID = filename[0].replace('/', '_').replace('\\', '_')
|
||||||
elif os.path.basename(folder) != "Text":
|
elif os.path.basename(folder) != "Text":
|
||||||
title = chapterNames[os.path.basename(folder)]
|
title = chapternames[os.path.basename(folder)]
|
||||||
f.write("<navPoint id=\"" + navID + "\"><navLabel><text>" +
|
f.write("<navPoint id=\"" + navID + "\"><navLabel><text>" +
|
||||||
escape(title) + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") +
|
escape(title) + "</text></navLabel><content src=\"" + filename[0].replace("\\", "/") +
|
||||||
".xhtml\"/></navPoint>\n")
|
".xhtml\"/></navPoint>\n")
|
||||||
@@ -228,7 +228,7 @@ def buildNCX(dstdir, title, chapters, chapterNames):
|
|||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
def buildNAV(dstdir, title, chapters, chapterNames):
|
def buildNAV(dstdir, title, chapters, chapternames):
|
||||||
navfile = os.path.join(dstdir, 'OEBPS', 'nav.xhtml')
|
navfile = os.path.join(dstdir, 'OEBPS', 'nav.xhtml')
|
||||||
f = open(navfile, "w", encoding='UTF-8')
|
f = open(navfile, "w", encoding='UTF-8')
|
||||||
f.writelines(["<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
|
f.writelines(["<?xml version=\"1.0\" encoding=\"utf-8\"?>\n",
|
||||||
@@ -245,9 +245,9 @@ def buildNAV(dstdir, title, chapters, chapterNames):
|
|||||||
folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')
|
folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')
|
||||||
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
||||||
if options.chapters:
|
if options.chapters:
|
||||||
title = chapterNames[chapter[1]]
|
title = chapternames[chapter[1]]
|
||||||
elif os.path.basename(folder) != "Text":
|
elif os.path.basename(folder) != "Text":
|
||||||
title = chapterNames[os.path.basename(folder)]
|
title = chapternames[os.path.basename(folder)]
|
||||||
f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".xhtml\">" + escape(title) + "</a></li>\n")
|
f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".xhtml\">" + escape(title) + "</a></li>\n")
|
||||||
f.writelines(["</ol>\n",
|
f.writelines(["</ol>\n",
|
||||||
"</nav>\n",
|
"</nav>\n",
|
||||||
@@ -257,9 +257,9 @@ def buildNAV(dstdir, title, chapters, chapterNames):
|
|||||||
folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')
|
folder = chapter[0].replace(os.path.join(dstdir, 'OEBPS'), '').lstrip('/').lstrip('\\\\')
|
||||||
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
filename = getImageFileName(os.path.join(folder, chapter[1]))
|
||||||
if options.chapters:
|
if options.chapters:
|
||||||
title = chapterNames[chapter[1]]
|
title = chapternames[chapter[1]]
|
||||||
elif os.path.basename(folder) != "Text":
|
elif os.path.basename(folder) != "Text":
|
||||||
title = chapterNames[os.path.basename(folder)]
|
title = chapternames[os.path.basename(folder)]
|
||||||
f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".xhtml\">" + escape(title) + "</a></li>\n")
|
f.write("<li><a href=\"" + filename[0].replace("\\", "/") + ".xhtml\">" + escape(title) + "</a></li>\n")
|
||||||
f.write("</ol>\n</nav>\n</body>\n</html>")
|
f.write("</ol>\n</nav>\n</body>\n</html>")
|
||||||
f.close()
|
f.close()
|
||||||
@@ -287,20 +287,27 @@ def buildOPF(dstdir, title, filelist, cover=None):
|
|||||||
for author in options.authors:
|
for author in options.authors:
|
||||||
f.writelines(["<dc:creator>", author, "</dc:creator>\n"])
|
f.writelines(["<dc:creator>", author, "</dc:creator>\n"])
|
||||||
f.writelines(["<meta property=\"dcterms:modified\">" + strftime("%Y-%m-%dT%H:%M:%SZ", gmtime()) + "</meta>\n",
|
f.writelines(["<meta property=\"dcterms:modified\">" + strftime("%Y-%m-%dT%H:%M:%SZ", gmtime()) + "</meta>\n",
|
||||||
"<meta name=\"cover\" content=\"cover\"/>\n",
|
"<meta name=\"cover\" content=\"cover\"/>\n"])
|
||||||
"<meta property=\"rendition:orientation\">portrait</meta>\n",
|
|
||||||
"<meta property=\"rendition:spread\">portrait</meta>\n",
|
|
||||||
"<meta property=\"rendition:layout\">pre-paginated</meta>\n"])
|
|
||||||
if options.iskindle and options.profile != 'Custom':
|
if options.iskindle and options.profile != 'Custom':
|
||||||
f.writelines(["<meta name=\"original-resolution\" content=\"",
|
f.writelines(["<meta name=\"fixed-layout\" content=\"true\"/>\n",
|
||||||
|
"<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=\"RegionMagnification\" content=\"true\"/>\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",
|
||||||
"<meta name=\"zero-margin\" content=\"true\"/>\n",
|
"<meta name=\"zero-margin\" content=\"true\"/>\n",
|
||||||
"<meta name=\"ke-border-color\" content=\"#ffffff\"/>\n",
|
"<meta name=\"ke-border-color\" content=\"#FFFFFF\"/>\n",
|
||||||
"<meta name=\"ke-border-width\" content=\"0\"/>\n"])
|
"<meta name=\"ke-border-width\" content=\"0\"/>\n"])
|
||||||
|
if options.kfx:
|
||||||
|
f.writelines(["<meta name=\"orientation-lock\" content=\"none\"/>\n",
|
||||||
|
"<meta name=\"region-mag\" content=\"false\"/>\n"])
|
||||||
|
else:
|
||||||
|
f.writelines(["<meta name=\"orientation-lock\" content=\"portrait\"/>\n",
|
||||||
|
"<meta name=\"region-mag\" content=\"true\"/>\n"])
|
||||||
|
else:
|
||||||
|
f.writelines(["<meta property=\"rendition:orientation\">portrait</meta>\n",
|
||||||
|
"<meta property=\"rendition:spread\">portrait</meta>\n",
|
||||||
|
"<meta property=\"rendition:layout\">pre-paginated</meta>\n"])
|
||||||
f.writelines(["</metadata>\n<manifest>\n<item id=\"ncx\" href=\"toc.ncx\" ",
|
f.writelines(["</metadata>\n<manifest>\n<item id=\"ncx\" href=\"toc.ncx\" ",
|
||||||
"media-type=\"application/x-dtbncx+xml\"/>\n",
|
"media-type=\"application/x-dtbncx+xml\"/>\n",
|
||||||
"<item id=\"nav\" href=\"nav.xhtml\" ",
|
"<item id=\"nav\" href=\"nav.xhtml\" ",
|
||||||
@@ -331,10 +338,43 @@ def buildOPF(dstdir, title, filelist, cover=None):
|
|||||||
f.write("<item id=\"css\" href=\"Text/style.css\" media-type=\"text/css\"/>\n")
|
f.write("<item id=\"css\" href=\"Text/style.css\" media-type=\"text/css\"/>\n")
|
||||||
if options.righttoleft:
|
if options.righttoleft:
|
||||||
f.write("</manifest>\n<spine page-progression-direction=\"rtl\" toc=\"ncx\">\n")
|
f.write("</manifest>\n<spine page-progression-direction=\"rtl\" toc=\"ncx\">\n")
|
||||||
|
pageside = "right"
|
||||||
else:
|
else:
|
||||||
f.write("</manifest>\n<spine page-progression-direction=\"ltr\" toc=\"ncx\">\n")
|
f.write("</manifest>\n<spine page-progression-direction=\"ltr\" toc=\"ncx\">\n")
|
||||||
for entry in reflist:
|
pageside = "left"
|
||||||
f.write("<itemref idref=\"page_" + entry + "\"/>\n")
|
if options.iskindle:
|
||||||
|
for entry in reflist:
|
||||||
|
if options.righttoleft:
|
||||||
|
if entry.endswith("-b"):
|
||||||
|
f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-right\"/>\n")
|
||||||
|
pageside = "right"
|
||||||
|
elif entry.endswith("-c"):
|
||||||
|
f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-left\"/>\n")
|
||||||
|
pageside = "right"
|
||||||
|
else:
|
||||||
|
f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-" +
|
||||||
|
pageside + "\"/>\n")
|
||||||
|
if pageside == "right":
|
||||||
|
pageside = "left"
|
||||||
|
else:
|
||||||
|
pageside = "right"
|
||||||
|
else:
|
||||||
|
if entry.endswith("-b"):
|
||||||
|
f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-left\"/>\n")
|
||||||
|
pageside = "left"
|
||||||
|
elif entry.endswith("-c"):
|
||||||
|
f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-right\"/>\n")
|
||||||
|
pageside = "left"
|
||||||
|
else:
|
||||||
|
f.write("<itemref idref=\"page_" + entry + "\" linear=\"yes\" properties=\"page-spread-" +
|
||||||
|
pageside + "\"/>\n")
|
||||||
|
if pageside == "right":
|
||||||
|
pageside = "left"
|
||||||
|
else:
|
||||||
|
pageside = "right"
|
||||||
|
else:
|
||||||
|
for entry in reflist:
|
||||||
|
f.write("<itemref idref=\"page_" + entry + "\">\n")
|
||||||
f.write("</spine>\n</package>\n")
|
f.write("</spine>\n</package>\n")
|
||||||
f.close()
|
f.close()
|
||||||
os.mkdir(os.path.join(dstdir, 'META-INF'))
|
os.mkdir(os.path.join(dstdir, 'META-INF'))
|
||||||
@@ -348,7 +388,7 @@ def buildOPF(dstdir, title, filelist, cover=None):
|
|||||||
f.close()
|
f.close()
|
||||||
|
|
||||||
|
|
||||||
def buildEPUB(path, chapterNames, tomeNumber):
|
def buildEPUB(path, chapternames, tomenumber):
|
||||||
filelist = []
|
filelist = []
|
||||||
chapterlist = []
|
chapterlist = []
|
||||||
cover = None
|
cover = None
|
||||||
@@ -361,71 +401,72 @@ def buildEPUB(path, chapterNames, tomeNumber):
|
|||||||
"display: block;\n",
|
"display: block;\n",
|
||||||
"margin: 0;\n",
|
"margin: 0;\n",
|
||||||
"padding: 0;\n",
|
"padding: 0;\n",
|
||||||
"}\n",
|
|
||||||
"#PV {\n",
|
|
||||||
"position: absolute;\n",
|
|
||||||
"width: 100%;\n",
|
|
||||||
"height: 100%;\n",
|
|
||||||
"top: 0;\n",
|
|
||||||
"left: 0;\n",
|
|
||||||
"}\n",
|
|
||||||
"#PV-T {\n",
|
|
||||||
"top: 0;\n",
|
|
||||||
"width: 100%;\n",
|
|
||||||
"height: 50%;\n",
|
|
||||||
"}\n",
|
|
||||||
"#PV-B {\n",
|
|
||||||
"bottom: 0;\n",
|
|
||||||
"width: 100%;\n",
|
|
||||||
"height: 50%;\n",
|
|
||||||
"}\n",
|
|
||||||
"#PV-L {\n",
|
|
||||||
"left: 0;\n",
|
|
||||||
"width: 49.5%;\n",
|
|
||||||
"height: 100%;\n",
|
|
||||||
"float: left;\n",
|
|
||||||
"}\n",
|
|
||||||
"#PV-R {\n",
|
|
||||||
"right: 0;\n",
|
|
||||||
"width: 49.5%;\n",
|
|
||||||
"height: 100%;\n",
|
|
||||||
"float: right;\n",
|
|
||||||
"}\n",
|
|
||||||
"#PV-TL {\n",
|
|
||||||
"top: 0;\n",
|
|
||||||
"left: 0;\n",
|
|
||||||
"width: 49.5%;\n",
|
|
||||||
"height: 50%;\n",
|
|
||||||
"float: left;\n",
|
|
||||||
"}\n",
|
|
||||||
"#PV-TR {\n",
|
|
||||||
"top: 0;\n",
|
|
||||||
"right: 0;\n",
|
|
||||||
"width: 49.5%;\n",
|
|
||||||
"height: 50%;\n",
|
|
||||||
"float: right;\n",
|
|
||||||
"}\n",
|
|
||||||
"#PV-BL {\n",
|
|
||||||
"bottom: 0;\n",
|
|
||||||
"left: 0;\n",
|
|
||||||
"width: 49.5%;\n",
|
|
||||||
"height: 50%;\n",
|
|
||||||
"float: left;\n",
|
|
||||||
"}\n",
|
|
||||||
"#PV-BR {\n",
|
|
||||||
"bottom: 0;\n",
|
|
||||||
"right: 0;\n",
|
|
||||||
"width: 49.5%;\n",
|
|
||||||
"height: 50%;\n",
|
|
||||||
"float: right;\n",
|
|
||||||
"}\n",
|
|
||||||
".PV-P {\n",
|
|
||||||
"width: 100%;\n",
|
|
||||||
"height: 100%;\n",
|
|
||||||
"top: 0;\n",
|
|
||||||
"position: absolute;\n",
|
|
||||||
"display: none;\n",
|
|
||||||
"}\n"])
|
"}\n"])
|
||||||
|
if options.iskindle and options.panelview:
|
||||||
|
f.writelines(["#PV {\n",
|
||||||
|
"position: absolute;\n",
|
||||||
|
"width: 100%;\n",
|
||||||
|
"height: 100%;\n",
|
||||||
|
"top: 0;\n",
|
||||||
|
"left: 0;\n",
|
||||||
|
"}\n",
|
||||||
|
"#PV-T {\n",
|
||||||
|
"top: 0;\n",
|
||||||
|
"width: 100%;\n",
|
||||||
|
"height: 50%;\n",
|
||||||
|
"}\n",
|
||||||
|
"#PV-B {\n",
|
||||||
|
"bottom: 0;\n",
|
||||||
|
"width: 100%;\n",
|
||||||
|
"height: 50%;\n",
|
||||||
|
"}\n",
|
||||||
|
"#PV-L {\n",
|
||||||
|
"left: 0;\n",
|
||||||
|
"width: 49.5%;\n",
|
||||||
|
"height: 100%;\n",
|
||||||
|
"float: left;\n",
|
||||||
|
"}\n",
|
||||||
|
"#PV-R {\n",
|
||||||
|
"right: 0;\n",
|
||||||
|
"width: 49.5%;\n",
|
||||||
|
"height: 100%;\n",
|
||||||
|
"float: right;\n",
|
||||||
|
"}\n",
|
||||||
|
"#PV-TL {\n",
|
||||||
|
"top: 0;\n",
|
||||||
|
"left: 0;\n",
|
||||||
|
"width: 49.5%;\n",
|
||||||
|
"height: 50%;\n",
|
||||||
|
"float: left;\n",
|
||||||
|
"}\n",
|
||||||
|
"#PV-TR {\n",
|
||||||
|
"top: 0;\n",
|
||||||
|
"right: 0;\n",
|
||||||
|
"width: 49.5%;\n",
|
||||||
|
"height: 50%;\n",
|
||||||
|
"float: right;\n",
|
||||||
|
"}\n",
|
||||||
|
"#PV-BL {\n",
|
||||||
|
"bottom: 0;\n",
|
||||||
|
"left: 0;\n",
|
||||||
|
"width: 49.5%;\n",
|
||||||
|
"height: 50%;\n",
|
||||||
|
"float: left;\n",
|
||||||
|
"}\n",
|
||||||
|
"#PV-BR {\n",
|
||||||
|
"bottom: 0;\n",
|
||||||
|
"right: 0;\n",
|
||||||
|
"width: 49.5%;\n",
|
||||||
|
"height: 50%;\n",
|
||||||
|
"float: right;\n",
|
||||||
|
"}\n",
|
||||||
|
".PV-P {\n",
|
||||||
|
"width: 100%;\n",
|
||||||
|
"height: 100%;\n",
|
||||||
|
"top: 0;\n",
|
||||||
|
"position: absolute;\n",
|
||||||
|
"display: none;\n",
|
||||||
|
"}\n"])
|
||||||
f.close()
|
f.close()
|
||||||
for dirpath, dirnames, filenames in os.walk(os.path.join(path, 'OEBPS', 'Images')):
|
for dirpath, dirnames, filenames in os.walk(os.path.join(path, 'OEBPS', 'Images')):
|
||||||
chapter = False
|
chapter = False
|
||||||
@@ -439,9 +480,9 @@ def buildEPUB(path, chapterNames, tomeNumber):
|
|||||||
cover = os.path.join(os.path.join(path, 'OEBPS', 'Images'),
|
cover = os.path.join(os.path.join(path, 'OEBPS', 'Images'),
|
||||||
'cover' + getImageFileName(filelist[-1][1])[1])
|
'cover' + getImageFileName(filelist[-1][1])[1])
|
||||||
options.covers.append((image.Cover(os.path.join(filelist[-1][0], filelist[-1][1]), cover, options,
|
options.covers.append((image.Cover(os.path.join(filelist[-1][0], filelist[-1][1]), cover, options,
|
||||||
tomeNumber), options.uuid))
|
tomenumber), options.uuid))
|
||||||
# Overwrite chapternames if tree is flat and ComicInfo.xml has bookmarks
|
# Overwrite chapternames if tree is flat and ComicInfo.xml has bookmarks
|
||||||
if not chapterNames and options.chapters:
|
if not chapternames and options.chapters:
|
||||||
chapterlist = []
|
chapterlist = []
|
||||||
globaldiff = 0
|
globaldiff = 0
|
||||||
for aChapter in options.chapters:
|
for aChapter in options.chapters:
|
||||||
@@ -453,10 +494,10 @@ def buildEPUB(path, chapterNames, tomeNumber):
|
|||||||
pageid -= 1
|
pageid -= 1
|
||||||
filename = filelist[pageid][1]
|
filename = filelist[pageid][1]
|
||||||
chapterlist.append((filelist[pageid][0].replace('Images', 'Text'), filename))
|
chapterlist.append((filelist[pageid][0].replace('Images', 'Text'), filename))
|
||||||
chapterNames[filename] = aChapter[1]
|
chapternames[filename] = aChapter[1]
|
||||||
globaldiff = pageid - (aChapter[0] + globaldiff)
|
globaldiff = pageid - (aChapter[0] + globaldiff)
|
||||||
buildNCX(path, options.title, chapterlist, chapterNames)
|
buildNCX(path, options.title, chapterlist, chapternames)
|
||||||
buildNAV(path, options.title, chapterlist, chapterNames)
|
buildNAV(path, options.title, chapterlist, chapternames)
|
||||||
buildOPF(path, options.title, filelist, cover)
|
buildOPF(path, options.title, filelist, cover)
|
||||||
|
|
||||||
|
|
||||||
@@ -542,7 +583,7 @@ def getWorkFolder(afile):
|
|||||||
copytree(afile, fullPath)
|
copytree(afile, fullPath)
|
||||||
sanitizePermissions(fullPath)
|
sanitizePermissions(fullPath)
|
||||||
return workdir
|
return workdir
|
||||||
except:
|
except Exception:
|
||||||
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):
|
||||||
@@ -560,7 +601,7 @@ def getWorkFolder(afile):
|
|||||||
if cbx.isCbxFile():
|
if cbx.isCbxFile():
|
||||||
try:
|
try:
|
||||||
path = cbx.extract(workdir)
|
path = cbx.extract(workdir)
|
||||||
except:
|
except Exception:
|
||||||
rmtree(workdir, True)
|
rmtree(workdir, True)
|
||||||
raise UserWarning("Failed to extract archive.")
|
raise UserWarning("Failed to extract archive.")
|
||||||
else:
|
else:
|
||||||
@@ -575,7 +616,7 @@ def getWorkFolder(afile):
|
|||||||
return newpath
|
return newpath
|
||||||
|
|
||||||
|
|
||||||
def getOutputFilename(srcpath, wantedname, ext, tomeNumber):
|
def getOutputFilename(srcpath, wantedname, ext, tomenumber):
|
||||||
if srcpath[-1] == os.path.sep:
|
if srcpath[-1] == os.path.sep:
|
||||||
srcpath = srcpath[:-1]
|
srcpath = srcpath[:-1]
|
||||||
if 'Ko' in options.profile and options.format == 'EPUB':
|
if 'Ko' in options.profile and options.format == 'EPUB':
|
||||||
@@ -589,16 +630,16 @@ def getOutputFilename(srcpath, wantedname, ext, tomeNumber):
|
|||||||
filename = os.path.join(os.path.abspath(options.output),
|
filename = os.path.join(os.path.abspath(options.output),
|
||||||
os.path.basename(os.path.splitext(srcpath)[0]) + ext)
|
os.path.basename(os.path.splitext(srcpath)[0]) + ext)
|
||||||
elif os.path.isdir(srcpath):
|
elif os.path.isdir(srcpath):
|
||||||
filename = srcpath + tomeNumber + ext
|
filename = srcpath + tomenumber + ext
|
||||||
else:
|
else:
|
||||||
if 'Ko' in options.profile and options.format == 'EPUB':
|
if 'Ko' in options.profile and options.format == 'EPUB':
|
||||||
path = srcpath.split(os.path.sep)
|
path = srcpath.split(os.path.sep)
|
||||||
path[-1] = ''.join(e for e in path[-1].split('.')[0] if e.isalnum()) + tomeNumber + ext
|
path[-1] = ''.join(e for e in path[-1].split('.')[0] if e.isalnum()) + tomenumber + ext
|
||||||
if not path[-1].split('.')[0]:
|
if not path[-1].split('.')[0]:
|
||||||
path[-1] = 'KCCPlaceholder' + tomeNumber + ext
|
path[-1] = 'KCCPlaceholder' + tomenumber + ext
|
||||||
filename = os.path.sep.join(path)
|
filename = os.path.sep.join(path)
|
||||||
else:
|
else:
|
||||||
filename = os.path.splitext(srcpath)[0] + tomeNumber + ext
|
filename = os.path.splitext(srcpath)[0] + tomenumber + ext
|
||||||
if os.path.isfile(filename):
|
if os.path.isfile(filename):
|
||||||
counter = 0
|
counter = 0
|
||||||
basename = os.path.splitext(filename)[0]
|
basename = os.path.splitext(filename)[0]
|
||||||
@@ -608,7 +649,7 @@ def getOutputFilename(srcpath, wantedname, ext, tomeNumber):
|
|||||||
return filename
|
return filename
|
||||||
|
|
||||||
|
|
||||||
def getComicInfo(path, originalPath):
|
def getComicInfo(path, originalpath):
|
||||||
xmlPath = os.path.join(path, 'ComicInfo.xml')
|
xmlPath = os.path.join(path, 'ComicInfo.xml')
|
||||||
options.authors = ['KCC']
|
options.authors = ['KCC']
|
||||||
options.remoteCovers = {}
|
options.remoteCovers = {}
|
||||||
@@ -617,10 +658,10 @@ def getComicInfo(path, originalPath):
|
|||||||
titleSuffix = ''
|
titleSuffix = ''
|
||||||
if options.title == 'defaulttitle':
|
if options.title == 'defaulttitle':
|
||||||
defaultTitle = True
|
defaultTitle = True
|
||||||
if os.path.isdir(originalPath):
|
if os.path.isdir(originalpath):
|
||||||
options.title = os.path.basename(originalPath)
|
options.title = os.path.basename(originalpath)
|
||||||
else:
|
else:
|
||||||
options.title = os.path.splitext(os.path.basename(originalPath))[0]
|
options.title = os.path.splitext(os.path.basename(originalpath))[0]
|
||||||
else:
|
else:
|
||||||
defaultTitle = False
|
defaultTitle = False
|
||||||
if os.path.exists(xmlPath):
|
if os.path.exists(xmlPath):
|
||||||
@@ -655,10 +696,10 @@ def getComicInfo(path, originalPath):
|
|||||||
os.remove(xmlPath)
|
os.remove(xmlPath)
|
||||||
|
|
||||||
|
|
||||||
def getCoversFromMCB(mangaID):
|
def getCoversFromMCB(mangaid):
|
||||||
covers = {}
|
covers = {}
|
||||||
try:
|
try:
|
||||||
jsonRaw = urlopen(Request('http://mcd.iosphe.re/api/v1/series/' + mangaID + '/',
|
jsonRaw = urlopen(Request('http://mcd.iosphe.re/api/v1/series/' + mangaid + '/',
|
||||||
headers={'User-Agent': 'KindleComicConverter/' + __version__}))
|
headers={'User-Agent': 'KindleComicConverter/' + __version__}))
|
||||||
jsonData = loads(jsonRaw.read().decode('utf-8'))
|
jsonData = loads(jsonRaw.read().decode('utf-8'))
|
||||||
for volume in jsonData['Covers']['a']:
|
for volume in jsonData['Covers']['a']:
|
||||||
@@ -683,9 +724,9 @@ def getTopMargin(deviceres, size):
|
|||||||
return str(round(y, 1))
|
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])
|
||||||
|
|
||||||
|
|
||||||
def getPanelViewSize(deviceres, size):
|
def getPanelViewSize(deviceres, size):
|
||||||
@@ -804,19 +845,19 @@ def splitProcess(path, mode):
|
|||||||
return output
|
return output
|
||||||
|
|
||||||
|
|
||||||
def detectCorruption(tmpPath, orgPath):
|
def detectCorruption(tmppath, orgpath):
|
||||||
imageNumber = 0
|
imageNumber = 0
|
||||||
imageSmaller = 0
|
imageSmaller = 0
|
||||||
alreadyProcessed = False
|
alreadyProcessed = False
|
||||||
for root, _, files in os.walk(tmpPath, False):
|
for root, _, files in os.walk(tmppath, False):
|
||||||
for name in files:
|
for name in files:
|
||||||
if getImageFileName(name) is not None:
|
if getImageFileName(name) is not None:
|
||||||
if not alreadyProcessed and getImageFileName(name)[0].endswith('-kcc'):
|
if not alreadyProcessed and getImageFileName(name)[0].endswith('-kcc'):
|
||||||
alreadyProcessed = True
|
alreadyProcessed = True
|
||||||
path = os.path.join(root, name)
|
path = os.path.join(root, name)
|
||||||
pathOrg = orgPath + path.split('OEBPS' + os.path.sep + 'Images')[1]
|
pathOrg = orgpath + path.split('OEBPS' + os.path.sep + 'Images')[1]
|
||||||
if os.path.getsize(path) == 0:
|
if os.path.getsize(path) == 0:
|
||||||
rmtree(os.path.join(tmpPath, '..', '..'), True)
|
rmtree(os.path.join(tmppath, '..', '..'), True)
|
||||||
raise RuntimeError('Image file %s is corrupted.' % pathOrg)
|
raise RuntimeError('Image file %s is corrupted.' % pathOrg)
|
||||||
try:
|
try:
|
||||||
img = Image.open(path)
|
img = Image.open(path)
|
||||||
@@ -827,7 +868,7 @@ def detectCorruption(tmpPath, orgPath):
|
|||||||
if options.profileData[1][0] > img.size[0] and options.profileData[1][1] > img.size[1]:
|
if options.profileData[1][0] > img.size[0] and options.profileData[1][1] > img.size[1]:
|
||||||
imageSmaller += 1
|
imageSmaller += 1
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
rmtree(os.path.join(tmpPath, '..', '..'), True)
|
rmtree(os.path.join(tmppath, '..', '..'), True)
|
||||||
if 'decoder' in str(err) and 'not available' in str(err):
|
if 'decoder' in str(err) and 'not available' in str(err):
|
||||||
raise RuntimeError('Pillow was compiled without JPG and/or PNG decoder.')
|
raise RuntimeError('Pillow was compiled without JPG and/or PNG decoder.')
|
||||||
else:
|
else:
|
||||||
@@ -856,28 +897,28 @@ def createNewTome():
|
|||||||
return tomePath, tomePathRoot
|
return tomePath, tomePathRoot
|
||||||
|
|
||||||
|
|
||||||
def slugify(value, isDir):
|
def slugify(value, isdir):
|
||||||
if isDir:
|
if isdir:
|
||||||
value = slugifyExt(value, regex_pattern=r'[^-a-z0-9_\.]+')
|
value = slugifyExt(value, regex_pattern=r'[^-a-z0-9_\.]+').strip('.')
|
||||||
else:
|
else:
|
||||||
value = slugifyExt(value)
|
value = slugifyExt(value).strip('.')
|
||||||
value = sub(r'0*([0-9]{4,})', r'\1', sub(r'([0-9]+)', r'0000\1', value, count=2))
|
value = sub(r'0*([0-9]{4,})', r'\1', sub(r'([0-9]+)', r'0000\1', value, count=2))
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def makeZIP(zipFilename, baseDir, isEPUB=False):
|
def makeZIP(zipfilename, basedir, isepub=False):
|
||||||
zipFilename = os.path.abspath(zipFilename) + '.zip'
|
zipfilename = os.path.abspath(zipfilename) + '.zip'
|
||||||
zipOutput = ZipFile(zipFilename, 'w', ZIP_DEFLATED)
|
zipOutput = ZipFile(zipfilename, 'w', ZIP_DEFLATED)
|
||||||
if isEPUB:
|
if isepub:
|
||||||
zipOutput.writestr('mimetype', 'application/epub+zip', ZIP_STORED)
|
zipOutput.writestr('mimetype', 'application/epub+zip', ZIP_STORED)
|
||||||
for dirpath, _, filenames in os.walk(baseDir):
|
for dirpath, _, filenames in os.walk(basedir):
|
||||||
for name in filenames:
|
for name in filenames:
|
||||||
path = os.path.normpath(os.path.join(dirpath, name))
|
path = os.path.normpath(os.path.join(dirpath, name))
|
||||||
aPath = os.path.normpath(os.path.join(dirpath.replace(baseDir, ''), name))
|
aPath = os.path.normpath(os.path.join(dirpath.replace(basedir, ''), name))
|
||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
zipOutput.write(path, aPath)
|
zipOutput.write(path, aPath)
|
||||||
zipOutput.close()
|
zipOutput.close()
|
||||||
return zipFilename
|
return zipfilename
|
||||||
|
|
||||||
|
|
||||||
def makeParser():
|
def makeParser():
|
||||||
@@ -906,7 +947,7 @@ def makeParser():
|
|||||||
outputOptions.add_option("-t", "--title", action="store", dest="title", default="defaulttitle",
|
outputOptions.add_option("-t", "--title", action="store", dest="title", default="defaulttitle",
|
||||||
help="Comic title [Default=filename or directory name]")
|
help="Comic title [Default=filename or directory name]")
|
||||||
outputOptions.add_option("-f", "--format", action="store", dest="format", default="Auto",
|
outputOptions.add_option("-f", "--format", action="store", dest="format", default="Auto",
|
||||||
help="Output format (Available options: Auto, MOBI, EPUB, CBZ) [Default=Auto]")
|
help="Output format (Available options: Auto, MOBI, EPUB, CBZ, KFX) [Default=Auto]")
|
||||||
outputOptions.add_option("-b", "--batchsplit", type="int", dest="batchsplit", default="0",
|
outputOptions.add_option("-b", "--batchsplit", type="int", dest="batchsplit", default="0",
|
||||||
help="Split output into multiple files. 0: Don't split 1: Automatic mode "
|
help="Split output into multiple files. 0: Don't split 1: Automatic mode "
|
||||||
"2: Consider every subdirectory as separate volume [Default=0]")
|
"2: Consider every subdirectory as separate volume [Default=0]")
|
||||||
@@ -953,6 +994,7 @@ def checkOptions():
|
|||||||
options.panelview = True
|
options.panelview = True
|
||||||
options.iskindle = False
|
options.iskindle = False
|
||||||
options.bordersColor = None
|
options.bordersColor = None
|
||||||
|
options.kfx = False
|
||||||
if options.format == 'Auto':
|
if options.format == 'Auto':
|
||||||
if options.profile in ['K1', 'K2', 'K34', 'K578', 'KPW', 'KV', 'KO']:
|
if options.profile in ['K1', 'K2', 'K34', 'K578', 'KPW', 'KV', 'KO']:
|
||||||
options.format = 'MOBI'
|
options.format = 'MOBI'
|
||||||
@@ -967,7 +1009,7 @@ def checkOptions():
|
|||||||
if options.black_borders:
|
if options.black_borders:
|
||||||
options.bordersColor = 'black'
|
options.bordersColor = 'black'
|
||||||
# Splitting MOBI is not optional
|
# Splitting MOBI is not optional
|
||||||
if options.format == 'MOBI' and options.batchsplit != 2:
|
if (options.format == 'MOBI' or options.format == 'KFX') and options.batchsplit != 2:
|
||||||
options.batchsplit = 1
|
options.batchsplit = 1
|
||||||
# Older Kindle models don't support Panel View.
|
# Older Kindle models don't support Panel View.
|
||||||
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'K34' or options.profile == 'KDX':
|
if options.profile == 'K1' or options.profile == 'K2' or options.profile == 'K34' or options.profile == 'KDX':
|
||||||
@@ -989,6 +1031,11 @@ def checkOptions():
|
|||||||
# CBZ files on Kindle DX/DXG support higher resolution
|
# CBZ files on Kindle DX/DXG support higher resolution
|
||||||
if options.profile == 'KDX' and options.format == 'CBZ':
|
if options.profile == 'KDX' and options.format == 'CBZ':
|
||||||
options.customheight = 1200
|
options.customheight = 1200
|
||||||
|
# KFX output create EPUB that might be can be by jhowell KFX Output Calibre plugin
|
||||||
|
if options.format == 'KFX':
|
||||||
|
options.format = 'EPUB'
|
||||||
|
options.kfx = True
|
||||||
|
options.panelview = False
|
||||||
# Override profile data
|
# Override profile data
|
||||||
if options.customwidth != 0 or options.customheight != 0:
|
if options.customwidth != 0 or options.customheight != 0:
|
||||||
X = image.ProfileData.Profiles[options.profile][1][0]
|
X = image.ProfileData.Profiles[options.profile][1][0]
|
||||||
@@ -1039,13 +1086,13 @@ def checkPre(source):
|
|||||||
try:
|
try:
|
||||||
with TemporaryFile(prefix='KCC-', dir=src):
|
with TemporaryFile(prefix='KCC-', dir=src):
|
||||||
pass
|
pass
|
||||||
except:
|
except Exception:
|
||||||
raise UserWarning("Target directory is not writable.")
|
raise UserWarning("Target directory is not writable.")
|
||||||
|
|
||||||
|
|
||||||
def makeBook(source, qtGUI=None):
|
def makeBook(source, qtgui=None):
|
||||||
global GUI
|
global GUI
|
||||||
GUI = qtGUI
|
GUI = qtgui
|
||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('1')
|
GUI.progressBarTick.emit('1')
|
||||||
else:
|
else:
|
||||||
@@ -1061,7 +1108,7 @@ def makeBook(source, qtGUI=None):
|
|||||||
y = 1024
|
y = 1024
|
||||||
else:
|
else:
|
||||||
y = image.ProfileData.Profiles[options.profile][1][1]
|
y = image.ProfileData.Profiles[options.profile][1][1]
|
||||||
comic2panel.main(['-y ' + str(y), '-i', '-m', path], qtGUI)
|
comic2panel.main(['-y ' + str(y), '-i', '-m', path], qtgui)
|
||||||
print("Processing images...")
|
print("Processing images...")
|
||||||
if GUI:
|
if GUI:
|
||||||
GUI.progressBarTick.emit('Processing images')
|
GUI.progressBarTick.emit('Processing images')
|
||||||
@@ -1192,9 +1239,9 @@ def makeMOBIWorker(item):
|
|||||||
return [kindlegenErrorCode, kindlegenError, item]
|
return [kindlegenErrorCode, kindlegenError, item]
|
||||||
|
|
||||||
|
|
||||||
def makeMOBI(work, qtGUI=None):
|
def makeMOBI(work, qtgui=None):
|
||||||
global GUI, makeMOBIWorkerPool, makeMOBIWorkerOutput
|
global GUI, makeMOBIWorkerPool, makeMOBIWorkerOutput
|
||||||
GUI = qtGUI
|
GUI = qtgui
|
||||||
makeMOBIWorkerOutput = []
|
makeMOBIWorkerOutput = []
|
||||||
availableMemory = virtual_memory().total / 1000000000
|
availableMemory = virtual_memory().total / 1000000000
|
||||||
if availableMemory <= 2:
|
if availableMemory <= 2:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -93,6 +93,7 @@ def splitImageTick(output):
|
|||||||
splitWorkerPool.terminate()
|
splitWorkerPool.terminate()
|
||||||
|
|
||||||
|
|
||||||
|
# noinspection PyUnboundLocalVariable
|
||||||
def splitImage(work):
|
def splitImage(work):
|
||||||
try:
|
try:
|
||||||
path = work[0]
|
path = work[0]
|
||||||
@@ -140,9 +141,7 @@ def splitImage(work):
|
|||||||
|
|
||||||
if opt.debug:
|
if opt.debug:
|
||||||
for panel in panelsProcessed:
|
for panel in panelsProcessed:
|
||||||
# noinspection PyUnboundLocalVariable
|
|
||||||
draw.rectangle([(0, panel[0]), (widthImg, panel[1])], (0, 255, 0, 128), (0, 0, 255, 255))
|
draw.rectangle([(0, panel[0]), (widthImg, panel[1])], (0, 255, 0, 128), (0, 0, 255, 255))
|
||||||
# noinspection PyUnboundLocalVariable
|
|
||||||
debugImage = Image.alpha_composite(imgOrg.convert(mode='RGBA'), drawImg)
|
debugImage = Image.alpha_composite(imgOrg.convert(mode='RGBA'), drawImg)
|
||||||
debugImage.save(os.path.join(path, os.path.splitext(name)[0] + '-debug.png'), 'PNG')
|
debugImage.save(os.path.join(path, os.path.splitext(name)[0] + '-debug.png'), 'PNG')
|
||||||
|
|
||||||
@@ -185,7 +184,7 @@ def splitImage(work):
|
|||||||
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
|
return str(sys.exc_info()[1]), sanitizeTrace(sys.exc_info()[2])
|
||||||
|
|
||||||
|
|
||||||
def main(argv=None, qtGUI=None):
|
def main(argv=None, qtgui=None):
|
||||||
global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
|
global options, GUI, splitWorkerPool, splitWorkerOutput, mergeWorkerPool, mergeWorkerOutput
|
||||||
parser = OptionParser(usage="Usage: kcc-c2p [options] comic_folder", add_help_option=False)
|
parser = OptionParser(usage="Usage: kcc-c2p [options] comic_folder", add_help_option=False)
|
||||||
mainOptions = OptionGroup(parser, "MANDATORY")
|
mainOptions = OptionGroup(parser, "MANDATORY")
|
||||||
@@ -203,8 +202,8 @@ def main(argv=None, qtGUI=None):
|
|||||||
parser.add_option_group(mainOptions)
|
parser.add_option_group(mainOptions)
|
||||||
parser.add_option_group(otherOptions)
|
parser.add_option_group(otherOptions)
|
||||||
options, args = parser.parse_args(argv)
|
options, args = parser.parse_args(argv)
|
||||||
if qtGUI:
|
if qtgui:
|
||||||
GUI = qtGUI
|
GUI = qtgui
|
||||||
else:
|
else:
|
||||||
GUI = None
|
GUI = None
|
||||||
if len(args) != 1:
|
if len(args) != 1:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Based on initial version of DualMetaFix. Copyright (C) 2013 Kevin Hendricks
|
# Based on initial version of DualMetaFix. Copyright (C) 2013 Kevin Hendricks
|
||||||
# Changes for KCC Copyright (C) 2014-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Changes for KCC Copyright (C) 2014-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
|
# Copyright (C) 2011 Stanislav (proDOOMman) Kosolapov <prodoomman@gmail.com>
|
||||||
# Copyright (c) 2016 Alberto Planas <aplanas@gmail.com>
|
# Copyright (c) 2016 Alberto Planas <aplanas@gmail.com>
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -273,17 +273,17 @@ class ComicPage:
|
|||||||
method = Image.BICUBIC
|
method = Image.BICUBIC
|
||||||
else:
|
else:
|
||||||
method = Image.LANCZOS
|
method = Image.LANCZOS
|
||||||
if self.opt.stretch:
|
if self.opt.stretch or (self.opt.kfx and ('-KCC-B' in self.targetPath or '-KCC-C' in self.targetPath)):
|
||||||
self.image = self.image.resize(self.size, method)
|
self.image = self.image.resize(self.size, method)
|
||||||
elif self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1] and not self.opt.upscale:
|
elif self.image.size[0] <= self.size[0] and self.image.size[1] <= self.size[1] and not self.opt.upscale:
|
||||||
if self.opt.format == 'CBZ':
|
if self.opt.format == 'CBZ' or self.opt.kfx:
|
||||||
borderw = int((self.size[0] - self.image.size[0]) / 2)
|
borderw = int((self.size[0] - self.image.size[0]) / 2)
|
||||||
borderh = int((self.size[1] - self.image.size[1]) / 2)
|
borderh = int((self.size[1] - self.image.size[1]) / 2)
|
||||||
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=self.fill)
|
self.image = ImageOps.expand(self.image, border=(borderw, borderh), fill=self.fill)
|
||||||
if self.image.size[0] != self.size[0] or self.image.size[1] != self.size[1]:
|
if self.image.size[0] != self.size[0] or self.image.size[1] != self.size[1]:
|
||||||
self.image = ImageOps.fit(self.image, self.size, method=Image.BICUBIC, centering=(0.5, 0.5))
|
self.image = ImageOps.fit(self.image, self.size, method=Image.BICUBIC, centering=(0.5, 0.5))
|
||||||
else:
|
else:
|
||||||
if self.opt.format == 'CBZ':
|
if self.opt.format == 'CBZ' or self.opt.kfx:
|
||||||
ratioDev = float(self.size[0]) / float(self.size[1])
|
ratioDev = float(self.size[0]) / float(self.size[1])
|
||||||
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
|
if (float(self.image.size[0]) / float(self.image.size[1])) < ratioDev:
|
||||||
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
diff = int(self.image.size[1] * ratioDev) - self.image.size[0]
|
||||||
@@ -299,53 +299,53 @@ class ComicPage:
|
|||||||
if self.image.size[0] > self.size[0] or self.image.size[1] > self.size[1]:
|
if self.image.size[0] > self.size[0] or self.image.size[1] > self.size[1]:
|
||||||
self.image.thumbnail(self.size, Image.LANCZOS)
|
self.image.thumbnail(self.size, Image.LANCZOS)
|
||||||
|
|
||||||
def getBoundingBox(self, tmpImg):
|
def getBoundingBox(self, tmptmg):
|
||||||
min_margin = [int(0.005 * i + 0.5) for i in tmpImg.size]
|
min_margin = [int(0.005 * i + 0.5) for i in tmptmg.size]
|
||||||
max_margin = [int(0.1 * i + 0.5) for i in tmpImg.size]
|
max_margin = [int(0.1 * i + 0.5) for i in tmptmg.size]
|
||||||
bbox = tmpImg.getbbox()
|
bbox = tmptmg.getbbox()
|
||||||
bbox = (
|
bbox = (
|
||||||
max(0, min(max_margin[0], bbox[0] - min_margin[0])),
|
max(0, min(max_margin[0], bbox[0] - min_margin[0])),
|
||||||
max(0, min(max_margin[1], bbox[1] - min_margin[1])),
|
max(0, min(max_margin[1], bbox[1] - min_margin[1])),
|
||||||
min(tmpImg.size[0],
|
min(tmptmg.size[0],
|
||||||
max(tmpImg.size[0] - max_margin[0], bbox[2] + min_margin[0])),
|
max(tmptmg.size[0] - max_margin[0], bbox[2] + min_margin[0])),
|
||||||
min(tmpImg.size[1],
|
min(tmptmg.size[1],
|
||||||
max(tmpImg.size[1] - max_margin[1], bbox[3] + min_margin[1])),
|
max(tmptmg.size[1] - max_margin[1], bbox[3] + min_margin[1])),
|
||||||
)
|
)
|
||||||
return bbox
|
return bbox
|
||||||
|
|
||||||
def cropPageNumber(self, power):
|
def cropPageNumber(self, power):
|
||||||
if self.fill != 'white':
|
if self.fill != 'white':
|
||||||
tmpImg = self.image.convert(mode='L')
|
tmptmg = self.image.convert(mode='L')
|
||||||
else:
|
else:
|
||||||
tmpImg = ImageOps.invert(self.image.convert(mode='L'))
|
tmptmg = ImageOps.invert(self.image.convert(mode='L'))
|
||||||
tmpImg = tmpImg.point(lambda x: x and 255)
|
tmptmg = tmptmg.point(lambda x: x and 255)
|
||||||
tmpImg = tmpImg.filter(ImageFilter.MinFilter(size=3))
|
tmptmg = tmptmg.filter(ImageFilter.MinFilter(size=3))
|
||||||
tmpImg = tmpImg.filter(ImageFilter.GaussianBlur(radius=5))
|
tmptmg = tmptmg.filter(ImageFilter.GaussianBlur(radius=5))
|
||||||
tmpImg = tmpImg.point(lambda x: (x >= 16 * power) and x)
|
tmptmg = tmptmg.point(lambda x: (x >= 16 * power) and x)
|
||||||
self.image = self.image.crop(tmpImg.getbbox()) if tmpImg.getbbox() else self.image
|
self.image = self.image.crop(tmptmg.getbbox()) if tmptmg.getbbox() else self.image
|
||||||
|
|
||||||
def cropMargin(self, power):
|
def cropMargin(self, power):
|
||||||
if self.fill != 'white':
|
if self.fill != 'white':
|
||||||
tmpImg = self.image.convert(mode='L')
|
tmptmg = self.image.convert(mode='L')
|
||||||
else:
|
else:
|
||||||
tmpImg = ImageOps.invert(self.image.convert(mode='L'))
|
tmptmg = ImageOps.invert(self.image.convert(mode='L'))
|
||||||
tmpImg = tmpImg.filter(ImageFilter.GaussianBlur(radius=3))
|
tmptmg = tmptmg.filter(ImageFilter.GaussianBlur(radius=3))
|
||||||
tmpImg = tmpImg.point(lambda x: (x >= 16 * power) and x)
|
tmptmg = tmptmg.point(lambda x: (x >= 16 * power) and x)
|
||||||
self.image = self.image.crop(self.getBoundingBox(tmpImg)) if tmpImg.getbbox() else self.image
|
self.image = self.image.crop(self.getBoundingBox(tmptmg)) if tmptmg.getbbox() else self.image
|
||||||
|
|
||||||
|
|
||||||
class Cover:
|
class Cover:
|
||||||
def __init__(self, source, target, opt, tomeNumber):
|
def __init__(self, source, target, opt, tomeid):
|
||||||
self.options = opt
|
self.options = opt
|
||||||
self.source = source
|
self.source = source
|
||||||
self.target = target
|
self.target = target
|
||||||
if tomeNumber == 0:
|
if tomeid == 0:
|
||||||
self.tomeNumber = 1
|
self.tomeid = 1
|
||||||
else:
|
else:
|
||||||
self.tomeNumber = tomeNumber
|
self.tomeid = tomeid
|
||||||
if self.tomeNumber in self.options.remoteCovers:
|
if self.tomeid in self.options.remoteCovers:
|
||||||
try:
|
try:
|
||||||
source = urlopen(Request(quote(self.options.remoteCovers[self.tomeNumber]).replace('%3A', ':', 1),
|
source = urlopen(Request(quote(self.options.remoteCovers[self.tomeid]).replace('%3A', ':', 1),
|
||||||
headers={'User-Agent': 'KindleComicConverter/' + __version__})).read()
|
headers={'User-Agent': 'KindleComicConverter/' + __version__})).read()
|
||||||
self.image = Image.open(BytesIO(source))
|
self.image = Image.open(BytesIO(source))
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Based upon the code snippet by Ned Batchelder
|
# Based upon the code snippet by Ned Batchelder
|
||||||
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
|
# (http://nedbatchelder.com/blog/200712/extracting_jpgs_from_pdfs.html)
|
||||||
@@ -25,17 +25,16 @@ from string import ascii_uppercase, digits
|
|||||||
|
|
||||||
|
|
||||||
class PdfJpgExtract:
|
class PdfJpgExtract:
|
||||||
def __init__(self, origFileName):
|
def __init__(self, fname):
|
||||||
self.origFileName = origFileName
|
self.fname = fname
|
||||||
self.filename = os.path.splitext(origFileName)
|
self.filename = os.path.splitext(fname)
|
||||||
# noinspection PyUnusedLocal
|
self.path = self.filename[0] + "-KCC-" + ''.join(choice(ascii_uppercase + digits) for _ in range(3))
|
||||||
self.path = self.filename[0] + "-KCC-" + ''.join(choice(ascii_uppercase + digits) for x in range(3))
|
|
||||||
|
|
||||||
def getPath(self):
|
def getPath(self):
|
||||||
return self.path
|
return self.path
|
||||||
|
|
||||||
def extract(self):
|
def extract(self):
|
||||||
pdf = open(self.origFileName, "rb").read()
|
pdf = open(self.fname, "rb").read()
|
||||||
startmark = b"\xff\xd8"
|
startmark = b"\xff\xd8"
|
||||||
startfix = 0
|
startfix = 0
|
||||||
endmark = b"\xff\xd9"
|
endmark = b"\xff\xd9"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
@@ -73,8 +73,8 @@ def walkLevel(some_dir, level=1):
|
|||||||
del dirs[:]
|
del dirs[:]
|
||||||
|
|
||||||
|
|
||||||
def md5Checksum(filePath):
|
def md5Checksum(fpath):
|
||||||
with open(filePath, 'rb') as fh:
|
with open(fpath, 'rb') as fh:
|
||||||
m = md5()
|
m = md5()
|
||||||
while True:
|
while True:
|
||||||
data = fh.read(8192)
|
data = fh.read(8192)
|
||||||
@@ -84,8 +84,8 @@ def md5Checksum(filePath):
|
|||||||
return m.hexdigest()
|
return m.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
def check7ZFile(filePath):
|
def check7ZFile(fpath):
|
||||||
with open(filePath, 'rb') as fh:
|
with open(fpath, 'rb') as fh:
|
||||||
header = fh.read(6)
|
header = fh.read(6)
|
||||||
return header == b"7z\xbc\xaf'\x1c"
|
return header == b"7z\xbc\xaf'\x1c"
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
# Copyright (c) 2012-2014 Ciro Mattia Gonano <ciromattia@gmail.com>
|
||||||
# Copyright (c) 2013-2017 Pawel Jastrzebski <pawelj@iosphe.re>
|
# Copyright (c) 2013-2018 Pawel Jastrzebski <pawelj@iosphe.re>
|
||||||
#
|
#
|
||||||
# Permission to use, copy, modify, and/or distribute this software for
|
# Permission to use, copy, modify, and/or distribute this software for
|
||||||
# any purpose with or without fee is hereby granted, provided that the
|
# any purpose with or without fee is hereby granted, provided that the
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>MacOS/Kindle Comic Converter</string>
|
<string>MacOS/Kindle Comic Converter</string>
|
||||||
<key>CFBundleGetInfoString</key>
|
<key>CFBundleGetInfoString</key>
|
||||||
<string>KindleComicConverter 5.4.3, written 2012-2017 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
|
<string>KindleComicConverter 5.4.4, written 2012-2018 by Ciro Mattia Gonano and Pawel Jastrzebski</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>comic2ebook.icns</string>
|
<string>comic2ebook.icns</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
@@ -42,11 +42,11 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.4.3</string>
|
<string>5.4.4</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>5.4.3</string>
|
<string>5.4.4</string>
|
||||||
<key>LSEnvironment</key>
|
<key>LSEnvironment</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>PATH</key>
|
<key>PATH</key>
|
||||||
|
|||||||
Binary file not shown.
@@ -1,4 +0,0 @@
|
|||||||
@echo off
|
|
||||||
verpatch\lib\win\verpatch dist\KCC.exe %1 /va /pv %1 /s product "Kindle Comic Converter" /s description "Kindle Comic Converter" /s copyright "Copyright (C) 2012-2017 Ciro Mattia Gonano and Pawel Jastrzebski"
|
|
||||||
"C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe" sign /f "%APPVEYOR_BUILD_FOLDER%\other\windows\Cert.pfx" /p "%CERT_PASS%" /t http://time.certum.pl /d "Kindle Comic Converter" /du "http://kcc.iosphe.re/" dist/KCC.exe
|
|
||||||
iscc /SSignTool="""C:\Program Files (x86)\Windows Kits\8.1\bin\x64\signtool.exe"" sign /f ""%APPVEYOR_BUILD_FOLDER%\other\windows\Cert.pfx"" /p ""%CERT_PASS%"" /t http://time.certum.pl $p" kcc.iss >nul 2>&1
|
|
||||||
4
setup.py
4
setup.py
@@ -47,10 +47,6 @@ class BuildBinaryCommand(distutils.cmd.Command):
|
|||||||
exit(0)
|
exit(0)
|
||||||
elif sys.platform == 'win32':
|
elif sys.platform == 'win32':
|
||||||
os.system('pyinstaller -y -F -i icons\comic2ebook.ico -n KCC -w --noupx kcc.py')
|
os.system('pyinstaller -y -F -i icons\comic2ebook.ico -n KCC -w --noupx kcc.py')
|
||||||
if os.getenv('APPVEYOR'):
|
|
||||||
if len(VERSION) == 3:
|
|
||||||
VERSION = VERSION + '.0'
|
|
||||||
os.system('setup.bat ' + VERSION)
|
|
||||||
exit(0)
|
exit(0)
|
||||||
else:
|
else:
|
||||||
os.system('pyinstaller -y -F kcc.py')
|
os.system('pyinstaller -y -F kcc.py')
|
||||||
|
|||||||
Reference in New Issue
Block a user