Рубрики
Без рубрики

ReportLab: преобразование сотен изображений в PDFS

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Я недавно попросил преобразовать несколько сотен изображений на PDF-страницы. Мой друг привлекает комиксов, и мой брат хотел прочитать их на планшете. Увы, если у вас была куча файлов, названных что-то вроде этого:

‘Jia_01.jpg’, ‘jia_02.jpg’, ‘jia_09.jpg’, ‘jia_10.jpg’, ‘jia_11.jpg’, ‘jia_101.jpg’

Планшет Android будет извлекать бы их во что-то подобное:

‘Jia_01.jpg’, ‘jia_02.jpg’, ‘jia_09.jpg’, ‘jia_10.jpg’, ‘jia_101.jpg’, ‘jia_11.jpg’

И это было довольно запутанно, тем больше файлов, которые вы имели, вышли из строя. К сожалению, даже Python сортирует файлы таким образом. Я пытался использовать шаблон Модуль на непосредственно и затем сортировка результата и получила точную те же проблема. Итак, первое, что мне нужно было сделать, было находить какой-то алгоритм сортировки, который мог отсортировать их правильно. Следует отметить, что Windows 7 может правильно отсортировать файлы в своей файловой системе, хотя Python не может.

После небольшого поиска в Google я нашел следующий скрипт на Stackoverflow :

import re

#----------------------------------------------------------------------
def sorted_nicely( l ): 
    """     
    Sort the given iterable in the way that humans expect.
    """ 
    convert = lambda text: int(text) if text.isdigit() else text 
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(l, key = alphanum_key)

Это отлично работало! Теперь мне просто пришлось найти способ поставить каждую комикс на собственной странице PDF. К счастью, ReportLab Библиотека делает эту довольно легко для достижения. Вам просто нужно повторять изображения и вставить их по одному на страницу. Проще просто посмотреть на код, так что давайте сделаем это:

import glob
import os
import re

from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Image, PageBreak
from reportlab.lib.units import inch

#----------------------------------------------------------------------
def sorted_nicely( l ): 
    """ 
    # http://stackoverflow.com/questions/2669059/how-to-sort-alpha-numeric-set-in-python

    Sort the given iterable in the way that humans expect.
    """ 
    convert = lambda text: int(text) if text.isdigit() else text 
    alphanum_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ] 
    return sorted(l, key = alphanum_key)

#----------------------------------------------------------------------
def create_comic(fname, front_cover, back_cover, path):
    """"""
    filename = os.path.join(path, fname + ".pdf")
    doc = SimpleDocTemplate(filename,pagesize=letter,
                            rightMargin=72,leftMargin=72,
                            topMargin=72,bottomMargin=18)
    Story=[]
    width = 7.5*inch
    height = 9.5*inch    
    
    pictures = sorted_nicely(glob.glob(path + "\\%s*" % fname))
    
    Story.append(Image(front_cover, width, height))
    Story.append(PageBreak())
    
    x = 0
    page_nums = {100:'%s_101-200.pdf', 200:'%s_201-300.pdf',
                 300:'%s_301-400.pdf', 400:'%s_401-500.pdf',
                 500:'%s_end.pdf'}
    for pic in pictures:
        parts = pic.split("\\")
        p = parts[-1].split("%s" % fname)
        page_num = int(p[-1].split(".")[0])
        print "page_num => ", page_num
        
        im = Image(pic, width, height)
        Story.append(im)
        Story.append(PageBreak())
        
        if page_num in page_nums.keys():
            print "%s created" % filename 
            doc.build(Story)
            filename = os.path.join(path, page_nums[page_num] % fname)
            doc = SimpleDocTemplate(filename,
                                    pagesize=letter,
                                    rightMargin=72,leftMargin=72,
                                    topMargin=72,bottomMargin=18)
            Story=[]
        print pic
        x += 1
        
    Story.append(Image(back_cover, width, height))
    doc.build(Story)
    print "%s created" % filename
    
#----------------------------------------------------------------------
if __name__ == "__main__":
    path = r"C:\Users\Mike\Desktop\Sam's Comics"
    front_cover = os.path.join(path, "FrontCover.jpg")
    back_cover = os.path.join(path, "BackCover2.jpg")
    create_comic("Jia_", front_cover, back_cover, path) 

Давайте немного сломаемся. Как обычно, у вас есть необходимый импорт, необходимый для этого кода. Вы отметиете, что у нас также есть это Сортировать_Назовать Функция, о которой мы говорили о ранее в этом коде. Основная функция называется create_comic И принимает четыре аргумента: fname, front_cover, back_cover, путь. Если вы использовали инструментарий ReportLab ранее, вы узнаете SimpledoCteMplate и список историй, так как они прямыми из учебника ReportLab.

В любом случае, вы ведете по сортировке изображения и добавьте изображение в историю вместе с объектом Pagebreak. Причина, по которой в цикле условна, потому что я обнаружил, что если я попытался создать PDF со всеми 400+ изображениями, я бы столкнулся с ошибкой памяти. Поэтому я разбил его в серию PDF-документов, которые были 100 страницами или меньше. В конце документа вы должны позвонить в Док Объект построить Метод на самом деле создать документ PDF.

Теперь вы знаете, как я закончил писать целую степень изображений на несколько документов PDF. Теоретически, вы можете использовать PYPDF, чтобы связать все полученные PDF в один PDF, но я не пробовал его. Вы можете в конечном итоге с другой ошибкой памяти. Я оставлю это как упражнение для читателя.

Исходный код

  • comic_maker.zip
  • comic_maker.tar.tar.