This commit is contained in:
Alex Yatskov 2016-09-06 21:15:41 -07:00
commit 87701a38ec
6 changed files with 97 additions and 64 deletions

28
.gitignore vendored
View File

@ -5,3 +5,31 @@ dist
*.mngl *.mngl
*.cbz *.cbz
*.bat *.bat
.idea/
*.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

View File

@ -45,7 +45,7 @@ def natural_key(string_):
class Book(object): class Book(object):
DefaultDevice = 'Kindle Paperwhite' DefaultDevice = 'Kindle Paperwhite 3/Voyage/Oasis'
DefaultOutputFormat = 'CBZ only' DefaultOutputFormat = 'CBZ only'
DefaultOverwrite = True DefaultOverwrite = True
DefaultImageFlags = ImageFlags.Orient | ImageFlags.Resize | ImageFlags.Quantize DefaultImageFlags = ImageFlags.Orient | ImageFlags.Resize | ImageFlags.Quantize

View File

@ -36,6 +36,7 @@ class DialogConvert(QtGui.QProgressDialog):
self.setWindowTitle('Exporting book...') self.setWindowTitle('Exporting book...')
self.setMaximum(len(self.book.images)) self.setMaximum(len(self.book.images))
self.setValue(0) self.setValue(0)
self.increment = 0
self.archive = None self.archive = None
if 'CBZ' in self.book.outputFormat: if 'CBZ' in self.book.outputFormat:
@ -79,7 +80,8 @@ class DialogConvert(QtGui.QProgressDialog):
def onTimer(self): def onTimer(self):
index = self.value() index = self.value()
target = os.path.join(self.bookPath, '%05d.png' % index) pages_split = self.increment
target = os.path.join(self.bookPath, '%05d.png' % (index + pages_split))
source = unicode(self.book.images[index]) source = unicode(self.book.images[index])
if index == 0: if index == 0:
@ -121,30 +123,34 @@ class DialogConvert(QtGui.QProgressDialog):
archive = self.archive archive = self.archive
pdf = self.pdf pdf = self.pdf
# Maybe the user ask for a split, but the picture is not a large one, so skip # Check if page wide enough to split
# it but only for this picture if (flags & ImageFlags.SplitRightLeft) or (flags & ImageFlags.SplitLeftRight):
if (flags & ImageFlags.Split) or (flags & ImageFlags.SplitInverse):
if not image.isSplitable(source): if not image.isSplitable(source):
# remove split flags # remove split flags
splitFlags= [ImageFlags.Split, ImageFlags.SplitInverse, ImageFlags.SplitRight, ImageFlags.SplitLeft] splitFlags = [ImageFlags.SplitRightLeft, ImageFlags.SplitLeftRight, ImageFlags.SplitRight,
ImageFlags.SplitLeft]
for f in splitFlags: for f in splitFlags:
flags &= ~f flags &= ~f
# For right page (if requested in options and need for this image) # For right page (if requested in options and need for this image)
if (flags & ImageFlags.Split): if flags & ImageFlags.SplitRightLeft:
# New path based on modified index self.convertAndSave(source, target, device,
target = os.path.join(self.bookPath, '%05d.png' % (index * 2 + 0)) flags ^ ImageFlags.SplitRightLeft | ImageFlags.SplitRight,
self.convertAndSave(source, target, device, flags ^ ImageFlags.Split | ImageFlags.SplitRight, archive, pdf) archive, pdf)
# Change target once again for left page
target = os.path.join(self.bookPath, '%05d.png' % (index * 2 + 1)) # Change target for left page
target = os.path.join(self.bookPath, '%05d.png' % (index + pages_split + 1))
self.increment += 1
# For right page (if requested), but in inverted mode # For right page (if requested), but in inverted mode
if (flags & ImageFlags.SplitInverse): if flags & ImageFlags.SplitLeftRight:
# New path based on modified index self.convertAndSave(source, target, device,
target = os.path.join(self.bookPath, '%05d.png' % (index * 2 + 0)) flags ^ ImageFlags.SplitLeftRight | ImageFlags.SplitLeft,
self.convertAndSave(source, target, device, flags ^ ImageFlags.SplitInverse | ImageFlags.SplitLeft, archive, pdf) archive, pdf)
# Change target once again for left page
target = os.path.join(self.bookPath, '%05d.png' % (index * 2 + 1)) # Change target for left page
target = os.path.join(self.bookPath, '%05d.png' % (index + pages_split + 1))
self.increment += 1
# Convert page # Convert page
self.convertAndSave(source, target, device, flags, archive, pdf) self.convertAndSave(source, target, device, flags, archive, pdf)

