مقالة تقنية

استخراج الصور من مستندات PDF باستخدام PDFium VCL في دلفي

· برمجة PDF

غالبًا ما تحتوي مستندات PDF على صور قيمة - مثل الصور والرسوم البيانية والمخططات والرسومات. استخراج الصور يوضح هذا المثال كيفية استخراج جميع الصور المضمنة من مستند PDF باستخدام PDFium VCL، وحفظها بتنسيقات مثالية بناءً على خصائصها.

نظرة عامة

يستخرج هذا المثال الصور المضمنة (الصور النقطية) من صفحات PDF ويحفظها كملفات صور منفصلة. يتضمن معاينة الصور، واكتشاف التنسيق، والاستخراج الدفعي مع تتبع التقدم.

الميزات الرئيسية

  • استخراج جميع الصور - استخراج كل صورة مضمنة من ملف PDF.
  • تحديد نطاق الصفحات - الاستخراج من صفحات محددة فقط.
  • اكتشاف تنسيق ذكي. – اختر تلقائيًا بين تنسيقات JPEG و PNG و BMP بناءً على خصائص الصورة.
  • معاينة الصور. – قم بمعاينة الصور المستخرجة قبل الحفظ.
  • معلومات تفصيلية. – عرض الأبعاد والتنسيق وحجم الملف.
  • معالجة مجمعة. – استخراج صور متعددة مع تتبع التقدم.

متطلبات ملف PDFium DLL.

قبل تشغيل أي تطبيق PDFium VCL، تأكد من تثبيت ملفات PDFium DLL:

  • pdfium32.dll / pdfium64.dll – الإصدارات القياسية (حوالي 5-6 ميجابايت).
  • pdfium32v8.dll / pdfium64v8.dll – مع محرك JavaScript V8 (حوالي 23-27 ميجابايت).

التثبيت: تشغيل PDFiumVCL\DLLs\CopyDlls.bat بصلاحيات المسؤول لنسخ ملفات DLL تلقائيًا إلى مجلدات نظام Windows.

استخراج أساسي للصور.

الوصول إلى الصور المضمنة من خلال الخصائص: Bitmap و BitmapCount .

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
procedure ExtractImagesSimple;
var
  Pdf: TPdf;
  I, J: Integer;
  Bitmap: TBitmap;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'document.pdf';
    Pdf.Active := True;
    
    // Loop through all pages
    for I := 1 to Pdf.PageCount do
    begin
      Pdf.PageNumber := I;
      
      // Loop through all images on this page
      for J := 0 to Pdf.BitmapCount - 1 do
      begin
        Bitmap := Pdf.Bitmap[J];
        try
          // Save as BMP
          Bitmap.SaveToFile(Format('Page%d_Image%d.bmp', [I, J + 1]));
        finally
          Bitmap.Free;
        end;
      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
procedure TFormMain.ButtonExtractClick(Sender: TObject);
var
  I, J, StartPage, EndPage: Integer;
  Bitmap: TBitmap;
  FullFileName, DetectedFormat, ImageExtension: string;
  ImageInfo: TImageInfo;
begin
  FCancelled := False;
  FProcessedImages := 0;
  FTotalImages := 0;
  
  ClearExtractedImages;
  EnableControls(False);
  
  try
    Pdf.FileName := EditPdfFile.Text;
    Pdf.PageNumber := 0;
    Pdf.Active := True;
    
    ParsePageRange(EditPageRange.Text, StartPage, EndPage);
    if EndPage = -1 then
      EndPage := Pdf.PageCount;
      
    // Calculate total images for progress
    for I := StartPage to EndPage do
    begin
      Pdf.PageNumber := I;
      FTotalImages := FTotalImages + Pdf.BitmapCount;
    end;
    
    ProgressBar.Max := FTotalImages;
    
    // Extract images
    for I := StartPage to EndPage do
    begin
      if FCancelled then
        Break;
        
      Pdf.PageNumber := I;
      
      for J := 0 to Pdf.BitmapCount - 1 do
      begin
        if FCancelled then
          Break;
          
        Bitmap := Pdf.Bitmap[J];
        if Assigned(Bitmap) then
        begin
          try
            // Detect optimal format
            DetectedFormat := DetectImageFormat(Bitmap);
            ImageExtension := GetExtensionForFormat(DetectedFormat);
            
            FullFileName := Format('%s\Page%d_Image%d%s',
              [FCurrentOutputDir, I, J + 1, ImageExtension]);
              
            SaveBitmapInOptimalFormat(Bitmap, FullFileName);
            
            // Store image info for preview
            ImageInfo.FileName := FullFileName;
            ImageInfo.PageNumber := I;
            ImageInfo.ImageIndex := J + 1;
            ImageInfo.Width := Bitmap.Width;
            ImageInfo.Height := Bitmap.Height;
            ImageInfo.Format := DetectedFormat;
            ImageInfo.Bitmap := TBitmap.Create;
            ImageInfo.Bitmap.Assign(Bitmap);
            
            AddImageInfo(ImageInfo);
            
            Inc(FProcessedImages);
            ProgressBar.Position := FProcessedImages;
            
          finally
            Bitmap.Free;
          end;
        end;
      end;
    end;
    
    UpdateImageList;
    
  finally
    Pdf.Active := False;
    EnableControls(True);
  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
function TFormMain.DetectImageFormat(ABitmap: TBitmap): string;
begin
  // Check if image has transparency (alpha channel)
  if ABitmap.PixelFormat = pf32bit then
  begin
    // PNG for transparency support
    Result := 'PNG';
  end
  // Check if it's likely a photographic image
  else if (ABitmap.Width * ABitmap.Height > 100000) and
          (ABitmap.PixelFormat in [pf24bit, pf32bit]) then
  begin
    // Large, complex image - use JPEG for smaller file size
    Result := 'JPEG';
  end
  else
  begin
    // Small or simple image - preserve quality with BMP
    Result := 'BMP';
  end;
