python3 将图片转换至PDF,批量转换漫画文档等

  • A+
所属分类:python基础入门

将图片转PDF,适用于图片批量转换。如漫画。图片文档等。

自动对图片大小进行处理,适用与kindle、iphone、ipad等终端。

支持多重文件路径检索进行转换。

支持jpg、png、bmp

转载源码:

  1. # -*- coding: utf-8 -*-
  2. # -------------------------------------------------------------------------------
  3. # @File     : Convert2PDF.py
  4. # @Created  : 2017/12/25 下午3:03
  5. # @Software : PyCharm
  6. # @Author   : Liu.Qi
  7. # @Contact  : liuqi_0725#aliyun.com
  8. # -------------------------------------------------------------------------------
  9. import os
  10. from reportlab.platypus import SimpleDocTemplate,Image, PageBreak
  11. from reportlab.lib.pagesizes import A4, landscape
  12. import time
  13. from PIL import Image as pilImage
  14. # 支持的图片类型
  15. __allow_type = [".jpg", ".jpeg", ".bmp", ".png"]
  16. __rootDir = ""
  17. def convert_images2PDF_one_dir(file_dir,save_name=None ,filename_sort_fn=None):
  18.     '''
  19.     转换一个目录文件夹下的图片至 PDF
  20.     :param file_dir:
  21.     :param file_name: 如果为空,则以当前文件夹的名称命名, 必须是.pdf结尾
  22.     :param filename_sort_fn:
  23.     文件名排序的回调函数,当此回调函数有值时,在文件名排序时,会回调,并将 file 的完整路径返回。
  24.     回调函数需要返回一个可转换整形的内容,函数根据此回调函数的返回值,对文件名排序
  25.     比如:
  26.         现实中,文件名会是
  27.         test_01_doc_0.png、
  28.         test_01_doc_1.png、
  29.         test_01_doc_2.png、
  30.         test_01_doc_3.png、
  31.         test_01_doc_11.png、
  32.         test_01_doc_21.png
  33.         等等,我们也希望读取出来的顺序如此,但是 mac、win 下,包括sort 排序出来的结果都不理想。
  34.         结果为
  35.         test_01_doc_0.png、
  36.         test_01_doc_1.png、
  37.         test_01_doc_11.png、
  38.         test_01_doc_2.png、
  39.         test_01_doc_21.png、
  40.         test_01_doc_3.png
  41.         不是我们想要得到的。
  42.         通过 filename_sort_fn(filename) 返回的整形数字,对齐正确的排序
  43.     '''
  44.     book_pages = []
  45.     for parent, dirnames ,filenames in os.walk(file_dir):
  46.         # 只遍历最顶层
  47.         if parent != file_dir :
  48.             continue
  49.         # 过滤文件中所有的图片
  50.         for file_name in filenames:
  51.             file_path = os.path.join(parent, file_name)
  52.             # 是否图片
  53.             if __isAllow_file(file_path) :
  54.                 book_pages.append(file_path)
  55.         # 取当前目录的文件名为书名
  56.         if save_name == None :
  57.             save_name = os.path.join(file_dir,(os.path.basename(file_dir) + ".pdf"))
  58.         else :
  59.             save_name = os.path.join(file_dir,save_name)
  60.         if len(book_pages) > 0 :
  61.             # 开始转换
  62.             print("[*][转换PDF] : 开始. [保存路径] > [%s]" % (save_name))
  63.             beginTime = time.clock()
  64.             __converted(save_name , book_pages ,filename_sort_fn)
  65.             endTime = time.clock()
  66.             print("[*][转换PDF] : 结束. [保存路径] > [%s] , 耗时 %f s " % (save_name, (endTime - beginTime)))
  67.         else :
  68.             print("该目录下没有找到任何图片文件.如果是多重目录,尝试使用 convert_images2PDF_more_dirs 函数")
  69. def convert_images2PDF_more_dirs(dirPath):
  70.     """
  71.     转换一个目录文件夹下的图片至 PDF
  72.     :param file_dir:
  73.     :param filename_sort_fn:
  74.     """
  75.     # 已经找到目录
  76.     __dirs = {}
  77.     for parent, dirnames, filenames in os.walk(dirPath):
  78.         for dirname in dirnames:
  79.             # 假设每个文件夹下都有图片,都是一本书
  80.             dirData = {"name": "", "pages": [], "isBook": False}
  81.             dirName = dirname.split('/')[0]
  82.             dirData['name'] = dirName
  83.             __dirs[dirName] = dirData
  84.         # 查找有无图片
  85.         for filename in filenames:
  86.             real_filename = os.path.join(parent, filename)
  87.             # 取父文件夹名称为书名
  88.             parentDirName = real_filename.split('/')[-2]
  89.             if parentDirName in __dirs.keys():
  90.                 dirJsonData = __dirs[parentDirName]
  91.             else:
  92.                 continue
  93.             # 检查是否图片
  94.             if __isAllow_file(real_filename) :
  95.                 # 将图片添加至书本
  96.                 dirJsonData['pages'].append(real_filename)
  97.                 # 如果该书的isbook 是false 改为true
  98.                 if not dirJsonData['isBook']:
  99.                     dirJsonData['isBook'] = True
  100.     index = 1
  101.     for dirName in __dirs.keys():
  102.         dirData = __dirs[dirName]
  103.         if dirData['isBook']:
  104.             print("[*][转换PDF] : 开始. [名称] > [%s]" % (dirName))
  105.             beginTime = time.clock()
  106.             __converted(os.path.join(dirPath,(dirData['name'] + ".pdf")) , dirData['pages'])
  107.             endTime = time.clock()
  108.             print("[*][转换PDF] : 结束. [名称] > [%s] , 耗时 %f s " % (dirName, (endTime - beginTime)))
  109.             index += 1
  110.     print("[*][所有转换完成] : 本次转换检索目录数 %d 个,共转换的PDF %d 本 " % (len(__dirs), index - 1))
  111. def __isAllow_file(filepath):
  112.     """
  113.     是否允许的文件
  114.     :param file:
  115.     :return:
  116.     """
  117.     if filepath and (os.path.splitext(filepath)[1] in __allow_type):
  118.         return True
  119.     return False
  120. def __converted(save_book_name,book_pages=[],filename_sort_fn=None):
  121.     """
  122.     开始转换
  123.     :param book_name: 保存的文件名(包含路径)
  124.     :param book_pages: 图片数组
  125.     :param filename_sort_fn: 文件名排序规则
  126.     :return:
  127.     """
  128.     # A4 纸的宽高
  129.     __a4_w, __a4_h = landscape(A4)
  130.     # 对数据进行排序
  131.     if (filename_sort_fn == None):
  132.         # 将按图片按名称的ASCII排序以避免错乱问题
  133.         book_pages.sort()
  134.     else:
  135.         # lambda 匿名函数, 第一个参数定义函数入参,第二个为参数的处理表达式
  136.         # 这样理解
  137.         # def getName(name):
  138.         #   return name.split("-")[1]
  139.         #
  140.         # 用匿名函数就这么表示
  141.         # name = lambda name:name.split("-")[1]
  142.         # xname = name("haha-dd-23")
  143.         #
  144.         # 支持多个参数
  145.         #
  146.         book_pages = sorted(book_pages, key=lambda name: int(filename_sort_fn(name)))
  147.     bookPagesData = []
  148.     bookDoc = SimpleDocTemplate(save_book_name, pagesize=A4, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=18)
  149.     for page in book_pages:
  150.         img_w, img_h = ImageTools().getImageSize(page)
  151.         # img_w = img.imageWidth
  152.         # img_h = img.imageHeight
  153.         if __a4_w / img_w < __a4_h / img_h:
  154.             ratio = __a4_w / img_w
  155.         else:
  156.             ratio = __a4_h / img_h
  157.         data = Image(page, img_w * ratio, img_h * ratio)
  158.         bookPagesData.append(data)
  159.         bookPagesData.append(PageBreak())
  160.     try:
  161.         bookDoc.build(bookPagesData)
  162.         # print("已转换 >>>> " + bookName)
  163.     except Exception as err:
  164.         print("[*][转换PDF] : 错误. [名称] > [%s]" % (save_book_name))
  165.         print("[*] Exception >>>> ", err)
  166. class ImageTools:
  167.     def getImageSize(self, imagePath):
  168.         img = pilImage.open(imagePath)
  169.         return img.size
weinxin
我的微信公众号
爱真理,得永生!          爱在灵灵久博客,网罗天下,福利大家!

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: