# Source: https://trigger.dev/docs/guides/examples/pdf-to-image.md

> ## Documentation Index
> Fetch the complete documentation index at: https://trigger.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Turn a PDF into an image using MuPDF

> This example will show you how to turn a PDF into an image using MuPDF and Trigger.dev.

export const packages_0 = "mupdf-tools from MuPDF"

## Overview

This example demonstrates how to use Trigger.dev to turn a PDF into a series of images using MuPDF and upload them to Cloudflare R2.

## Update your build configuration

To use this example, add these build settings below to your `trigger.config.ts` file. They ensure that the `mutool` and `curl` packages are installed when you deploy your task. You can learn more about this and see more build settings [here](/config/extensions/aptGet).

```ts trigger.config.ts theme={"theme":"css-variables"}
export default defineConfig({
  project: "<project ref>",
  // Your other config settings...
  build: {
    extensions: [aptGet({ packages: ["mupdf-tools", "curl"] })],
  },
});
```

## Task code

```ts trigger/pdfToImage.ts theme={"theme":"css-variables"}
import { logger, task } from "@trigger.dev/sdk";
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { execSync } from "child_process";
import fs from "fs";
import path from "path";

// Initialize S3 client
const s3Client = new S3Client({
  region: "auto",
  endpoint: process.env.S3_ENDPOINT,
  credentials: {
    accessKeyId: process.env.R2_ACCESS_KEY_ID ?? "",
    secretAccessKey: process.env.R2_SECRET_ACCESS_KEY ?? "",
  },
});

export const pdfToImage = task({
  id: "pdf-to-image",
  run: async (payload: { pdfUrl: string; documentId: string }) => {
    logger.log("Converting PDF to images", payload);

    const pdfPath = `/tmp/${payload.documentId}.pdf`;
    const outputDir = `/tmp/${payload.documentId}`;

    // Download PDF and convert to images using MuPDF
    execSync(`curl -s -o ${pdfPath} ${payload.pdfUrl}`);
    fs.mkdirSync(outputDir, { recursive: true });
    execSync(`mutool convert -o ${outputDir}/page-%d.png ${pdfPath}`);

    // Upload images to R2
    const uploadedUrls = [];
    for (const file of fs.readdirSync(outputDir)) {
      const s3Key = `images/${payload.documentId}/${file}`;
      const uploadParams = {
        Bucket: process.env.S3_BUCKET,
        Key: s3Key,
        Body: fs.readFileSync(path.join(outputDir, file)),
        ContentType: "image/png",
      };

      logger.log("Uploading to R2", uploadParams);

      await s3Client.send(new PutObjectCommand(uploadParams));
      const s3Url = `https://${process.env.S3_BUCKET}.r2.cloudflarestorage.com/${s3Key}`;
      uploadedUrls.push(s3Url);
      logger.log("Image uploaded to R2", { url: s3Url });
    }

    // Clean up
    fs.rmSync(outputDir, { recursive: true, force: true });
    fs.unlinkSync(pdfPath);

    logger.log("All images uploaded to R2", { urls: uploadedUrls });

    return {
      imageUrls: uploadedUrls,
    };
  },
});
```

## Testing your task

To test this task in the dashboard, you can use the following payload:

```json  theme={"theme":"css-variables"}
{
  "pdfUrl": "https://pdfobject.com/pdf/sample.pdf",
  "documentId": "unique-document-id"
}
```

## Local development

To test this example task locally, be sure to install any packages from the build extensions you added to your `trigger.config.ts` file to your local machine. In this case, you need to install {packages_0}.