用 Python 將漫畫轉 PDF 給 Kindle DX 用

Posted by TJ Wei on 星期二, 10月 09, 2012 with No comments


Kindle DX 的 824x1200 解析度拿來看黑白漫畫還算合適。可以直接轉圖檔來看,但是 Kindle DX 的看圖軟體並不是很穩定。也可以用一些免費的 pdf 工具來把圖檔組合轉成 pdf 檔,但並不是很能隨心所欲的控制解析度。
所以這裡利用 python 的 reportlab 來做。
底下是先利用 PIL 先將圖檔切兩半,然後增加對比,壓縮成 JPEG,最後再利用reportlab 將圖檔放入 pdf 中即可。
from glob import iglob
from sys import argv
from io import BytesIO
from PIL import Image, ImageOps
from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
dxsize=(776,1150)
pathname=argv[1]
c = canvas.Canvas( pathname+".pdf",pagesize=dxsize)
for fn in sorted(iglob(pathname+"/*.jpg")):
    img=Image.open(fn).convert("L")    
    w,h=img.size    
    im_split = map(img.crop, [(w/2,20, w, h), (0,20, w/2, h)])    
    im = [img.crop((0,20,w,h))] if w < h else im_split    
    for imgx in im:
        imgx=imgx.resize(dxsize, Image.ANTIALIAS)
        imgx=ImageOps.autocontrast(imgx, cutoff=10)
        tmpio=BytesIO()
        imgx.save(tmpio, "JPEG", quality=70)
        tmpio.seek(0)        
        c.drawImage(ImageReader(tmpio), 0, 0)
        c.showPage()
c.save()

裡面的 dxsize 是根據 mobileread 的網友實驗出來,kindle dx 中 pdf 可用的最大圖檔解析度。雖然 pagesize 的單位是 point 而不是 pixel,但看起來似乎這樣是對的設定。
由於抓來的圖檔對比太弱,利用 autocontrast 來加強對比。
im_split 那行是將圖切回左右兩頁,上面的 20px 是去掉漫畫網站的 mark。
ImageReader 其實吃 PIL 的 Image,但為了能夠控制 JPEG 的壓縮率,所以利用 BytesIO 來當暫存檔。由於某些 PIL bug 的緣故,雖然理論上 Image.save 應該要能吃 BytesIO,但是上面的程式碼會出錯,因為 PIL 沒有處理某些 BytesIO 丟出的 exception,所以我手動修改 PIL 的程式碼讓,save 能吃 BytesIO,也許改成 StringIO 也可以避開這個問題。
原先還想說是否要 dithering,不過至少漫畫看起來還可以接受。

倒也不是非得一定要用 python 寫,我同時也有抓 pdf fill 這樣的現成工具。只是剛好網路有點慢,還沒有抓完 pdf fill,已經先裝好 PIL、 reportlab,然後寫出上面那個程式的雛型了(不過原來沒有用 BytesIO 而且是用 reportlab 比較高階的寫法)。

Categories: