pdf_to_image_converter 0.0.4 copy "pdf_to_image_converter: ^0.0.4" to clipboard
pdf_to_image_converter: ^0.0.4 copied to clipboard

A comprehensive Flutter package for converting PDF documents to images with quality presets, page rotation, thumbnail generation, batch processing, cancellation support, and metadata extraction. Perfe [...]

pdf_to_image_converter #

A Flutter package that provides easy-to-use utilities for converting PDF documents to images. Perfect for apps that need to display, edit, or share PDF content as images.

Features #

  • PDF File Selection - Built-in file picker for easy PDF selection
  • Page-by-Page Rendering - Convert individual PDF pages to high-quality images
  • Quality Presets - 6 predefined quality levels (thumbnail, low, medium, high, print, ultra)
  • Page Rotation - Render pages at 0°, 90°, 180°, or 270° angles
  • Batch Processing - Render and save all pages at once with progress tracking
  • Page Range Rendering - Convert specific page ranges (e.g., pages 5-10)
  • Thumbnail Generation - Quick low-resolution previews with custom dimensions
  • Custom Per-Page Settings - Different quality/rotation for each page in batch operations
  • Cancellation Support - Stop long-running operations mid-process
  • Page Dimensions - Get size and dimensions for single or all pages
  • PDF Metadata - Extract document info (title, page count, etc.)
  • File Export - Save rendered images to files with custom paths and naming
  • High Performance - Optimized rendering with customizable scale
  • Progress Callbacks - Track rendering and saving progress in real-time
  • Fully Documented - 100% dartdoc coverage for all public APIs

Installation #

  1. Add the latest version of package to your pubspec.yaml (and run dart pub get):
dependencies:
  pdf_to_image_converter: ^0.0.4
  1. Import the package and use it in your Flutter App.
import 'package:pdf_to_image_converter/pdf_to_image_converter.dart';

Example #

The pdf_to_image_converter package allows you to select a PDF file, render its pages as images, and save them to the gallery.


import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:pdf_to_image_converter/pdf_to_image_converter.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PDF to Image Converter',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const PdfToImageScreen(),
    );
  }
}

class PdfToImageScreen extends StatefulWidget {
  const PdfToImageScreen({Key? key}) : super(key: key);

  @override
  State<PdfToImageScreen> createState() => _PdfToImageScreenState();
}

class _PdfToImageScreenState extends State<PdfToImageScreen> {
  final PdfImageConverter _converter = PdfImageConverter();
  Uint8List? _image;

  void _showSnackbar(String message) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(message),
        duration: const Duration(seconds: 2),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('PDF to Image Converter'),
      ),
      body: Center(
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              ElevatedButton(
                child: const Text('Select PDF'),
                onPressed: () async {
                  final path = await PdfPicker.pickPdf();
                  if (path != null) {
                    await _converter.openPdf(path);
                    _image = await _converter.renderPage(0);
                    setState(() {});
                  }
                },
              ),
              if (_converter.isOpen)
                ElevatedButton(
                  child: const Text('Close PDF'),
                  onPressed: () async {
                    await _converter.closePdf();
                    setState(() {});
                  },
                ),
              if (_image != null) ...[
                const Text('Image area:'),
                Image(image: MemoryImage(_image!)),
                ElevatedButton(
                  child: const Text('Save Image'),
                  onPressed: () async {
                    if (_image != null) {
                      final directory = await getApplicationDocumentsDirectory();
                      final filePath = '${directory.path}/page_${_converter.currentPage + 1}.png';
                      
                      await _converter.saveImage(_image!, filePath, (bool isSuccess) {
                        _showSnackbar(
                          isSuccess
                              ? 'Image saved to: $filePath'
                              : 'Failed to save image.',
                        );
                      });
                    }
                  },
                ),
              ],
              if (_converter.isOpen) ...[
                Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    TextButton.icon(
                      onPressed: _converter.currentPage > 0
                          ? () async {
                              _image = await _converter.renderPage(
                                  _converter.currentPage - 1);
                              setState(() {});
                            }
                          : null,
                      icon: const Icon(Icons.chevron_left),
                      label: const Text('Previous'),
                    ),
                    TextButton.icon(
                      onPressed: _converter.currentPage < (_converter.pageCount - 1)
                          ? () async {
                              _image = await _converter.renderPage(
                                  _converter.currentPage + 1);
                              setState(() {});
                            }
                          : null,
                      icon: const Icon(Icons.chevron_right),
                      label: const Text('Next'),
                    ),
                  ],
                ),
              ],
            ],
          ),
        ),
      ),
    );
  }
}


