技术文章

在 Delphi 中使用 PDFium VCL 将 PDF 页面转换为 JPEG 图像

· PDF 编程

将 PDF 页面转换为图像对于生成缩略图、预览和网页显示至关重要。 PDF 转 JPG 演示程序展示了如何使用 PDFium VCL 将 PDF 页面渲染为高质量的 JPEG 图像。

概述

此演示程序将 PDF 页面转换为 JPEG 图像,并提供可自定义的 DPI、质量设置和页面选择功能。它非常适合生成缩略图、创建基于图像的存档或为网页显示准备 PDF 文件。

主要特性

  • 可自定义的 DPI – 控制输出分辨率(72-600 DPI)
  • 质量设置 – 调整 JPEG 压缩质量
  • 页面选择 – 转换所有页面或指定页面范围
  • 输出目录 – 选择保存转换后图像的位置
  • 进度跟踪 – 转换过程中的可视化反馈
  • 取消支持 – 随时取消长时间的转换

PDFium DLL 的要求

在运行任何 PDFium VCL 应用程序之前,请确保已安装 PDFium DLL 文件:

  • pdfium32.dll / pdfium64.dll – 标准版本(约 5-6 MB)
  • pdfium32v8.dll / pdfium64v8.dll – 包含 V8 JavaScript 引擎的版本(约 23-27 MB)

安装: 运行 PDFiumVCL\DLLs\CopyDlls.bat 以管理员身份,自动将 DLL 文件复制到 Windows 系统目录。

基础的 PDF 转换为图像

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
procedure ConvertPdfToImages;
var
  Pdf: TPdf;
  I: Integer;
  Bitmap: TBitmap;
  JpegImage: TJpegImage;
  Dpi: Integer;
begin
  Dpi := 150; // 150 DPI is good for screen viewing
  
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'document.pdf';
    Pdf.Active := True;
    
    for I := 1 to Pdf.PageCount do
    begin
      Pdf.PageNumber := I;
      
      // Calculate size based on DPI
      // PDF default is 72 DPI, so scale accordingly
      Bitmap := Pdf.RenderPage(
        0, 0,
        Round(Pdf.PageWidth * Dpi / 72),
        Round(Pdf.PageHeight * Dpi / 72),
        ro0,      // No rotation
        [],       // Default render options
        clWhite   // Background color
      );
      
      try
        // Convert to JPEG
        JpegImage := TJpegImage.Create;
        try
          JpegImage.Assign(Bitmap);
          JpegImage.CompressionQuality := 85;
          JpegImage.SaveToFile(Format('page_%03d.jpg', [I]));
        finally
          JpegImage.Free;
        end;
      finally
        Bitmap.Free;
      end;
    end;
    
  finally
    Pdf.Active := False;
    Pdf.Free;
  end;
end;

带有选项的完整转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
procedure TFormMain.ButtonConvertClick(Sender: TObject);
var
  I: Integer;
  OutDir, BaseName, FileName: string;
  JpegImage: TJpegImage;
  Bitmap: TBitmap;
  Dpi, Quality: Integer;
  Pages: TIntArray;
  PageDigits: Integer;
  UseAllPages: Boolean;
begin
  ProgressBar.Position := 0;
  FCancelRequested := False;
  Screen.Cursor := crHourGlass;
  
  try
    try
      if not FileExists(EditPdfFile.Text) then
        raise Exception.Create('PDF file does not exist.');
        
      // Parse settings
      Dpi := StrToIntDef(Trim(EditDPI.Text), 150);
      if Dpi <= 0 then Dpi := 150;
      if Dpi > 600 then Dpi := 600;
      
      Quality := StrToIntDef(Trim(EditQuality.Text), 85);
      if Quality < 1 then Quality := 1;
      if Quality > 100 then Quality := 100;
      
      // Load PDF
      Pdf.FileName := EditPdfFile.Text;
      Pdf.Active := True;
      
      // Parse page ranges
      UseAllPages := Trim(EditPageRange.Text) = '';
      if UseAllPages then
      begin
        SetLength(Pages, Pdf.PageCount);
        for I := 1 to Pdf.PageCount do
          Pages[I - 1] := I;
      end
      else
      begin
        if not ParsePageRanges(EditPageRange.Text, Pdf.PageCount, Pages) then
          raise Exception.Create('Invalid page range.');
      end;
      
      ProgressBar.Max := Length(Pages);
      PageDigits := Length(IntToStr(Pdf.PageCount));
      
      // Setup output
      OutDir := EnsureOutputDir(Pdf.FileName, EditOutputDir.Text);
      BaseName := ChangeFileExt(ExtractFileName(Pdf.FileName), '');
      
      JpegImage := TJpegImage.Create;
      try
        for I := 0 to High(Pages) do
        begin
          if FCancelRequested then
            Break;
            
          Pdf.PageNumber := Pages[I];
          
          // Render page to bitmap
          Bitmap := Pdf.RenderPage(
            0, 0,
            Round(Pdf.PageWidth * Dpi / 72),
            Round(Pdf.PageHeight * Dpi / 72),
            ro0, [], clWhite
          );
          
          try
            // Save as JPEG
            FileName := Format('%s\%s_%.*d.jpg',
              [OutDir, BaseName, PageDigits, Pages[I]]);
              
            JpegImage.Assign(Bitmap);
            JpegImage.CompressionQuality := Quality;
            JpegImage.SaveToFile(FileName);
          finally
            Bitmap.Free;
          end;
          
          ProgressBar.Position := I + 1;
          Application.ProcessMessages;
        end;
      finally
        JpegImage.Free;
      end;
      
    except
      on E: Exception do
        Application.MessageBox(
          PChar('Conversion failed: ' + E.Message),
          'Error', MB_ICONERROR or MB_OK);
    end;
    
  finally
    Screen.Cursor := crDefault;
    Pdf.Active := False;
  end;
