Crafting an Image to PDF Converter App Using Python.
Tags: webdev, python, beginners, programming
Published: 2024-04-11 21:10:49

Have you ever found yourself in a situation where you needed to convert a bunch of images into a PDF file quickly and efficiently? Imagine the convenience of converting a series of images from your recent trip into a single PDF album with just a few clicks. In this article, we will cover the process of building an Image PDF Converter App using [Python](https://www.python.org/). With the help of libraries like [tkinter](https://docs.python.org/3/library/tkinter.html), [os](https://www.tutorialsteacher.com/python/os-module), and [Python Imaging Library](https://pypi.org/project/pillow/)  (PIL), we'll walk through the process of creating a powerful tool that can streamline this task for you.

Throughout this tutorial, we will explore the step-by-step process of developing a user-friendly application that not only converts images to PDF but also allows for customization and optimization. By the end of this article, you will have a solid understanding of how to leverage these Python libraries to create a practical solution to your image conversion needs.


## Setting Up The Project Environment

When working in [Visual Studio Code](https://code.visualstudio.com/) (VS Code), start by creating a new [Python](https://www.python.org/) file for our image-to-PDF project. It's helpful to have separate files for different parts of your project.


### Create a new Python application:

To do this, you can start by opening your [VS Code](https://code.visualstudio.com/) and creating a new folder:


####Step 1

Open [VS Code](https://code.visualstudio.com/) 



![vs code main page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ulspz3lg5qazjgbh1xoj.png)




####Step 2

Create new folder



![create new folder in VS code](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fmxj93j07litb2q4llf3.png)



####Step 3

Head over to the newly created folder and create a new file called app.py.


![New Python file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/m6tv3dr3r18g1zeb5a7u.png)




##Install libraries

To start we are going to install [Python](https://www.python.org/) libraries [Tkinter](https://docs.python.org/3/library/tkinter.html), [Python Imaging Library](https://pypi.org/project/pillow/) (PIL):


<prev>
```python
pip install tk pillow
```
</prev>


![Installing tk and pillow](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1fta9bo9k9af0u64v0t3.png)



Next, we import our libraries:

<prev>
```python
import tkinter as tk
from tkinter import filedialog
from reportlab.pdfgen import canvas
from PIL import image
import OS
```
</prev>

##Creating Class

A `class` contains the image loading and PDF conversion functionality, making it easier to manage the overall conversion process.

###Step 1

To get started first, we will create a `class` `ImagetoPDFConverter`:

<prev>
```python
class ImageToPDFConverter
```
</prev>

###Step 2

Next, we have to initialize our `self` and `root`:

<prev>
```python
   def__init__(self,root):
```
</prev>

To initialize, we will call `self `:

<prev>
```python
self.root=root
```
</prev>

After initializing our roots, we will create some important variables.

###Step 3

First, we create variables for our images:

<prev>
```python
self.image_paths = [ ]
```
</prev>

We are leaving `self.image_paths`  empty because we are going to convert multiple images to PDF files.

###Step 4

To convert our images to PDF, we have to create a variable for PDF:

<prev>
```python
self.output_pdf_name = tk.StrngVar( ) 
```
</prev>

###Step 5

When we select multiple images to convert to PDF, we need to create a variable to store the names of the images:

<prev>
```python
self.selected_images_listbox = tk.Listbox(root, selectmode=tk.MULTIPLE)
```
</prev>

###Step 6

Next, we initialize the UI, and to do this we have to create an instance name:

<prev>
```python
self.initialize_ui()
```
</prev>

###Step 7

We define our instance:

<prev>
```python
def initialize _ui(self):
```
</prev>

Now, we create variables and define our components like `title` `buttons`, our `listing space`, `input section` and our `convert button.` 

###Step 8

First, we are going to create a variable for our title `image to PDF converter`:

<prev>
```python
def initialize _ui(self):
   title_label = tk.Label(self.root, text ='image to pdf converter' , font =('Helvetica', 16, 'bold'))
   title_label.pack(pady=10)
```
</prev>

###Step 9

To check if the components we just created above are working, we have to define our `main`:

<prev>
```python
def main():
root = tk.Tk()
```
</prev>

###Step 10

Next, we create a title also for the window:

<prev>
```python
root.title("image to pdf")
Converter = ImageToPDFConverter(root)
```
</prev>

###Step 11

Finally, we initialize the size for our window:

<prev>
```python
root.geometry("400x600")
root.mainloop()
```
</prev>

<prev>
```python
if__name__ == "__main__":
main()
```
</prev>

###Step 12

Save and run our code


![Image of main window](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0w7gryo6xjzokb9s6w2x.png)





##Design GUI for Application

Designing a GUI for an application refers to creating the graphical user interface (GUI) that users will interact with when using the application. It involves designing the layout, appearance, and functionality of the user interface elements.

###Step 1

To get started, we create our `select image button`:

<prev>
```python
select_image_button= tk.Button(self.root, text ='select images', command = self.select_images)
select_image_button.pack(pady=(0,10))
```
</prev>

###Step 2

Next, we create our `list box.`
To do this we first initialize our `self` and create a variable:

<prev>
```python
self.selected_images_listbox.pck(pady=(0,10), fill=tk.BOTH, expand=True)
```
</prev>

###Step 3

Next, we will create a list label, to do this we have to create a variable `label.`:

<prev>
```python
label = tk.label(self.root,text="enter output pdf name")
label.pack()
```
</prev>

###Step 4

We need an input section so users can type a personalized name for the generated PDF file:

<prev>
```python
pdf_name_entry = tk.Entry(self.root,textvariable=self.output_pdf_name, width=40, justify =='center')
pdf_name_entry.pack()
```
</prev>

###Step 5

Next, we create our `convert to pdf button`:

<prev>
```python
convert_button= tk.Button(self.root, text ='convert to pdf ', command = self.convert_images_to_pdf)
convert_button.pack(pady=(20,40))
```
</prev>

##Implementing Button Functions

When we click on the select image button, our file explorer should open for us to select some images and also save the names in the list box.

###Step 1

To do this, first, we create a variable and call it `self`:

<prev>
```python
def select_images(self)
   self.image_paths = filedalog.askopenfilenames(title="select images", filetypes = [('images files', '*.png;*.jpg;*.jpeg)])
 self.update_selected_images_listbox()
```
</prev>

(* represents the file name and the file names that we select could be anything, so we use * )

###Step 2

After selecting our images we want to update our image on the `list box`:

<prev>
```python
def update_selected_images_listbox(self):
   self.selected_images_listbox.delete(0,tk.END)
```
</prev>

###Step 3

Next, let's find out if there are any names already on the list. If we come across any, we'll remove them and then split them up.

This is useful when you want to display only the file names in a user interface component like a list box, without showing the entire file path:

<prev>
```python
for image_path in self.image_paths:
      _, image_path = os.path.split(image_path)
self.selected_images_lisbox.insert(tk.End,image_path)
```
</prev>

##Convert Images into PDF Function

We need to prompt the user to input a personalized name to save the PDF file. If the user fails to provide a name, we can automatically generate one.

###Step 1

To do this we need to define `convert_images_to_pdf`:

<prev>
```python
def convert_images_to_pdf(self):
     if not self.image_paths:
       return
    output_pdf_path = self.output_pdf_name.get() + ".pdf" if self.output_pdf_name.get()
    else "output.pdf"
```
</prev>


##Inserting images into PDF pages

After deciding on the PDF name, we initialize a page size for the PDF.

The standard PDF page size is 612 by 792, 

###Step 1

To do this we create a variable `pdf`:

<prev>
```python
pdf = canvas.canvas(output_pdf_path, pagesize = (612,792))
```
</prev>

###Step 2

Continuing with the process, we will iterate through each image file path and open the corresponding image using the PIL library. This way, we can assign each opened image to the variable `img` one by one:

<prev>
```python
for image_path in self.image_paths:
    img = image.open(image_path)
```
</prev>

###Step 3

For placing all images in the center of our PDF page, we will create a variable 'scale_factor':

<prev>
```python
for image_path in self.image_paths:
    img = image.open(image_path)
    available_width =540
    available_height = 720
    scalefactor = min(available_width/ img.width, available_height/img.height)
    new_width = img.width * scale_factor
    new_height = img.height* scale_factor
```
</prev>

###Step 4
 
Next, we have to determine the `x and y` values:

<prev>
```python
x_centered =(612 - new_width)/2
y_centered =(792 - new_height)/2
```
</prev>

###Step 5

Next, we also want to add a white margin color:

<prev>
```python
pdf.setFilColorRGB(255,255,255)
pdf.rect(0,0,612,792,fill=True)
```
</prev>

###Step 6

Next, we want to add the image at the center of our white page:

<prev>
```python
pdfdrawInLineImage(img,x-centered, width=new_width, height=new_height)
pdf.showPage()
```
</prev>

###Step 7

Lastly, we save and run our code


![adding images in PDF page ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q0u562brxorltu3ji2uh.png)




###Step 8

Finally, after converting our images we save our newly created PDF file:
 
<prev>
```python
pdf.save()
```
</prev>

Wrapping it up together:

<Prev>
```python
import tkinter as tk
from tkinter import filedialog
from reportlab.pdfgen import canvas
from PIL import Image
import os

class ImageToPDFConverter:
    def __init__(self, root):
        self.root = root
        self.image_paths = []
        self.output_pdf_name = tk.StringVar()

        self.selected_images_listbox = tk.Listbox(root, selectmode=tk.MULTIPLE)
        self.selected_images_listbox.pack(pady=(0, 10), fill=tk.BOTH, expand=True)

        self.initialize_ui()

    def initialize_ui(self):
        title_label = tk.Label(self.root, text='Image to PDF Converter', font=('Helvetica', 16, 'bold'))
        title_label.pack(pady=10)

        select_image_button = tk.Button(self.root, text='Select Images', command=self.select_images)
        select_image_button.pack(pady=(0, 10))

        label = tk.Label(self.root, text="Enter output PDF name:")
        label.pack()

        pdf_name_entry = tk.Entry(self.root, textvariable=self.output_pdf_name, width=40)
        pdf_name_entry.pack()

        convert_button = tk.Button(self.root, text='Convert to PDF', command=self.convert_images_to_pdf)
        convert_button.pack(pady=(20, 40))

    def select_images(self):
        self.image_paths = filedialog.askopenfilenames(title="Select images", filetypes=[('Image files', '*.png;*.jpg;*.jpeg')])
        self.update_selected_images_listbox()

    def update_selected_images_listbox(self):
        self.selected_images_listbox.delete(0, tk.END)
        for image_path in self.image_paths:
            _, image_name = os.path.split(image_path)
            self.selected_images_listbox.insert(tk.END, image_name)

    def convert_images_to_pdf(self):
        if not self.image_paths:
            return

        output_pdf_path = self.output_pdf_name.get() + ".pdf" if self.output_pdf_name.get() else "output.pdf"

        pdf = canvas.Canvas(output_pdf_path, pagesize=(612, 792))

        for image_path in self.image_paths:
            img = Image.open(image_path)
            available_width = 540
            available_height = 720
            scale_factor = min(available_width / img.width, available_height / img.height)
            new_width = img.width * scale_factor
            new_height = img.height * scale_factor

            x_centered = (612 - new_width) / 2
            y_centered = (792 - new_height) / 2

            pdf.setFillColorRGB(255, 255, 255)
            pdf.rect(0, 0, 612, 792, fill=True)

            pdf.drawImage(img, x_centered, y_centered, width=new_width, height=new_height)
            pdf.showPage()

        pdf.save()

def main():
    root = tk.Tk()
    root.title("Image to PDF")
    converter = ImageToPDFConverter(root)
    root.geometry("400x600")
    root.mainloop()

if __name__ == "__main__":
    main()
```
</prev>


##Conclusion

The process of developing the image-to-PDF converter app has been an insightful journey from start to finish. We began by identifying the need for such a tool in the market and understanding the requirements of the users. Through careful planning and research, we designed the application's features and functionality to meet these needs effectively. Throughout the development phase, we encountered challenges that we overcame with creativity and problem-solving skills. We implemented key functionalities such as image recognition, file conversion, and user-friendly interface design to ensure a seamless user experience.

The learning outcomes from this project are vast. We gained valuable experience in app development, image processing, file handling, and user interface design. Additionally, we honed our project management and teamwork skills by collaborating effectively to deliver a high-quality product. The practical applications of this image to PDF converter app are significant. Users can now easily convert their images to PDF files with just a few clicks, saving time and effort. This app can be used in various industries such as education, business, and photography, providing a convenient solution for converting and sharing documents.

Overall, developing the image-to-PDF converter app has been a rewarding experience that has equipped us with new skills and knowledge. The app has the potential to make a positive impact on users' productivity and efficiency, demonstrating the power of technology to simplify everyday tasks.