Quick Start #

Here's a minimal example to get you started:

import 'dart:io';
import 'package:pdf_to_image_converter/pdf_to_image_converter.dart';
import 'package:path_provider/path_provider.dart';

// Pick a PDF file
final path = await PdfPicker.pickPdf();

if (path != null) {
  // Create converter instance
  final converter = PdfImageConverter();
  
  // Open the PDF
  await converter.openPdf(path);
  
  // Get PDF metadata
  print('Total pages: ${converter.pageCount}');
  print('Title: ${converter.metadata?.title}');
  
  // Get page dimensions
  final size = await converter.getPageSize(0);
  print('Page size: ${size?.width} x ${size?.height}');
  
  // Render with quality preset
  final imageBytes = await converter.renderPage(
    0, 
    quality: RenderQuality.high,
  );
  
  // Get directory to save image
  final directory = await getApplicationDocumentsDirectory();
  final filePath = '${directory.path}/page_1.png';
  
  // Save to file
  await converter.saveImage(imageBytes, filePath, (success) {
    print('Saved: $success');
  });
  
  // Clean up
  await converter.closePdf();
}

Batch Processing with Cancellation #

Convert all pages at once with progress tracking and cancellation support:

import 'dart:io';
import 'package:path_provider/path_provider.dart';

final path = await PdfPicker.pickPdf();
if (path != null) {
  final converter = PdfImageConverter();
  await converter.openPdf(path);
  
  // Create cancellation token
  final token = CancellationToken();
  
  // Render all pages with progress and quality preset
  final images = await converter.renderAllPages(
    quality: RenderQuality.medium,
    cancellationToken: token,
    onProgress: (current, total) {
      print('Rendering: $current/$total');
      // Cancel after 5 pages if needed
      // if (current >= 5) token.cancel();
    },
  );
  
  // Get output directory
  final directory = await getApplicationDocumentsDirectory();
  final outputDir = '${directory.path}/pdf_images';
  
  // Save all images with progress
  final saved = await converter.saveAllImages(
    images,
    outputDir,
    fileNamePattern: 'page_{index}.png',
    cancellationToken: token,
    onProgress: (current, total, success) {
      print('Saving: $current/$total - Success: $success');
    },
  );
  
  print('Saved $saved images to $outputDir');
  await converter.closePdf();
}

Usage Examples #

1. Using Quality Presets #

Quality presets provide optimized settings for different use cases:

// Thumbnail quality (1.0x) - Fast, low quality
final thumbnail = await converter.renderPage(0, quality: RenderQuality.thumbnail);

// Low quality (1.5x) - Quick previews
final preview = await converter.renderPage(0, quality: RenderQuality.low);

// Medium quality (2.0x) - Balanced
final medium = await converter.renderPage(0, quality: RenderQuality.medium);

// High quality (3.0x) - Default, best for viewing
final high = await converter.renderPage(0, quality: RenderQuality.high);

// Print quality (4.0x) - High resolution
final print = await converter.renderPage(0, quality: RenderQuality.print);

// Ultra quality (5.0x) - Maximum quality
final ultra = await converter.renderPage(0, quality: RenderQuality.ultra);

2. Page Rotation #

Rotate pages while rendering:

// Normal orientation
final normal = await converter.renderPage(0, rotation: PageRotation.rotate0);

// Rotate 90 degrees clockwise
final rotated90 = await converter.renderPage(0, rotation: PageRotation.rotate90);