end;

理解 RenderPage

好的。 RenderPage 方法是 PDF 转换为图像的关键。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Render to a new bitmap
function TPdf.RenderPage(
  Left, Top, Width, Height: Integer;
  Rotation: TRotation = ro0;
  Options: TRenderOptions = [];
  Color: TColor = clWhite
): TBitmap;
 
// Render to an existing bitmap
procedure TPdf.RenderPage(
  Bitmap: TBitmap;
  Left, Top, Width, Height: Integer;
  Rotation: TRotation = ro0;
  Options: TRenderOptions = [];
  Color: TColor = clWhite
);
 
// Render directly to a device context (for printing)
procedure TPdf.RenderPage(
  DeviceContext: HDC;
  Left, Top, Width, Height: Integer;
  Rotation: TRotation = ro0;
  Options: TRenderOptions = []
);

渲染选项。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
type
  TRenderOption = (
    reAnnotations,       // Include annotations in output
    reLcd,               // Optimize for LCD displays
    reNoNativeText,      // Don't use system text rendering
    reGrayscale,         // Output in grayscale
    reLimitCache,        // Limit memory cache
    reHalftone,          // Better image downscaling
    rePrinting,          // Optimize for printing
    reNoSmoothText,      // Disable text anti-aliasing
    reNoSmoothImage,     // Disable image anti-aliasing
    reNoSmoothPath       // Disable path anti-aliasing
  );
 
// Example: High-quality output with annotations
Bitmap := Pdf.RenderPage(0, 0, Width, Height, ro0,
  [reAnnotations, reLcd], clWhite);
  
// Example: Fast, grayscale thumbnail
Bitmap := Pdf.RenderPage(0, 0, 200, 280, ro0,
  [reGrayscale, reNoSmoothText, reNoSmoothImage], clWhite);

DPI 和质量指南。

Use Case Recommended DPI JPEG Quality
Thumbnails 72 60-70
Screen viewing 96-150 80-85
High-quality display 200-300 85-95
Printing 300-600 90-100

解析页面范围。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
function TFormMain.ParsePageRanges(const S: string; MaxPage: Integer;
  out Pages: TIntArray): Boolean;
var
  List: TStringList;
  I, A, B, J: Integer;
  Part: string;
  DashPos: Integer;
  Used: array of Boolean;
  Count: Integer;
begin
  Result := False;
  SetLength(Pages, 0);
  
  if Trim(S) = '' then
  begin
    Result := True;
    Exit;
  end;
  
  SetLength(Used, MaxPage + 1);
  for I := 0 to High(Used) do
    Used[I] := False;
    
  List := TStringList.Create;
  try
    List.Delimiter := ',';
    List.DelimitedText := StringReplace(Trim(S), ' ', '', [rfReplaceAll]);
    
    for I := 0 to List.Count - 1 do
    begin
      Part := Trim(List[I]);
      DashPos := Pos('-', Part);
      
      if DashPos > 0 then
      begin
        // Range: "1-5"
        A := StrToIntDef(Trim(Copy(Part, 1, DashPos - 1)), 0);
        B := StrToIntDef(Trim(Copy(Part, DashPos + 1, Length(Part))), 0);
        
        if (A < 1) or (B < A) or (B > MaxPage) then
          Exit;
          
        for J := A to B do
          Used[J] := True;
      end
      else
      begin
        // Single page
        A := StrToIntDef(Part, 0);
        if (A < 1) or (A > MaxPage) then
          Exit;
        Used[A] := True;
      end;
    end;
  finally
    List.Free;
  end;
  
  // Build result array
  Count := 0;
  for I := 1 to MaxPage do
    if Used[I] then Inc(Count);
    
  SetLength(Pages, Count);
  J := 0;
  for I := 1 to MaxPage do
    if Used[I] then
    begin
      Pages[J] := I;
      Inc(J);
    end;
    
  Result := True;
end;

创建缩略图。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function CreateThumbnail(Pdf: TPdf; PageNumber: Integer;
  MaxWidth, MaxHeight: Integer): TBitmap;
var
  PageWidth, PageHeight: Double;
  Scale: Double;
  ThumbWidth, ThumbHeight: Integer;
begin
  Pdf.PageNumber := PageNumber;
  
  PageWidth := Pdf.PageWidth;
  PageHeight := Pdf.PageHeight;
  
  // Calculate scale to fit in max dimensions
  Scale := Min(MaxWidth / PageWidth, MaxHeight / PageHeight);
  
  ThumbWidth := Round(PageWidth * Scale);
  ThumbHeight := Round(PageHeight * Scale);
  
  Result := Pdf.RenderPage(0, 0, ThumbWidth, ThumbHeight,
    ro0, [reGrayscale], clWhite);
end;

用例

  • 缩略图生成。 – 为文档浏览器创建预览。
  • Web 发布。 将PDF转换为图像以用于网页显示。
  • 社交媒体。 将PDF内容以图像形式分享。
  • 归档转换。 将PDF归档转换为图像格式。
  • OCR预处理。 准备PDF文件以进行OCR处理。

结论。

PDF转换为JPG的演示版展示了如何使用PDFium VCL轻松将PDF页面转换为高质量图像。 RenderPage 该方法让您完全控制分辨率、质量和渲染选项。

无论您是构建缩略图生成器、网页发布器还是文档转换器,PDFium VCL 都提供您所需的渲染功能。

立即开始将 PDF 转换为图像。 使用 PDFium VCL 组件 今天。