{"id":2695,"date":"2024-10-01T19:44:09","date_gmt":"2024-10-01T10:44:09","guid":{"rendered":"https:\/\/secondlife.lol\/?p=2695"},"modified":"2024-10-02T21:17:12","modified_gmt":"2024-10-02T12:17:12","slug":"python-pdf-image-processing-pillow-reportlab","status":"publish","type":"post","link":"https:\/\/secondlife.lol\/en\/python-pdf-image-processing-pillow-reportlab\/","title":{"rendered":"Python PDF Generation: Image Processing with Pillow and ReportLab"},"content":{"rendered":"<p class=\"wp-block-paragraph\"><a href=\"https:\/\/secondlife.lol\/en\/python-directory-exploration-os-module\/\">Previous Post<\/a>to see how to navigate a directory structure with Python. Well, let's take it a step further: with Python, it's very easy to automate the task of converting multiple image files into a single PDF. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this post, we'll learn how to create a Python PDF, and to do so, we'll use the <strong><a href=\"https:\/\/python-pillow.org\/\" target=\"_blank\" rel=\"noopener\">Pillow<\/a>and <a href=\"https:\/\/docs.reportlab.com\/\" data-type=\"link\" data-id=\"https:\/\/docs.reportlab.com\/\" target=\"_blank\" rel=\"noopener\">ReportLab<\/a> How to use libraries to process and convert images to PDFs<\/strong>which can be useful for creating reports or portfolios. This post will give you the skills you need to create a Python PDF.<\/p>\n\n\n<style>.kb-image2695_e21422-5a .kb-image-has-overlay:after{opacity:0.3;}.kb-image2695_e21422-5a img.kb-img, .kb-image2695_e21422-5a .kb-img img{box-shadow:0px 0px 14px 0px rgba(0, 0, 0, 0.2);}<\/style>\n<div class=\"wp-block-kadence-image kb-image2695_e21422-5a\"><figure class=\"aligncenter size-large\"><img decoding=\"async\" width=\"600\" height=\"258\" src=\"https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-6-2-600x258.jpg\" alt=\"Python PDF \uc0dd\uc131\" class=\"kb-img wp-image-2696\" srcset=\"https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-6-2-600x258.jpg 600w, https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-6-2-300x129.jpg 300w, https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-6-2-768x330.jpg 768w, https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-6-2.jpg 1200w\" sizes=\"(max-width: 600px) 100vw, 600px\" \/><\/figure><\/div>\n\n\n<style>.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-content-wrap{padding-top:var(--global-kb-spacing-sm, 1.5rem);padding-right:var(--global-kb-spacing-sm, 1.5rem);padding-bottom:var(--global-kb-spacing-sm, 1.5rem);padding-left:var(--global-kb-spacing-sm, 1.5rem);border-top:3px solid var(--global-palette2, #2B6CB0);border-right:3px solid var(--global-palette2, #2B6CB0);border-bottom:3px solid var(--global-palette2, #2B6CB0);border-left:3px solid var(--global-palette2, #2B6CB0);border-top-left-radius:5px;border-top-right-radius:5px;border-bottom-right-radius:5px;border-bottom-left-radius:5px;box-shadow:0px 0px 14px 0px rgba(0, 0, 0, 0.2);}.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-contents-title-wrap{padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;}.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-contents-title-wrap{color:var(--global-palette2, #2B6CB0);}.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-contents-title{color:var(--global-palette2, #2B6CB0);font-size:28px;font-weight:regular;font-style:normal;}.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-content-wrap .kb-table-of-content-list{color:var(--global-palette1, #3182CE);line-height:2em;font-weight:regular;font-style:normal;margin-top:var(--global-kb-spacing-sm, 1.5rem);margin-right:0px;margin-bottom:0px;margin-left:0px;}.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-content-wrap .kb-table-of-content-list .kb-table-of-contents__entry:hover{color:var(--global-palette6, #718096);}@media all and (max-width: 1024px){.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-content-wrap{border-top:3px solid var(--global-palette2, #2B6CB0);border-right:3px solid var(--global-palette2, #2B6CB0);border-bottom:3px solid var(--global-palette2, #2B6CB0);border-left:3px solid var(--global-palette2, #2B6CB0);}}@media all and (max-width: 1024px){.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-contents-title{font-size:28px;}}@media all and (max-width: 767px){.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-content-wrap{border-top:3px solid var(--global-palette2, #2B6CB0);border-right:3px solid var(--global-palette2, #2B6CB0);border-bottom:3px solid var(--global-palette2, #2B6CB0);border-left:3px solid var(--global-palette2, #2B6CB0);}.kb-table-of-content-nav.kb-table-of-content-id83_5f28a6-34 .kb-table-of-contents-title{font-size:28px;}}<\/style>\n\n\n<h2 class=\"wp-block-heading\">Pillow Libraries: The Basics of Image Processing<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Pillow<\/strong>is one of the most popular libraries for handling image files in Python. It makes it easy to open images, resize them, save them in different formats, and more. In the PDF creation task, it is used to determine the size and resolution of an image and convert it to a PDF as is.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Installing and basic usage of Pillow<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Pillow is easy to install using pip. If you're using VS code, you can run it in a Terminal window. I already have the package installed on my machine, so it says that the installation requirements are already met.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install Pillow<\/code><\/pre>\n\n\n<style>.kb-image2695_85f2a0-60 .kb-image-has-overlay:after{opacity:0.3;}.kb-image2695_85f2a0-60 img.kb-img, .kb-image2695_85f2a0-60 .kb-img img{box-shadow:0px 0px 14px 0px rgba(0, 0, 0, 0.2);}<\/style>\n<div class=\"wp-block-kadence-image kb-image2695_85f2a0-60\"><figure class=\"aligncenter size-full\"><img decoding=\"async\" width=\"730\" height=\"108\" src=\"https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-7-5.jpg\" alt=\"Python PDF \uc0dd\uc131 \ud3ec\uc2a4\ud2b8 \ud130\ubbf8\ub110 \ucea1\uccd0 \uadf8\ub9bc\" class=\"kb-img wp-image-2708\" srcset=\"https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-7-5.jpg 730w, https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-7-5-300x44.jpg 300w, https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-7-5-600x89.jpg 600w\" sizes=\"(max-width: 730px) 100vw, 730px\" \/><\/figure><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Let's look at a simple example of opening and verifying an image after installation.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from PIL import Image\n\nimg_path = \"C:\/Users\/user\/Documents\/lease_renewal_process.png\"\nimg = Image.open(img_path)\nprint(img.size) print # image size<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This code performs the basic task of using Pillow to open an image and output the size of that image. This information will be important later when generating a PDF.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">ReportLab: The Basics of PDF Creation<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>ReportLab<\/strong>is a very useful library for generating PDFs in Python. You can freely add text, images, shapes, and more, and you can even set custom page sizes. When converting an image to a PDF, the process works by setting up a page that fits the size of the image and inserting the image on top of it.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Installing and Basic Usage of ReportLab<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">ReportLab can also be installed using the pip command.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>pip install reportlab<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Let's look at an example of creating a simple PDF file after installation.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>from reportlab.pdfgen import canvas\n\npdf_path = \"C:\/Users\/user\/Documents\/output.pdf\"\nc = canvas.Canvas(pdf_path)\nc.drawString(100, 750, \"Hello, this is a PDF!\")\nc.save()<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This code creates a PDF file that includes the text \"Hello, this is a PDF!\". You can add images as well as text to a PDF page, and you can take advantage of this feature by using the <strong>Python PDF<\/strong>automatically, you can perform a variety of tasks.<\/p>\n\n\n<style>.kb-image2695_a17c7f-3f .kb-image-has-overlay:after{opacity:0.3;}.kb-image2695_a17c7f-3f img.kb-img, .kb-image2695_a17c7f-3f .kb-img img{box-shadow:0px 0px 14px 0px rgba(0, 0, 0, 0.2);}<\/style>\n<div class=\"wp-block-kadence-image kb-image2695_a17c7f-3f\"><figure class=\"aligncenter size-medium_large\"><img decoding=\"async\" width=\"768\" height=\"427\" src=\"https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-7-6-768x427.jpg\" alt=\"Python PDF \uc0dd\uc131 \ud3ec\uc2a4\ud2b8 pdf \uc0dd\uc131\uacb0\uacfc \ucea1\uccd0 \uadf8\ub9bc\" class=\"kb-img wp-image-2709\" srcset=\"https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-7-6-768x427.jpg 768w, https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-7-6-300x167.jpg 300w, https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-7-6-600x333.jpg 600w, https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/09\/image-7-6.jpg 869w\" sizes=\"(max-width: 768px) 100vw, 768px\" \/><\/figure><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Convert from image to PDF<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now let's take a look at an example of combining Pillow and ReportLab to convert multiple image files into a single PDF, which involves importing multiple image files, creating a page for each size, and inserting the image files onto the page.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Full code example<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>import os\nfrom PIL import Image\nfrom reportlab.pdfgen import canvas\n\ndef process_images(c, dir_path):\n    img_list = sorted([img_name for img_name in os.listdir(dir_path) if img_name.endswith(\".png\")])\n    for img_name in img_list:\n        img_path = os.path.join(dir_path, img_name)\n        img = Image.open(img_path)\n        img_width, img_height = img.size\n        c.setPageSize((img_width, img_height)) set page size to fit # image size\n        c.drawInlineImage(img_path, 0, 0, width=img_width, height=img_height) # Insert image\n        c.showPage()\n\ndef create_pdf_from_images(main_dir, output_pdf):\n    c = canvas.Canvas(output_pdf)\n    process_images(c, main_dir)\n    c.save()\n    print(f\"A PDF file has been created: {output_pdf}\")\n\nmain_dir = \"C:\/Users\/user\/Documents\/images\" # Folder where images are stored (adjust to suit your environment)\noutput_pdf = \"C:\/Users\/user\/Documents\/output.pdf\" # Path to the PDF to output (adjust to your environment)\ncreate_pdf_from_images(main_dir, output_pdf)<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Code description<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>process_images Function<\/strong>: This function imports PNG files from the specified directory, processes the images, and adds pages to the PDF for each image size.<\/li>\n\n\n\n<li><strong>create_pdf_from_images Function<\/strong>: This function creates a Canvas object, processes the image file, and saves it as a PDF.<\/li>\n\n\n\n<li><strong>Image processing with Pillow<\/strong>The key is to check the size of each image to ensure that the PDF page is sized to fit the image.<\/li>\n\n\n\n<li><strong>Generate PDFs with ReportLab<\/strong>Convert each image file to PDF one page at a time through a Canvas object, and finally save it as a PDF file.<\/li>\n<\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">Cautions when converting from image to PDF<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">There are a few caveats to generating PDFs with Python. First, you should check the resolution and size of your images beforehand; if you set the page size too small, the images may not output properly. Also, be sure to specify the image file format you want to convert, as different extensions of images may require different processing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Conclusion: The usefulness of Python PDF generation<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">In this post, we'll use the <strong>Python PDF<\/strong> Learn about creating, <strong>Pillow<\/strong>and <strong>ReportLab<\/strong>You've learned how to convert images to PDFs with the help of this technique, which allows you to document multiple image files in a single PDF, which is very useful for creating reports or portfolios. <strong>Python PDF<\/strong>if you want to automate the task of generating them, follow the steps in this post!<\/p>","protected":false},"excerpt":{"rendered":"<p>\uc774\uc804 \ud3ec\uc2a4\ud2b8\ub97c \ud1b5\ud574\uc11c Python\uc73c\ub85c \ub514\ub809\ud1a0\ub9ac \uad6c\uc870\ub97c \ud0d0\uc0c9\ud558\ub294 \ubc29\ubc95\uc744 \uc798 \uc0b4\ud3b4&#8230;<\/p>","protected":false},"author":3,"featured_media":2804,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_kad_blocks_custom_css":"","_kad_blocks_head_custom_js":"","_kad_blocks_body_custom_js":"","_kad_blocks_footer_custom_js":"","_kad_post_transparent":"","_kad_post_title":"","_kad_post_layout":"","_kad_post_sidebar_id":"","_kad_post_content_style":"","_kad_post_vertical_padding":"","_kad_post_feature":"","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"categories":[3],"tags":[294,292,291,296,290,293,295,215],"class_list":["post-2695","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-python-coding","tag-pdf-","tag-pillow","tag-python-pdf","tag-python-pdf-","tag-reportlab","tag--pdf-","tag-295","tag-215"],"taxonomy_info":{"category":[{"value":3,"label":"\ud30c\uc774\uc36c(Python)"}],"post_tag":[{"value":294,"label":"PDF \uc0dd\uc131"},{"value":292,"label":"Pillow"},{"value":291,"label":"Python PDF"},{"value":296,"label":"Python PDF \uc791\uc131"},{"value":290,"label":"ReportLab"},{"value":293,"label":"\uc774\ubbf8\uc9c0 PDF \ubcc0\ud658"},{"value":295,"label":"\uc774\ubbf8\uc9c0 \ucc98\ub9ac"},{"value":215,"label":"\ud30c\uc774\uc36c \ucd08\ubcf4\uc790"}]},"featured_image_src_large":["https:\/\/secondlife.lol\/wp-content\/uploads\/2024\/10\/Python-PDF-\uc0dd\uc131-\ud3ec\uc2a4\ud2b8-\uc378\ub124\uc77c-600x600.jpg",600,600,true],"author_info":{"display_name":"TERE","author_link":"https:\/\/secondlife.lol\/en\/author\/tere\/"},"comment_info":0,"category_info":[{"term_id":3,"name":"\ud30c\uc774\uc36c(Python)","slug":"python-coding","term_group":0,"term_taxonomy_id":3,"taxonomy":"category","description":"","parent":20,"count":118,"filter":"raw","cat_ID":3,"category_count":118,"category_description":"","cat_name":"\ud30c\uc774\uc36c(Python)","category_nicename":"python-coding","category_parent":20}],"tag_info":[{"term_id":294,"name":"PDF \uc0dd\uc131","slug":"pdf-%ec%83%9d%ec%84%b1","term_group":0,"term_taxonomy_id":294,"taxonomy":"post_tag","description":"","parent":0,"count":2,"filter":"raw"},{"term_id":292,"name":"Pillow","slug":"pillow","term_group":0,"term_taxonomy_id":292,"taxonomy":"post_tag","description":"","parent":0,"count":1,"filter":"raw"},{"term_id":291,"name":"Python PDF","slug":"python-pdf","term_group":0,"term_taxonomy_id":290,"taxonomy":"post_tag","description":"","parent":0,"count":2,"filter":"raw"},{"term_id":296,"name":"Python PDF \uc791\uc131","slug":"python-pdf-%ec%9e%91%ec%84%b1","term_group":0,"term_taxonomy_id":296,"taxonomy":"post_tag","description":"","parent":0,"count":1,"filter":"raw"},{"term_id":290,"name":"ReportLab","slug":"reportlab","term_group":0,"term_taxonomy_id":291,"taxonomy":"post_tag","description":"","parent":0,"count":1,"filter":"raw"},{"term_id":293,"name":"\uc774\ubbf8\uc9c0 PDF \ubcc0\ud658","slug":"%ec%9d%b4%eb%af%b8%ec%a7%80-pdf-%eb%b3%80%ed%99%98","term_group":0,"term_taxonomy_id":293,"taxonomy":"post_tag","description":"","parent":0,"count":2,"filter":"raw"},{"term_id":295,"name":"\uc774\ubbf8\uc9c0 \ucc98\ub9ac","slug":"%ec%9d%b4%eb%af%b8%ec%a7%80-%ec%b2%98%eb%a6%ac","term_group":0,"term_taxonomy_id":295,"taxonomy":"post_tag","description":"","parent":0,"count":2,"filter":"raw"},{"term_id":215,"name":"\ud30c\uc774\uc36c \ucd08\ubcf4\uc790","slug":"%ed%8c%8c%ec%9d%b4%ec%8d%ac-%ec%b4%88%eb%b3%b4%ec%9e%90","term_group":0,"term_taxonomy_id":215,"taxonomy":"post_tag","description":"","parent":0,"count":2,"filter":"raw"}],"_links":{"self":[{"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/posts\/2695","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/comments?post=2695"}],"version-history":[{"count":3,"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/posts\/2695\/revisions"}],"predecessor-version":[{"id":2712,"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/posts\/2695\/revisions\/2712"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/media\/2804"}],"wp:attachment":[{"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/media?parent=2695"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/categories?post=2695"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/secondlife.lol\/en\/wp-json\/wp\/v2\/tags?post=2695"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}