// Rotate 180 degrees
final rotated180 = await converter.renderPage(0, rotation: PageRotation.rotate180);

// Rotate 270 degrees clockwise (90 counter-clockwise)
final rotated270 = await converter.renderPage(0, rotation: PageRotation.rotate270);

3. Page Range Rendering #

Convert only specific pages:

// Render pages 5-10 (indices 4-9)
final images = await converter.renderPageRange(
  startPage: 4,
  endPage: 9,
  quality: RenderQuality.medium,
  onProgress: (current, total) {
    print('Progress: $current/$total');
  },
);

4. Thumbnail Generation #

Quick low-resolution previews:

// Single thumbnail
final thumbnail = await converter.renderThumbnail(
  0,
  maxWidth: 200,
  maxHeight: 300,
);

// All thumbnails
final thumbnails = await converter.renderAllThumbnails(
  maxWidth: 150,
  maxHeight: 200,
  onProgress: (current, total) {
    print('Generated $current/$total thumbnails');
  },
);

5. Custom Settings Per Page #

Apply different settings to different pages:

final images = await converter.renderPagesWithConfig([
  PageRenderConfig(
    pageIndex: 0, 
    scale: 2.0,
    background: Colors.white,
  ),
  PageRenderConfig(
    pageIndex: 1, 
    scale: 3.0, 
    rotation: PageRotation.rotate90,
  ),
  PageRenderConfig(
    pageIndex: 2, 
    scale: 1.5,
    background: Colors.grey[200]!,
  ),
]);

6. Cancellation Support #

Stop long operations:

final token = CancellationToken();

// Start rendering in background
Future.delayed(Duration.zero, () async {
  final images = await converter.renderAllPages(
    quality: RenderQuality.high,
    cancellationToken: token,
    onProgress: (current, total) {
      print('Rendering: $current/$total');
    },
  );
  print('Completed: ${images.length} pages');
});

// Cancel after 3 seconds
await Future.delayed(Duration(seconds: 3));
token.cancel();
print('Cancelled!');

7. Getting All Page Sizes #

Analyze page dimensions before rendering:

final sizes = await converter.getAllPageSizes();
for (int i = 0; i < sizes.length; i++) {
  print('Page $i: ${sizes[i].width} x ${sizes[i].height}');
}

8. Accessing PDF Metadata #

Get document information:

await converter.openPdf(path);
final metadata = converter.metadata;
print('Page count: ${metadata?.pageCount}');
print('Title: ${metadata?.title}');

API Documentation #

PdfImageConverter #

Main class for handling PDF to image conversion.

Properties

  • bool isOpen - Returns true if a PDF is currently open
  • int pageCount - Total number of pages in the open PDF
  • int currentPage - Index of the currently rendered page
  • PdfMetadata? metadata - Metadata of the currently open PDF

Core Methods

  • Future<void> openPdf(String path) - Opens a PDF from file path
  • Future<void> closePdf() - Closes the PDF and releases resources

Rendering Methods

  • Future<Uint8List?> renderPage(int pageIndex, {double? scale, RenderQuality quality, Color background, PageRotation rotation}) - Renders a single page with customizable settings
  • Future<List<Uint8List?>> renderAllPages({double? scale, RenderQuality quality, Color background, PageRotation rotation, CancellationToken? cancellationToken, Function? onProgress}) - Renders all pages with optional cancellation
  • Future<List<Uint8List?>> renderPageRange({required int startPage, required int endPage, double? scale, RenderQuality quality, Color background, PageRotation rotation, CancellationToken? cancellationToken, Function? onProgress}) - Renders a specific range of pages
  • Future<Uint8List?> renderThumbnail(int pageIndex, {double maxWidth, double maxHeight, Color background}) - Generates a thumbnail with max dimensions
  • Future<List<Uint8List?>> renderAllThumbnails({double maxWidth, double maxHeight, Color background, CancellationToken? cancellationToken, Function? onProgress}) - Generates thumbnails for all pages
  • Future<List<Uint8List?>> renderPagesWithConfig(List<PageRenderConfig> pageConfigs, {CancellationToken? cancellationToken, Function? onProgress}) - Renders multiple pages with custom settings per page

