From 2e8b4ac77cf518b08a766e11203b1537932e61cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gab=C3=A8s=20Jean?= Date: Fri, 25 Sep 2015 11:12:18 -0600 Subject: [PATCH 1/2] Add: option to split from left then right pages, add Kobo Aura h2o ereader and fix sorting bug * Add: split option from left then right to manage some mangas * Add: the Kobo Aura H2o ereader (special resolution) * Fix: remove natsort dependency and use a custom function instead for natural sorting --- .gitignore | 1 + README.md | 1 - mangle/book.py | 17 +++++++++++++---- mangle/convert.py | 8 ++++++++ mangle/image.py | 22 ++++++++++++++++++---- mangle/options.py | 2 ++ mangle/ui/options.ui | 12 ++++++++++++ 7 files changed, 54 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index d10b6b6..ae3a8a2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ dist *.pyo *.mngl *.cbz +*.bat diff --git a/README.md b/README.md index 2d6959d..8f4dd33 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,6 @@ of your choice. First you should make sure that you have the required dependenci * [Python 2.7](http://www.python.org/download/releases/2.7/) * [Python Imaging Library (PIL)](http://www.pythonware.com/products/pil/) * [ReportLab](https://pypi.python.org/pypi/reportlab) -* [natsort](https://pypi.python.org/pypi/natsort/3.0.1) * [py2exe](http://www.py2exe.org/) (optional, for Windows distribution only) Now you can fetch the [latest version of the code](https://github.com/FooSoft/mangle/) and run the `mangle.pyw` script diff --git a/mangle/book.py b/mangle/book.py index 1bc8c28..2079f8a 100644 --- a/mangle/book.py +++ b/mangle/book.py @@ -13,14 +13,13 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . - +import re from os.path import basename import os.path import tempfile from zipfile import ZipFile from PyQt4 import QtGui, QtCore, QtXml, uic -from natsort import natsorted from about import DialogAbout from convert import DialogConvert @@ -29,6 +28,13 @@ from options import DialogOptions import util +# Sort function use to sort files in a natural order, by lowering +# characters, and manage multi levels of integers (tome 1/ page 1.jpg, etc etc) +def natural_key(string_): + """See http://www.codinghorror.com/blog/archives/001018.html""" + return [int(s) if s.isdigit() else s.lower() for s in re.split(r'(\d+)', string_)] + + class Book(object): DefaultDevice = 'Kindle Paperwhite' DefaultOutputFormat = 'CBZ only' @@ -367,14 +373,16 @@ class MainWindowBook(QtGui.QMainWindow): filenamesListed = [] for i in xrange(0, self.listWidgetFiles.count()): filenamesListed.append(self.listWidgetFiles.item(i).text()) - - for filename in natsorted(filenames): + + # Get files but in a natural sorted order + for filename in sorted(filenames, key=natural_key): if filename not in filenamesListed: filename = QtCore.QString(filename) self.listWidgetFiles.addItem(filename) self.book.images.append(filename) self.book.modified = True + def addImageDirs(self, directories): filenames = [] @@ -387,6 +395,7 @@ class MainWindowBook(QtGui.QMainWindow): self.addImageFiles(filenames) + def addCBZFiles(self, filenames): directories = [] tempDir = tempfile.gettempdir() diff --git a/mangle/convert.py b/mangle/convert.py index a9258fb..d9bdf8f 100644 --- a/mangle/convert.py +++ b/mangle/convert.py @@ -129,6 +129,14 @@ class DialogConvert(QtGui.QProgressDialog): # Change target once again for left page target = os.path.join(self.bookPath, '%05d.png' % (index * 2 + 1)) + # For right page (if requested), but in inverted mode + if(self.book.imageFlags & ImageFlags.SplitInverse): + # New path based on modified index + target = os.path.join(self.bookPath, '%05d.png' % (index * 2 + 0)) + self.convertAndSave(source, target, device, flags ^ ImageFlags.SplitInverse | ImageFlags.SplitLeft, archive, pdf) + # Change target once again for left page + target = os.path.join(self.bookPath, '%05d.png' % (index * 2 + 1)) + # Convert page self.convertAndSave(source, target, device, flags, archive, pdf) diff --git a/mangle/image.py b/mangle/image.py index edf2928..1830dac 100644 --- a/mangle/image.py +++ b/mangle/image.py @@ -19,14 +19,17 @@ import os from PIL import Image, ImageDraw + class ImageFlags: Orient = 1 << 0 Resize = 1 << 1 Frame = 1 << 2 Quantize = 1 << 3 Stretch = 1 << 4 - Split = 1 << 5 - SplitRight = 1 << 6 + Split = 1 << 5 # split right then left + SplitRight = 1 << 6 # split only the right page + SplitLeft = 1 << 7 # split only the left page + SplitInverse = 1 << 8 # split left then right page class KindleData: @@ -82,7 +85,8 @@ class KindleData: 'Kindle DX': ((824, 1200), Palette15a), 'Kindle DXG': ((824, 1200), Palette15a), 'Kindle Touch': ((600, 800), Palette15a), - 'Kindle Paperwhite': ((758, 1024), Palette15b) # resolution given in manual, see http://kindle.s3.amazonaws.com/Kindle_Paperwhite_Users_Guide.pdf + 'Kindle Paperwhite': ((758, 1024), Palette15b), # resolution given in manual, see http://kindle.s3.amazonaws.com/Kindle_Paperwhite_Users_Guide.pdf + 'KoBo Aura H2o': ((1080, 1430), Palette15a), # resolution from http://www.fnac.com/Liseuse-Numerique-Kobo-by-Fnac-Kobo-Aura-H2O-Noir/a7745120/w-4 } @@ -204,10 +208,20 @@ def convertImage(source, target, device, flags): # Format according to palette image = formatImage(image) # Apply flag transforms + + # Second pass of first split if flags & ImageFlags.SplitRight: image = splitRight(image) - if flags & ImageFlags.Split: + # First pass of first split option + if (flags & ImageFlags.Split): image = splitLeft(image) + # First pass of second splitting option + if flags & ImageFlags.SplitLeft: + image = splitLeft(image) + # second pass of second splitting option + if (flags & ImageFlags.SplitInverse): + image = splitRight(image) + if flags & ImageFlags.Orient: image = orientImage(image, size) if flags & ImageFlags.Resize: diff --git a/mangle/options.py b/mangle/options.py index eb79f7f..eedfe88 100644 --- a/mangle/options.py +++ b/mangle/options.py @@ -66,6 +66,8 @@ class DialogOptions(QtGui.QDialog): imageFlags |= ImageFlags.Frame if self.checkboxSplit.isChecked(): imageFlags |= ImageFlags.Split + if self.checkboxSplitInverse.isChecked(): + imageFlags |= ImageFlags.SplitInverse modified = ( self.book.title != title or diff --git a/mangle/ui/options.ui b/mangle/ui/options.ui index 1c903ae..e5af54a 100644 --- a/mangle/ui/options.ui +++ b/mangle/ui/options.ui @@ -101,6 +101,11 @@ Kindle Paperwhite + + + KoBo Aura H2o + + @@ -170,6 +175,13 @@ Split images into two pages (right, left) + + + + + Split images into two pages (left, right) + + From 0492be40a433da24ebb0db192fa64705f0d6ed65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gab=C3=A8s=20Jean?= Date: Fri, 25 Sep 2015 14:33:57 -0600 Subject: [PATCH 2/2] Add: change pictures for export, and add a new one for book option menu Icons are GPL from http://genericons.com/ --- mangle/img/book.png | Bin 0 -> 398 bytes mangle/img/export_book.png | Bin 827 -> 545 bytes mangle/ui/book.ui | 4 ++++ 3 files changed, 4 insertions(+) create mode 100644 mangle/img/book.png diff --git a/mangle/img/book.png b/mangle/img/book.png new file mode 100644 index 0000000000000000000000000000000000000000..aee4342a6f82ef0991deaa4a4ff45da7d4d5c525 GIT binary patch literal 398 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b z3=DjSL74G){)!Z!AbW|YuPgg~PDvqYg(mk$MGOp#(w;7kAr`0KPCl>gQYdoN{`=nd zv(NAt&SRa}s}tcV7PfiwrmYh^Zbq$)^vGAd7@<|)Fn4P!YqzBJ%oFQVJSA6q`bwo< zvAKR|#=R@t%}axq=iRM7zw+|l4}8I?$pwqH%I@?sG<{N(!@d2Pwv(Lx{+|zf(q72O zDwi&_Fte#We48PafqOxL$L+1nsh2Hu7%JC_*^B<*{m1&xVZpx|(dG+088D z00(qQO+^Ra2^kU?0}Bnn!vFvQu1Q2eR5;6xlRs!vQ5431=f0cw`bVo|X>kx2C&fQx z(5(@4>d>LY&1}Kh!Q!HbQ*f!PbP$T0wBXROR3}{u+Ob`lLVtx0{tZd`?tAwg2a~kg zK9dj5aJk&?eD{3c0kD8YHF$D|dNH682s?Qd8g?mO`M~4GCBRCT0A1$B#9Z_`wXt)a zh#YtoA6o6W>$NR?xL7g0i}p5Wo06rSQf=2O7xGG%wB~#`LKdH)((V2i(%7gHh#)5^ zXn$c8RD0*X0)Gn@VFDNz!LOGY3V#TmD$yg}k|mRDEZx)vZr^InKLgUC2;vc$!4&p; zla>eO<@o34a}=+=r}FA@d7y&-!CNy>L3E(2WXWWI(hJ%B*46oCzI~cz<=*DI0X-~W z<2tjL!ak+yM}YNmH(>u%tIiBk*rrrnQzhuzm_my33x8;JZ5#^6b6}%P1fTa{>>M39 zq(4S5y0LiP2|ECRK~PRPH3tD%0w7iK1>@RDo(qY`2{Z+oZfg3w^E$P1H+$i+9f775 zZ6D_F2*KDzew1B!2{RLP=Bz2nYy#2xN!=00Qz!L_t(Ijct=ZNF#Y1#ozpPCee%% zC#W+~Fs6`2SnyaZJR4J5TW@u{3s#oGu560HE*4^GVc4sJm1%8uAz+b9;VmXC9Lr+i zpM%6OhKMtn-+aHnnX6Wm^VQ$?iue6IEskS6rIVAB*UbD%DSrhbsuT)^&rjWH4+C1Q z*1S^cU!~L?Gq-1EW+vh|Mx)W_rcx<~nMa6ddTnj(pI;vFz+6^JeP`w$L}U|@l2SrS zi9{lyh{z7Z@JASi-z$|$`B6Z#+1xTs^Gz<76P9H;%>0v??H~v+7z_|akxfKDbGe*T zC=|r_`1qThoqwGz0MG#-3`5aww_^aBloGaWn?eW>5ddI*eqNJOno>%fpP%FS_&5%N zKs@T8Uax;lr_=9)Ab?T|{eB-87Z)%L1NnR&x~_wW;QKyWt=6Z_&CM+U&>D@#-^@J8 z%%wkHkS4<|8uq>;zxVZRx9LF$C6MwZ@tw%&2Ghge>{M+2zoN!$i z{eB;YVW89LKnPLX-roKS0OfKSolfVA<2Z0#7t71bmTlYC?(XiCAR(_Nz1a#g@pxcFc@HZdK#|lmiG7e zK|~;;Qhzp^MHq$4I!V; z!!V3@>+9 + + + ../img/book.png../img/book.png + &Options...