Python - PDF to JPG & back Converter
Tags: tutorial, python, pdf2image, img2pdf
Published: 2021-09-02 20:49:23

#Motivation
Quite often, I have to submit the same documents in either `.pdf` or `.jpg/jpeg` format. I used online conversion sites to convert between the two formats. Recently a concern had been lingering in my mind that why am I uploading my personal documents on clouds and shouldn't I just create a converter so that the process stays local on my device. Hence, I decided to make a program to do the conversions.
#Steps I Took
####- Step 1: Decide framework/language for development
I'd like to include this as a documented step :) The reason is short: I do web development in my day-to-day life, so I decided that coding this small program in Python will be refreshing.
####- Step 2: Search for packages
You can either implement conversions on your own or you can look for packages that are well-maintained and have a good download count. I chose following packages for conversions:
- [pdf2image](https://pypistats.org/packages/pdf2image) for PDF to JPG conversion.
- [img2pdf](https://pypi.org/project/img2pdf/) for JPG/JPEG to PDF conversion.

####- Step 3: Make GUI
I used [PAGE](http://page.sourceforge.net/) to build static GUI. It is a very simple and easy-to-use drag-and-drop GUI generator. I made two GUIs, one for the converter and the other for showing success message. You can also handle all in one.

| ![JPG to PDF](https://user-images.githubusercontent.com/35191030/130137429-60b1ef67-239d-484d-88f4-a8c0d66d638b.png) | ![Successful conversion](https://user-images.githubusercontent.com/35191030/130138374-64e84b9c-c69b-465a-b70c-2290bc2b4ad3.png) |
|:--:|:--:|

<small>*Note: tkinter applications look different on different OS. I use Windows. If you want to make application same across all platforms, you can add conditional layouts.*</small>

After generating scripts from PAGE, I made the GUI dynamic on the basis of `conversion_mode`:
- If the `conversion_mode == 'jpg'`, then set text accordingly and show entry field for inputting name of output PDF file.
- Similarly, if the `conversion_mode == 'pdf'`, then make relevant textual changes. No need to add entry field as the output JPGs will have the PDF's name followed by index.

####- Step 4: Upload Files
I used tkinter's [filedialog](https://docs.python.org/3/library/dialog.html#module-tkinter.filedialog) module to upload files. I set `initialdir` to the directory where script is placed. `curr_dir = os.getcwd()`
- <u>Upload PDF</u>: Since single PDF file will be uploaded, hence `filedialog.askopenfilename` is used.
```
filedialog.askopenfilename(initialdir=curr_dir, title="Select PDF",
                                   filetypes=[("PDF File", "*.pdf")])
```
- <u>Upload JPGs</u>: Multiple JPG files can be uploaded to create a PDF file, hence `filedialog.askopenfilenames` is used.
```
filedialog.askopenfilenames(initialdir=curr_dir, title="Select JPG(s)",
            filetypes=[("JPG File", "*.jpeg *.jpg")
```
####- Step 5: Convert JPG to PDF:
To convert JPG/JPEG files to a single PDF, simply provide `file_paths`, which is a list of image file paths, to img2pdf's `convert` function.
```
import img2pdf

with open(name+".pdf", "wb+") as file:
        file.write(img2pdf.convert(*file_paths))
```
`name` is the output PDF name provided by the user.

####- Step 6: Convert PDF to JPG:
To use `pdf2image`, firstly download `poppler` on your system. ([Instructions](https://github.com/Belval/pdf2image#windows)). Since I'm a Windows user, I downloaded poppler and placed the `bin/` folder in the same directory as the script.
`poppler_path=r"./bin" if (sys.platform == "win32" or sys.platform == "cygwin") else None`
Image files created are stored in `output_folder`. To avoid out-of-memory error, I set `paths_only=True` so that `convert_from_path(...)` doesn't need to return PIL Image objects.
```
from pdf2image import convert_from_path
from pdf2image.exceptions import (
    PDFInfoNotInstalledError,
    PDFPageCountError,
    PDFSyntaxError
)

convert_from_path(
        file_path,
        output_folder=output_folder_path,
        output_file=output_folder_name,
        fmt="jpg",
        paths_only=True,
        poppler_path=r"./bin" if (sys.platform == "win32" or sys.platform == "cygwin") else None
)
```
You can run the function in chunks ([see](https://stackoverflow.com/a/56483540/10097213)) if the PDF file has hundreds of pages or you want to work on Image object and are concerned about running into OOM error.

After conversion, I shift the user to different interface where success message is displayed.

**Get the full implementation from my [GitHub](https://github.com/sanamumtaz/PDF-JPG-Converter).**

So this is how I made a PDF ⇌ JPG converter that fulfills my requirements and now I don't have to worry about security/privacy.

<small>*Share your thoughts. Feedback's always welcome :)*</small>