Page Information Methods

  • Future<Size?> getPageSize(int pageIndex) - Gets the dimensions of a specific page
  • Future<List<Size>> getAllPageSizes() - Gets dimensions of all pages

Saving Methods

  • Future<void> saveImage(Uint8List imageBytes, String filePath, Function(bool) onSave) - Saves a single image to file
  • Future<int> saveAllImages(List<Uint8List?> imagesList, String outputDirectory, {String fileNamePattern, CancellationToken? cancellationToken, Function? onProgress}) - Saves multiple images with custom naming

RenderQuality Enum #

Predefined quality presets:

  • RenderQuality.thumbnail - 1.0x scale
  • RenderQuality.low - 1.5x scale
  • RenderQuality.medium - 2.0x scale
  • RenderQuality.high - 3.0x scale (default)
  • RenderQuality.print - 4.0x scale
  • RenderQuality.ultra - 5.0x scale

PageRotation Enum #

Rotation angles:

  • PageRotation.rotate0 - No rotation (0°)
  • PageRotation.rotate90 - 90° clockwise
  • PageRotation.rotate180 - 180° rotation
  • PageRotation.rotate270 - 270° clockwise (90° counter-clockwise)

PageRenderConfig Class #

Configuration for rendering individual pages:

PageRenderConfig({
  required int pageIndex,
  double scale = 3.0,
  Color background = Colors.white,
  PageRotation rotation = PageRotation.rotate0,
})

CancellationToken Class #

Token for cancelling operations:

  • bool isCancelled - Check if cancellation was requested
  • void cancel() - Request cancellation
  • void reset() - Reset the token state

PdfMetadata Class #

Contains PDF document metadata:

  • int pageCount - Total number of pages
  • String? title - Document title
  • String? author - Document author
  • String? subject - Document subject
  • String? creator - Creating application
  • String? producer - PDF producer
  • DateTime? creationDate - Creation date
  • DateTime? modificationDate - Last modification date

PdfPicker #

Utility class for PDF file selection.

Methods

  • static Future<String?> pickPdf() - Opens file picker for PDF selection

Platform Configuration #

Android #

Add file access permissions to android/app/src/main/AndroidManifest.xml:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

For Android 13+ (API 33+), also add:

<uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>

iOS #

Add file picker permission to ios/Runner/Info.plist:

<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to select PDF files</string>

Note on Saving Images #

This package saves images to files on the device. To save to the gallery, use additional packages like gallery_saver or image_gallery_saver in combination with this package.

Advanced Examples #

Complete Workflow with All Features #

import 'package:pdf_to_image_converter/pdf_to_image_converter.dart';
import 'package:path_provider/path_provider.dart';

Future<void> advancedPdfConversion() async {
  // 1. Pick PDF
  final path = await PdfPicker.pickPdf();
  if (path == null) return;
  
  final converter = PdfImageConverter();
  
  // 2. Open and inspect
  await converter.openPdf(path);
  print('Pages: ${converter.pageCount}');
  print('Title: ${converter.metadata?.title}');
  
  // 3. Get all page sizes
  final sizes = await converter.getAllPageSizes();
  print('First page: ${sizes[0].width} x ${sizes[0].height}');
  
  // 4. Generate thumbnails for preview
  final thumbnails = await converter.renderAllThumbnails(
    maxWidth: 150,
    maxHeight: 200,
    onProgress: (current, total) {
      print('Thumbnail: $current/$total');
    },
  );
  
  // 5. Render specific pages with different settings
  final token = CancellationToken();
  final images = await converter.renderPagesWithConfig([
    PageRenderConfig(pageIndex: 0, scale: 4.0), // High quality cover
    PageRenderConfig(pageIndex: 1, scale: 2.0), // Medium quality
    PageRenderConfig(
      pageIndex: 2, 
      scale: 2.0, 
      rotation: PageRotation.rotate90,
    ), // Rotated
  ], cancellationToken: token);
  
  // 6. Render page range with rotation
  final pages5to10 = await converter.renderPageRange(
    startPage: 4,
    endPage: 9,
    quality: RenderQuality.medium,
    rotation: PageRotation.rotate0,
  );
  
  // 7. Save with custom naming
  final directory = await getApplicationDocumentsDirectory();
  final saved = await converter.saveAllImages(
    images,
    '${directory.path}/pdf_output',
    fileNamePattern: 'document_page_{index}.png',
    onProgress: (current, total, success) {
      print('Saved: $current/$total - ${success ? "Success" : "Failed"}');
    },
  );
  
  print('Total saved: $saved images');
  
  // 8. Clean up
  await converter.closePdf();
}

Performance Optimization #

Choose the right quality for your use case:

// For preview/thumbnails - Fast rendering
final preview = await converter.renderPage(0, quality: RenderQuality.thumbnail);

// For in-app display - Balanced
final display = await converter.renderPage(0, quality: RenderQuality.medium);

// For export/sharing - High quality
final export = await converter.renderPage(0, quality: RenderQuality.print);

// For archival/professional use - Maximum quality
final archival = await converter.renderPage(0, quality: RenderQuality.ultra);

Example App #

For a complete working example, check the example directory. It demonstrates:

  • PDF file selection with PdfPicker
  • Quality presets selection
  • Page rotation controls
  • Page rendering with custom quality
  • Page navigation with page counter
  • Page range rendering
  • Thumbnail generation
  • Batch rendering and saving all pages
  • Cancellation of operations
  • Progress tracking for batch operations
  • Image preview and display
  • Metadata display
  • Status updates and loading indicators

Run the example:

cd example
flutter pub get
flutter run

Contributing #

Contributions are welcome! Please feel free to submit a Pull Request.

License #

This project is licensed under the MIT License - see the LICENSE file for details.

Issues and Feedback #

Please file issues, bugs, or feature requests in our issue tracker.

Performance Tips #

  1. Choose appropriate quality: Use lower quality presets for previews and higher for final output
  2. Use page ranges: Instead of rendering all pages, render only what's needed
  3. Generate thumbnails first: Show quick previews before full rendering
  4. Use cancellation: Allow users to stop long operations
  5. Batch operations wisely: Break large PDFs into smaller chunks
  6. Memory management: Always call closePdf() when done

Troubleshooting #

Issue: Out of memory with large PDFs

  • Solution: Use lower quality presets or render pages in smaller batches

Issue: Rendering is slow

  • Solution: Use RenderQuality.thumbnail or RenderQuality.low for previews, then render at higher quality only when needed

Issue: Images are blurry

  • Solution: Increase quality preset (e.g., RenderQuality.print or RenderQuality.ultra)

Issue: Need to stop a long operation

  • Solution: Use CancellationToken with rendering and saving methods

Changelog #

Latest Version #

  • Added quality presets (thumbnail, low, medium, high, print, ultra)
  • Added page rotation support (0°, 90°, 180°, 270°)
  • Added page range rendering
  • Added thumbnail generation methods
  • Added cancellation support with CancellationToken
  • Added custom per-page rendering configurations
  • Added PDF metadata extraction
  • Added getAllPageSizes method
  • Enhanced documentation with comprehensive examples

Next Goals #

  • Add support for text extraction from PDFs
  • Add watermark support
  • Add image compression options
  • Add support for encrypted PDFs
  • Add batch conversion from multiple PDFs
16
likes
150
points
237
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive Flutter package for converting PDF documents to images with quality presets, page rotation, thumbnail generation, batch processing, cancellation support, and metadata extraction. Perfect for PDF viewing and conversion apps.

Repository (GitHub)
View/report issues

Topics

#pdf #image #converter #pdf-to-image #rendering

Documentation

Documentation
API reference

License

BSD-3-Clause (license)

Dependencies

file_picker, flutter, pdf_image_renderer

More

Packages that depend on pdf_to_image_converter