end;
 
function TFormMain.GetExtensionForFormat(const AFormat: string): string;
begin
  case UpperCase(AFormat)[1] of
    'J': Result := '.jpg';
    'P': Result := '.png';
    'B': Result := '.bmp';
  else
    Result := '.bmp';
  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
procedure TFormMain.SaveBitmapInOptimalFormat(ABitmap: TBitmap;
  const AFileName: string);
var
  JpegImg: TJPEGImage;
  FileExt: string;
begin
  FileExt := UpperCase(ExtractFileExt(AFileName));
  
  if FileExt = '.JPG' then
  begin
    // Save as JPEG with good quality
    JpegImg := TJPEGImage.Create;
    try
      JpegImg.Assign(ABitmap);
      JpegImg.CompressionQuality := 85; // Good quality/size balance
      JpegImg.SaveToFile(AFileName);
    finally
      JpegImg.Free;
    end;
  end
  else if FileExt = '.PNG' then
  begin
    // PNG would require additional library
    // Fall back to BMP for compatibility
    ABitmap.SaveToFile(ChangeFileExt(AFileName, '.bmp'));
  end
  else
  begin
    // BMP - lossless quality
    ABitmap.SaveToFile(AFileName);
  end;
end;

استخدام TPdfImage للبيانات الأولية للصور.

للحالات المتقدمة، الوصول إلى البيانات الأولية للصور:

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
procedure ProcessRawImageData;
var
  Pdf: TPdf;
  I: Integer;
  PdfImage: TPdfImage;
begin
  Pdf := TPdf.Create(nil);
  try
    Pdf.FileName := 'document.pdf';
    Pdf.Active := True;
    Pdf.PageNumber := 1;
    
    for I := 0 to Pdf.ImageCount - 1 do
    begin
      PdfImage := Pdf.Image[I];
      
      // Access raw image properties
      ShowMessage(Format('Image %d: %d x %d, %d bytes',
        [I, PdfImage.Width, PdfImage.Height, Length(PdfImage.Data)]));
        
      // PdfImage.Data contains raw pixel data
    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
procedure TFormMain.UpdatePreview(Index: Integer);
var
  Info: TImageInfo;
begin
  if (Index >= 0) and (Index < Length(FExtractedImages)) then
  begin
    Info := FExtractedImages[Index];
    
    // Update preview
    if Assigned(Info.Bitmap) then
      ImagePreview.Picture.Assign(Info.Bitmap);
      
    // Update info display
    MemoInfo.Lines.Clear;
    MemoInfo.Lines.Add('File: ' + ExtractFileName(Info.FileName));
    MemoInfo.Lines.Add('Page: ' + IntToStr(Info.PageNumber));
    MemoInfo.Lines.Add('Dimensions: ' + IntToStr(Info.Width) +
                       ' x ' + IntToStr(Info.Height));
    MemoInfo.Lines.Add('Format: ' + Info.Format);
    if Info.Size > 0 then
      MemoInfo.Lines.Add('Size: ' + FormatFloat('#,##0', Info.Size) + ' bytes');
  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
procedure TFormMain.ParsePageRange(const ARange: string;
  var AStartPage, AEndPage: Integer);
var
  RangeStr: string;
  DashPos: Integer;
begin
  RangeStr := Trim(ARange);
  AStartPage := 1;
  AEndPage := -1; // -1 means extract to end
  
  if (RangeStr = '') or (UpperCase(RangeStr) = 'ALL') then
    Exit;
    
  DashPos := Pos('-', RangeStr);
  if DashPos > 0 then
  begin
    // Range format: start-end
    AStartPage := StrToIntDef(Trim(Copy(RangeStr, 1, DashPos - 1)), 1);
    AEndPage := StrToIntDef(Trim(Copy(RangeStr, DashPos + 1, Length(RangeStr))), -1);
  end
  else
  begin
    // Single page
    AStartPage := StrToIntDef(RangeStr, 1);
    AEndPage := AStartPage;
  end;
end;

فتح مجلد الصور المستخرجة.

1
2
3
4
5
6
7
procedure TFormMain.ButtonOpenFolderClick(Sender: TObject);
begin
  if DirectoryExists(FCurrentOutputDir) then
    ShellExecute(Handle, 'open', PChar(FCurrentOutputDir), nil, nil, SW_SHOWNORMAL)
  else
    ShowMessage('Output directory does not exist.');
end;

حالات الاستخدام.

  • استخراج الأصول الرقمية. - استخراج الصور والرسومات من المواد التسويقية.
  • تحويل المستندات. – قم بإعداد الصور لتنسيقات الويب أو غيرها.
  • معالجة الأرشيف. – استخراج الصور من أرشيفات المستندات الممسوحة ضوئيًا.
  • تحليل المحتوى. – استخراج الصور لتعلم الآلة أو التحليل.

الخلاصة.

يوضح نموذج "استخراج الصور" مدى سهولة استخراج الصور المضمنة من مستندات PDF باستخدام PDFium VCL. يتعامل المكون مع تحليل PDF المعقد بينما تركز على كيفية استخدام الصور المستخرجة في تطبيقك.

عند دمجه مع الكشف الذكي عن التنسيق، يمكنك إنشاء أدوات استخراج صور احترافية تنتج مخرجات محسّنة لأي حالة استخدام.

استكشف. مكون PDFium. على loslab.com وقم بفتح المحتوى الموجود في مستندات PDF الخاصة بك.