View File

@ -20,16 +20,16 @@ from PIL import Image, ImageDraw, ImageStat, ImageChops
class ImageFlags: class ImageFlags:
Orient = 1 << 0 Orient = 1 << 0
Resize = 1 << 1 Resize = 1 << 1
Frame = 1 << 2 Frame = 1 << 2
Quantize = 1 << 3 Quantize = 1 << 3
Stretch = 1 << 4 Stretch = 1 << 4
Split = 1 << 5 # split right then left SplitRightLeft = 1 << 5 # split right then left
SplitRight = 1 << 6 # split only the right page SplitRight = 1 << 6 # split only the right page
SplitLeft = 1 << 7 # split only the left page SplitLeft = 1 << 7 # split only the left page
SplitInverse = 1 << 8 # split left then right page SplitLeftRight = 1 << 8 # split left then right page
AutoCrop = 1 << 9 # split left then right page AutoCrop = 1 << 9
class KindleData: class KindleData:
@ -78,16 +78,17 @@ class KindleData:
Profiles = { Profiles = {
'Kindle 1': ((600, 800), Palette4), 'Kindle 1': ((600, 800), Palette4),
'Kindle 2': ((600, 800), Palette15a), 'Kindle 2/3/Touch': ((600, 800), Palette15a),
'Kindle 3': ((600, 800), Palette15a), 'Kindle 4 & 5': ((600, 800), Palette15b),
'Kindle 4': ((600, 800), Palette15b), 'Kindle DX/DXG': ((824, 1200), Palette15a),
'Kindle 5': ((600, 800), Palette15b), 'Kindle Paperwhite 1 & 2': ((758, 1024), Palette15b),
'Kindle DX': ((824, 1200), Palette15a), 'Kindle Paperwhite 3/Voyage/Oasis': ((1072, 1448), Palette15b),
'Kindle DXG': ((824, 1200), Palette15a), 'Kobo Mini/Touch': ((600, 800), Palette15b),
'Kindle Touch': ((600, 800), Palette15a), 'Kobo Glo': ((768, 1024), Palette15b),
'Kindle Paperwhite': ((758, 1024), Palette15b), # resolution given in manual, see http://kindle.s3.amazonaws.com/Kindle_Paperwhite_Users_Guide.pdf 'Kobo Glo HD': ((1072, 1448), Palette15b),
'Kindle Paperwhite 3': ((1072, 1448), Palette15b), 'Kobo Aura': ((758, 1024), Palette15b),
'KoBo Aura H2o': ((1080, 1430), Palette15a), # resolution from http://www.fnac.com/Liseuse-Numerique-Kobo-by-Fnac-Kobo-Aura-H2O-Noir/a7745120/w-4 'Kobo Aura HD': ((1080, 1440), Palette15b),
'Kobo Aura H2O': ((1080, 1430), Palette15a),
} }
@ -102,12 +103,14 @@ def protect_bad_image(func):
return func(*args, **kwargs) return func(*args, **kwargs)
except IOError: # Exception from PIL about bad image except IOError: # Exception from PIL about bad image
return args[0] return args[0]
return func_wrapper return func_wrapper
@protect_bad_image @protect_bad_image
def splitLeft(image): def splitLeft(image):
widthImg, heightImg = image.size widthImg, heightImg = image.size
return image.crop((0, 0, widthImg / 2, heightImg)) return image.crop((0, 0, widthImg / 2, heightImg))
@ -188,6 +191,7 @@ def autoCropImage(image):
except TypeError: # bad image, specific to chops except TypeError: # bad image, specific to chops
return image return image
image = image.crop((x0, y0, xend, yend)) image = image.crop((x0, y0, xend, yend))
return image return image
@ -253,29 +257,22 @@ def convertImage(source, target, device, flags):
# Load image from source path # Load image from source path
image = loadImage(source) image = loadImage(source)
# Format according to palette # Format according to palette
image = formatImage(image) image = formatImage(image)
# Apply flag transforms
# Second pass of first split # Apply flag transforms
if flags & ImageFlags.SplitRight: if flags & ImageFlags.SplitRight:
image = splitRight(image) image = splitRight(image)
# First pass of first split option if flags & ImageFlags.SplitRightLeft:
if (flags & ImageFlags.Split):
image = splitLeft(image) image = splitLeft(image)
# First pass of second splitting option
if flags & ImageFlags.SplitLeft: if flags & ImageFlags.SplitLeft:
image = splitLeft(image) image = splitLeft(image)
# second pass of second splitting option if flags & ImageFlags.SplitLeftRight:
if (flags & ImageFlags.SplitInverse):
image = splitRight(image) image = splitRight(image)
# Auto crop the image, but before manage size and co, clean the source so # Auto crop the image, but before manage size and co, clean the source so
if flags & ImageFlags.AutoCrop: if flags & ImageFlags.AutoCrop:
image = autoCropImage(image) image = autoCropImage(image)
if flags & ImageFlags.Orient: if flags & ImageFlags.Orient:
image = orientImage(image, size) image = orientImage(image, size)
if flags & ImageFlags.Resize: if flags & ImageFlags.Resize:
@ -284,9 +281,6 @@ def convertImage(source, target, device, flags):
image = stretchImage(image, size) image = stretchImage(image, size)
if flags & ImageFlags.Frame: if flags & ImageFlags.Frame:
image = frameImage(image, tuple(palette[:3]), tuple(palette[-3:]), size) image = frameImage(image, tuple(palette[:3]), tuple(palette[-3:]), size)
if flags & ImageFlags.Quantize: if flags & ImageFlags.Quantize:
image = quantizeImage(image, palette) image = quantizeImage(image, palette)

