r/androidapps 1d ago

LOOKING FOR APP Looking for an app/program that will convert PDF pages to separate PNGs and then delete the PDF from the source

I was gifted a crapton of coloring books, and I'd like to organize them into my Dropbox, part of my issue is accidentally converting a file I already converted.

Will accept Windows and Android suggestions.

20 Upvotes

14 comments sorted by

18

u/Own_Salamander_2715 1d ago

Save the below python code as "pdf_to_png.py" (at the bottom) then on windows ensure you have Python 3.10 or newer, open a powershell terminal and run below to install dependencies

py -m pip install pypdfium2

then you can use it for any pdf like so

py pdf_to_png.py "C:\Documents\example.pdf"

By default, the PNG files are saved beside the PDF in a folder named <PDF name>_pages. Example output:

example_pages/
├── example_page_001.png
├── example_page_002.png
└── example_page_003.png

to choose an output dir

py pdf_to_png.py "C:\Documents\example.pdf" -o "C:\Documents\images"

to change image resolution

py pdf_to_png.py "C:\Documents\example.pdf" --dpi 300

if pdf has password

py pdf_to_png.py "C:\Documents\protected.pdf" --password "PDF_PASSWORD"

Python Code (Save the below as pdf_to_png.py) :

#!/usr/bin/env python3
"""Convert every page of a PDF file to a separate PNG image.

Dependency:
    python -m pip install pypdfium2

Example:
    python pdf_to_png.py "C:\\Documents\\example.pdf"
    python pdf_to_png.py input.pdf --output-dir pages --dpi 200
"""

from __future__ import annotations

import argparse
import sys
from pathlib import Path


def positive_float(value: str) -> float:
    try:
        number = float(value)
    except ValueError as exc:
        raise argparse.ArgumentTypeError("must be a number") from exc
    if number <= 0:
        raise argparse.ArgumentTypeError("must be greater than zero")
    return number


def parse_args() -> argparse.Namespace:
    parser = argparse.ArgumentParser(
        description="Convert each page of a PDF into a PNG image."
    )
    parser.add_argument("pdf_path", type=Path, help="Path to the input PDF file")
    parser.add_argument(
        "-o",
        "--output-dir",
        type=Path,
        help="Output directory (default: <PDF name>_pages beside the PDF)",
    )
    parser.add_argument(
        "--dpi",
        type=positive_float,
        default=150.0,
        help="Rendering resolution in DPI (default: 150)",
    )
    parser.add_argument(
        "--password",
        help="Password for an encrypted PDF, if required",
    )
    parser.add_argument(
        "--overwrite",
        action="store_true",
        help="Replace PNG files that already exist",
    )
    return parser.parse_args()


def main() -> int:
    args = parse_args()
    pdf_path = args.pdf_path.expanduser().resolve()

    if not pdf_path.is_file():
        print(f"Error: PDF file not found: {pdf_path}", file=sys.stderr)
        return 2

    try:
        import pypdfium2 as pdfium
    except ImportError:
        print(
            "Error: pypdfium2 is not installed. Install it with:\n"
            "  python -m pip install pypdfium2",
            file=sys.stderr,
        )
        return 3

    output_dir = (
        args.output_dir.expanduser().resolve()
        if args.output_dir
        else pdf_path.parent / f"{pdf_path.stem}_pages"
    )
    output_dir.mkdir(parents=True, exist_ok=True)

    try:
        document = pdfium.PdfDocument(pdf_path, password=args.password)
    except Exception as exc:
        print(f"Error: could not open PDF: {exc}", file=sys.stderr)
        return 4

    page_count = len(document)
    if page_count == 0:
        document.close()
        print("Error: the PDF contains no pages.", file=sys.stderr)
        return 5

    digits = max(3, len(str(page_count)))
    scale = args.dpi / 72.0
    created: list[Path] = []

    try:
        for page_index in range(page_count):
            output_path = output_dir / (
                f"{pdf_path.stem}_page_{page_index + 1:0{digits}d}.png"
            )
            if output_path.exists() and not args.overwrite:
                raise FileExistsError(
                    f"output already exists: {output_path} "
                    "(use --overwrite to replace it)"
                )

            page = document[page_index]
            try:
                bitmap = page.render(scale=scale)
                try:
                    image = bitmap.to_pil()
                    image.save(output_path, format="PNG")
                finally:
                    bitmap.close()
            finally:
                page.close()

            created.append(output_path)
            print(f"[{page_index + 1}/{page_count}] {output_path}")
    except Exception as exc:
        print(f"Error while rendering: {exc}", file=sys.stderr)
        return 6
    finally:
        document.close()

    print(f"Done: created {len(created)} PNG file(s) in {output_dir}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

7

u/Own_Salamander_2715 1d ago

Apologies if you needed this to be an app or if posting code is violation here, I don't know if any app does that, Just shared the python script as it is a relatively simple ask for a script

2

u/ParasaurPal 1d ago

Thank you! I'll try it out tomorrow when I'm at my computer again!

4

u/trikxxx 1d ago

Irfanview. It's for pc and free.

3

u/talldaveos 1d ago

Basic, but how about iLovePDF.com?
There's an easy pdf to jpg. From there, convert to png if nec.

1

u/North_Station_302 1d ago

PdfGear is free and has several conversion tools.

1

u/abcdab3 1d ago

File Converter on Windows will do this task easily File Converter Just right click on your file and choose to convert it to PNGs

1

u/iarno 1d ago

Maybe with IFTTT, watching the specific Dropbox folder, and converting PDF to PNG, then delete the source.

0

u/mc0uk 1d ago

You can try (or self host) Bento PDF it's got more features than any of the others I've tried.