Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/api-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,11 @@ formats.
[convert_to_jpeg][pdfrest.PdfRestClient.convert_to_jpeg],
[convert_to_tiff][pdfrest.PdfRestClient.convert_to_tiff]

All PDF-to-image helpers accept `password` for opening an encrypted input PDF.
See the
[password-protected PDF example](https://github.com/pdfrest/pdfrest-python/blob/main/examples/convert_to_image/convert_password_protected_pdf_to_png_example.py)
for the complete upload, protection, and conversion workflow.

## Forms data workflows

Use this group when users need to transfer form field values in/out of PDFs.
Expand Down
3 changes: 3 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ supported interpreter matrix.
format-specific options.
- `examples/convert_postscript_to_pdf/convert_postscript_with_job_options_example.py`
– convert PostScript to PDF with an uploaded custom `.joboptions` profile.
- `examples/convert_to_image/convert_password_protected_pdf_to_png_example.py` –
convert a password-protected PDF into PNG images by supplying its open
password.
- `examples/delete/delete_example.py` – demonstrate file deletion (sync + async
variants).
- `examples/extract_text/extract_pdf_text_example.py` – run `extract_pdf_text`
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# /// script
# requires-python = ">=3.10"
# dependencies = ["pdfrest", "python-dotenv"]
# ///
"""Convert a password-protected PDF into PNG images.

This sample demonstrates how to:

1. Upload the bundled ``examples/resources/report.pdf`` resource.
2. Add an open password to create a protected PDF.
3. Supply that password to ``convert_to_png``.
4. Print metadata for every generated PNG image.

Set ``PDFREST_API_KEY``, then run from the repository root with
``uv run examples/convert_to_image/convert_password_protected_pdf_to_png_example.py``.
The input PDF is included in the repository, so no additional files are required.
"""

from __future__ import annotations

from pathlib import Path

from dotenv import load_dotenv

from pdfrest import PdfRestClient

RESOURCE = Path(__file__).resolve().parents[1] / "resources" / "report.pdf"
PASSWORD = "example-password" # noqa: S105 - Demonstration-only password.


def convert_password_protected_pdf() -> None:
"""Protect the sample PDF, then convert its pages with the same password."""
load_dotenv()

with PdfRestClient() as client:
uploaded = client.files.create_from_paths([RESOURCE])[0]
protected = client.add_open_password(
uploaded,
new_open_password=PASSWORD,
output="password-protected-report",
).output_file
response = client.convert_to_png(
protected,
password=PASSWORD,
output_prefix="password-protected-report-page",
)

print(f"Created {len(response.output_files)} PNG image(s)")
for output in response.output_files:
print(f"{output.name}: {output.type}, {output.size} bytes")
print(f" Download URL: {output.url}")


if __name__ == "__main__": # pragma: no cover - manual example
convert_password_protected_pdf()
40 changes: 40 additions & 0 deletions src/pdfrest/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5780,6 +5780,7 @@ def convert_to_png(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: PngColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
extra_query: Query | None = None,
Expand All @@ -5796,6 +5797,7 @@ def convert_to_png(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
extra_query: Additional query parameters merged into the request.
Expand All @@ -5820,6 +5822,8 @@ def convert_to_png(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return self._convert_to_graphic(
endpoint="/png",
Expand All @@ -5838,6 +5842,7 @@ def convert_to_bmp(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: BmpColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
extra_query: Query | None = None,
Expand All @@ -5854,6 +5859,7 @@ def convert_to_bmp(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
extra_query: Additional query parameters merged into the request.
Expand All @@ -5878,6 +5884,8 @@ def convert_to_bmp(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return self._convert_to_graphic(
endpoint="/bmp",
Expand All @@ -5896,6 +5904,7 @@ def convert_to_gif(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: GifColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
extra_query: Query | None = None,
Expand All @@ -5912,6 +5921,7 @@ def convert_to_gif(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
extra_query: Additional query parameters merged into the request.
Expand All @@ -5936,6 +5946,8 @@ def convert_to_gif(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return self._convert_to_graphic(
endpoint="/gif",
Expand All @@ -5954,6 +5966,7 @@ def convert_to_jpeg(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: JpegColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
jpeg_quality: int = 75,
Expand All @@ -5971,6 +5984,7 @@ def convert_to_jpeg(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
jpeg_quality: JPEG quality setting (1-100) controlling compression level and output fidelity.
Expand All @@ -5997,6 +6011,8 @@ def convert_to_jpeg(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return self._convert_to_graphic(
endpoint="/jpg",
Expand All @@ -6015,6 +6031,7 @@ def convert_to_tiff(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: TiffColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
extra_query: Query | None = None,
Expand All @@ -6031,6 +6048,7 @@ def convert_to_tiff(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
extra_query: Additional query parameters merged into the request.
Expand All @@ -6055,6 +6073,8 @@ def convert_to_tiff(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return self._convert_to_graphic(
endpoint="/tif",
Expand Down Expand Up @@ -9108,6 +9128,7 @@ async def convert_to_png(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: PngColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
extra_query: Query | None = None,
Expand All @@ -9124,6 +9145,7 @@ async def convert_to_png(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
extra_query: Additional query parameters merged into the request.
Expand All @@ -9148,6 +9170,8 @@ async def convert_to_png(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return await self._convert_to_graphic(
endpoint="/png",
Expand All @@ -9166,6 +9190,7 @@ async def convert_to_bmp(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: BmpColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
extra_query: Query | None = None,
Expand All @@ -9182,6 +9207,7 @@ async def convert_to_bmp(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
extra_query: Additional query parameters merged into the request.
Expand All @@ -9206,6 +9232,8 @@ async def convert_to_bmp(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return await self._convert_to_graphic(
endpoint="/bmp",
Expand All @@ -9224,6 +9252,7 @@ async def convert_to_gif(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: GifColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
extra_query: Query | None = None,
Expand All @@ -9240,6 +9269,7 @@ async def convert_to_gif(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
extra_query: Additional query parameters merged into the request.
Expand All @@ -9264,6 +9294,8 @@ async def convert_to_gif(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return await self._convert_to_graphic(
endpoint="/gif",
Expand All @@ -9282,6 +9314,7 @@ async def convert_to_jpeg(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: JpegColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
jpeg_quality: int = 75,
Expand All @@ -9299,6 +9332,7 @@ async def convert_to_jpeg(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
jpeg_quality: JPEG quality setting (1-100) controlling compression level and output fidelity.
Expand All @@ -9325,6 +9359,8 @@ async def convert_to_jpeg(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return await self._convert_to_graphic(
endpoint="/jpg",
Expand All @@ -9343,6 +9379,7 @@ async def convert_to_tiff(
output_prefix: str | None = None,
page_range: str | Sequence[str] | None = None,
resolution: int = 300,
password: str | None = None,
color_model: TiffColorModel = "rgb",
smoothing: GraphicSmoothing | Sequence[GraphicSmoothing] = "none",
extra_query: Query | None = None,
Expand All @@ -9359,6 +9396,7 @@ async def convert_to_tiff(
output_prefix: Filename prefix used for generated per-page/per-file image outputs.
page_range: Page selection string/list for image conversion outputs.
resolution: Raster output resolution in DPI for generated image files.
password: Password for opening an encrypted input PDF.
color_model: Output image color model.
smoothing: Graphic smoothing mode for image output endpoints.
extra_query: Additional query parameters merged into the request.
Expand All @@ -9383,6 +9421,8 @@ async def convert_to_tiff(
payload["output_prefix"] = output_prefix
if page_range is not None:
payload["page_range"] = page_range
if password is not None:
payload["password"] = password

return await self._convert_to_graphic(
endpoint="/tif",
Expand Down
4 changes: 4 additions & 0 deletions src/pdfrest/models/_internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1648,6 +1648,10 @@ class BasePdfRestGraphicPayload(BaseModel, Generic[ColorModelT]):
PlainSerializer(_serialize_page_ranges),
]
resolution: Annotated[int, Field(ge=12, le=2400, default=300)]
password: Annotated[
str | None,
Field(min_length=1, default=None),
] = None
color_model: Annotated[ColorModelT, Field(default=...)]
smoothing: Annotated[
list[Literal["none", "all", "text", "line", "image"]],
Expand Down
Loading
Loading