View File

@ -69,9 +69,9 @@ class DialogOptions(QtGui.QDialog):
if self.checkboxFrame.isChecked(): if self.checkboxFrame.isChecked():
imageFlags |= ImageFlags.Frame imageFlags |= ImageFlags.Frame
if self.checkboxSplit.isChecked(): if self.checkboxSplit.isChecked():
imageFlags |= ImageFlags.Split imageFlags |= ImageFlags.SplitRightLeft
if self.checkboxSplitInverse.isChecked(): if self.checkboxSplitInverse.isChecked():
imageFlags |= ImageFlags.SplitInverse imageFlags |= ImageFlags.SplitLeftRight
if self.checkboxAutoCrop.isChecked(): if self.checkboxAutoCrop.isChecked():
imageFlags |= ImageFlags.AutoCrop imageFlags |= ImageFlags.AutoCrop

View File

@ -63,52 +63,57 @@
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Kindle 2</string> <string>Kindle 2/3/Touch</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Kindle 3</string> <string>Kindle 4 &amp; 5</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Kindle 4</string> <string>Kindle DX/DXG</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Kindle 5</string> <string>Kindle Paperwhite 1 &amp; 2</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Kindle DX</string> <string>Kindle Paperwhite 3/Voyage/Oasis</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Kindle DXG</string> <string>Kobo Mini/Touch</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Kindle Touch</string> <string>Kobo Glo</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Kindle Paperwhite</string> <string>Kobo Glo HD</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>Kindle Paperwhite 3</string> <string>Kobo Aura</string>
</property> </property>
</item> </item>
<item> <item>
<property name="text"> <property name="text">
<string>KoBo Aura H2o</string> <string>Kobo Aura HD</string>
</property>
</item>
<item>
<property name="text">
<string>Kobo Aura H2O</string>
</property> </property>
</item> </item>
</widget> </widget>