PDF ÑÑÑ
ÑанÑва изобÑажениÑÑа каÑо пÑÑвоклаÑни обекÑи в ÑвоиÑе поÑоÑи Ð¾Ñ ÑÑдÑÑжание. ÐогаÑо ÑÑÑаниÑа пÑепÑаÑа кÑм Ñнимка, ÑканиÑан докÑÐ¼ÐµÐ½Ñ Ð¸Ð»Ð¸ диагÑама, данниÑе за пикÑелиÑе Ñе намиÑÐ°Ñ Ð² XObject ÑеÑник паÑалелно Ñ Ð³ÐµÐ¾Ð¼ÐµÑÑиÑÑа на ÑÑÑаниÑаÑа. PDFium VCL пÑедоÑÑÐ°Ð²Ñ Ð´Ð¾ÑÑÑп до ÑÑÑ
ÑÑез две ÑвойÑÑва на TPdf: BitmapCount, коеÑо вÑÑÑа бÑÐ¾Ñ Ð½Ð° вгÑадениÑе ÑаÑÑеÑни изобÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð½Ð° ÑекÑÑаÑа ÑÑÑаниÑа, и Bitmap[Index], коеÑо декодиÑа едно Ð¾Ñ ÑÑÑ
в TBitmap, койÑо вие пÑиÑежаваÑе и ÑÑÑбва да оÑвободиÑе. Това е ÑелиÑÑ Ð¼Ð¾Ð´ÐµÐ» на извлиÑане. ЦикÑлÑÑ Ñе ÑÑÑÑои Ð¾Ñ ÑеÑиÑи Ñеда; Ñова, коеÑо изиÑква пÑеÑенка, е заобикалÑÑаÑа го аÑÑ
иÑекÑÑÑа.
ÐÑваÑÑне на докÑменÑа
ÐÑÑвоÑо неÑо, коеÑо ÑÑÑбва да знаеÑе за TPdf, е Ñе Active := True никога не пÑедизвиква изклÑÑение. ÐеÑÑпеÑно заÑеждане, гÑеÑна паÑола, повÑеден Ñайл â?вÑиÑки Ñези гÑеÑки Ñе ÑлавÑÑ Ð²ÑÑÑеÑно и компоненÑÑÑ Ð¿ÑоÑÑо оÑÑава неакÑивен. ТÑÑбва Ñами да пÑовеÑиÑе Ñлага Ñлед пÑиÑвоÑванеÑо, в пÑоÑивен ÑлÑÑай Ñе пÑеминеÑе кÑм ÑикÑла за ÑÑÑаниÑи Ñ PageCount, вÑÑÑÐ°Ñ Ð½Ñла, и Ñе Ñе ÑÑдиÑе заÑо ниÑо не Ñе извлиÑа.
var
Pdf: TPdf;
begin
Pdf := TPdf.Create(nil);
try
Pdf.FileName := 'report.pdf';
Pdf.Active := True;
if not Pdf.Active then
begin
Writeln('Failed to open: ', Pdf.FileName);
Exit;
end;
Writeln(Pdf.PageCount, ' pages');
// proceed to extraction
finally
Pdf.Free;
end;
end;
ÐаÑиÑениÑе Ñ Ð¿Ð°Ñола Ñайлове ÑÐ»ÐµÐ´Ð²Ð°Ñ ÑÑÑÐ¸Ñ Ð¼Ð¾Ð´ÐµÐ»: задайÑе ÑÑойноÑÑ Ð½Ð° Pdf.Password пÑеди да пÑомениÑе Active := True. Ðко паÑолаÑа е гÑеÑна, Active оÑÑава False и нÑма изклÑÑение, коеÑо да пÑиÑ
ванеÑе. ÐÑи инÑÑÑÑÐ¼ÐµÐ½Ñ Ð·Ð° пакеÑна обÑабоÑка на ÑÑоÑиÑи Ñайлове Ñова ÑиÑ
о поведение вÑÑÑноÑÑ Ðµ полезно: наÑÑÑпваÑе неÑÑпеÑниÑе опиÑи в ÑпиÑÑк, вмеÑÑо да ÑазгÑÑÑаÑе ÑÑека на извикваниÑÑа (call stack) за вÑеки оÑделен Ñайл.
ÐÐ±Ñ Ð¾Ð¶Ð´Ð°Ð½Ðµ на ÑÑÑаниÑи и извлиÑане на ÑаÑÑеÑни изобÑажениÑ
СвойÑÑвоÑо BitmapCount Ñе оÑнаÑÑ Ð·Ð° конкÑеÑна ÑÑÑаниÑа, Ñака Ñе ÑÑÑбва да зададеÑе ÑÑойноÑÑ Ð½Ð° Pdf.PageNumber пÑеди да го пÑоÑеÑеÑе. ÐомеÑаÑа на ÑÑÑаниÑиÑе запоÑÐ²Ð°Ñ Ð¾Ñ 1; ÑÑойноÑÑÑа по подÑазбиÑане е 0, коеÑо ознаÑава, Ñе нÑма заÑедена ÑÑÑаниÑа. СвойÑÑвоÑо Bitmap[Index] запоÑва Ð¾Ñ 0 и вÑÑÑа Ð¾Ð±ÐµÐºÑ TBitmap, ÑпÑавлÑван Ð¾Ñ Ð¸Ð·Ð²Ð¸ÐºÐ²Ð°ÑаÑа ÑÑÑана. ТÑÑбва да го оÑвободиÑе. Ðко пÑенебÑегнеÑе оÑвобождаванеÑо в дÑлÑг ÑикÑл вÑÑÑ
Ñ Ð³Ð¾Ð»Ñм докÑменÑ, памеÑÑа Ñе Ñе запÑлни бÑÑзо, ÑÑй каÑо вÑÑко ÑаÑÑеÑно изобÑажение може да ÑÑдÑÑжа нÑколко мегабайÑа необÑабоÑени пикÑелни данни пÑеди вÑÑкаква компÑеÑиÑ.
procedure ExtractAllImages(Pdf: TPdf; const OutputDir: string);
var
Page, Idx: Integer;
Bmp: TBitmap;
OutPath: string;
begin
for Page := 1 to Pdf.PageCount do
begin
Pdf.PageNumber := Page;
for Idx := 0 to Pdf.BitmapCount - 1 do
begin
Bmp := Pdf.Bitmap[Idx];
if not Assigned(Bmp) then
Continue;
try
OutPath := Format('%s\p%d_img%d.bmp', [OutputDir, Page, Idx + 1]);
Bmp.SaveToFile(OutPath);
finally
Bmp.Free;
end;
end;
end;
end;
ÐаÑиÑнаÑа пÑовеÑка Assigned е важна. ÐалÑк бÑой PDF генеÑаÑоÑи запиÑÐ²Ð°Ñ XObjects на изобÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ñ Ð½Ñлеви ÑазмеÑи в пикÑели или Ñ Ð¿Ð¾ дÑÑг наÑин деÑоÑмиÑани данни; в Ñези ÑлÑÑаи компоненÑÑÑ Ð²ÑÑÑа nil вмеÑÑо пÑазно изобÑажение. ТÑеÑиÑанеÑо на вÑÑнаÑа ÑÑойноÑÑ nil каÑо гÑеÑка и ÑпиÑанеÑо на извлиÑанеÑо е гÑеÑен ÑеÑлекÑ: пÑопÑÑнеÑе го, запиÑеÑе в лога ÑÑÑаниÑаÑа и индекÑа, ако имаÑе нÑжда Ð¾Ñ Ð¾Ð´Ð¸Ñна Ñледа, и пÑодÑлжеÑе. ÐÑÑаналаÑа ÑаÑÑ Ð¾Ñ ÑÑÑаниÑаÑа вÑе оÑе може да ÑÑдÑÑжа валидни изобÑажениÑ.
ÐбÑÑнеÑе внимание, Ñе вÑнÑниÑÑ ÑикÑл задава Pdf.PageNumber пÑи вÑÑка иÑеÑаÑиÑ. Това пÑиÑвоÑване заÑежда ÑÑÑаниÑаÑа вÑв вÑÑÑеÑноÑо ÑÑÑÑоÑние на компоненÑа и пÑави BitmapCount ÑмиÑлено ÑвойÑÑво. ÐÑопÑÑнеÑе го и Ñе ÑеÑеÑе бÑÐ¾Ñ Ð½Ð° изобÑажениÑÑа на една и ÑÑÑа ÑÑÑаниÑа многокÑаÑно. Този Ñаблон изглежда излиÑен пÑи пиÑане, но ÑакÑв е дизайнÑÑ Ð½Ð° API: ÑÑÑаниÑаÑа е кÑÑÑоÑ, а не колекÑиÑ.
ÐÐ·Ð±Ð¾Ñ Ð½Ð° Ð¸Ð·Ñ Ð¾Ð´ÐµÐ½ ÑоÑмаÑ
ФоÑмаÑÑÑ BMP е без загÑба на каÑеÑÑво (lossless) и е винаги налиÑен без допÑлниÑелни модÑли, коеÑо го пÑави надежден Ð¸Ð·Ð±Ð¾Ñ Ð¿Ð¾ подÑазбиÑане, когаÑо вÑе оÑе не знаеÑе какво ÑÑдÑÑжа изобÑажениеÑо. ÐогаÑо ÑазмеÑÑÑ Ð½Ð° Ñайла е Ð¾Ñ Ð·Ð½Ð°Ñение, пикÑелниÑÑ ÑоÑÐ¼Ð°Ñ Ð½Ð° вÑÑнаÑÐ¸Ñ TBitmap ви подÑказва кой кодек е подÑ
одÑÑ. 32-биÑовиÑÑ bitmap ÑÑдÑÑжа алÑа канал; PNG го запазва без загÑба на каÑеÑÑво. ÐолÑмо 24-биÑово изобÑажение Ñ Ð¿ÑеливаÑи Ñонове е подÑ
одÑÑ ÐºÐ°Ð½Ð´Ð¸Ð´Ð°Ñ Ð·Ð° JPEG. Ðа по-малки изобÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ Ñакива, наÑиÑÑвани Ñ Ð¾Ð³ÑаниÑена палиÑÑа, обикновено е по-добÑе да Ñе оÑÑавÑÑ ÐºÐ°Ñо BMP, вмеÑÑо да Ñе конвеÑÑиÑÐ°Ñ Ð² JPEG, койÑо Ð´Ð¾Ð±Ð°Ð²Ñ Ð°ÑÑеÑакÑи (blocking artifacts) пÑи ниÑко каÑеÑÑво и ÑпеÑÑÑва малко пÑоÑÑÑанÑÑво пÑи виÑоко.
procedure SaveBitmap(Bmp: TBitmap; const FileName: string);
var
Jpg: TJPEGImage;
begin
case UpperCase(ExtractFileExt(FileName)) of
'.JPG', '.JPEG':
begin
Jpg := TJPEGImage.Create;
try
Jpg.Assign(Bmp);
Jpg.CompressionQuality := 85;
Jpg.SaveToFile(FileName);
finally
Jpg.Free;
end;
end;
else
Bmp.SaveToFile(FileName); // BMP: lossless, no extra units
end;
end;
Ðа пÑакÑика избоÑÑÑ Ð½Ð° ÑоÑÐ¼Ð°Ñ Ñе опÑÐµÐ´ÐµÐ»Ñ Ð¾Ñ Bmp.PixelFormat и ÑазмеÑиÑе на изобÑажениеÑо. Ðко PixelFormat = pf32bit, имаÑе нÑжда Ð¾Ñ ÑоÑмаÑ, койÑо поддÑÑжа алÑа канал; PNG е оÑевидниÑÑ Ð¸Ð·Ð±Ð¾Ñ, вÑпÑеки Ñе изиÑква модÑла PNGImage в по-ÑÑаÑиÑе веÑÑии на Delphi. Ðа 24-биÑови изобÑажениÑ, по-ÑиÑоки Ð¾Ñ Ð¿ÑиблизиÑелно 300 пикÑела, JPEG Ñ ÐºÐ°ÑеÑÑво 85 пÑедлага ÑÑикÑаÑно намаление на ÑазмеÑа ÑпÑÑмо BMP без забележима загÑба в каÑеÑÑвоÑо пÑи повеÑеÑо Ñнимки. Ðод Ñози пÑаг BMP е ÑÑпоÑÑавим по ÑÐ°Ð·Ð¼ÐµÑ Ð¸ напÑлно ÑпеÑÑÑва нÑждаÑа Ð¾Ñ Ð²Ð·ÐµÐ¼Ð°Ð½Ðµ на ÑеÑÐµÐ½Ð¸Ñ Ð·Ð° каÑеÑÑвоÑо.
Ðакво оÑÑиÑа и какво не оÑÑиÑа BitmapCount
PDF ÑазгÑаниÑава XObjects на изобÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¸ векÑоÑна гÑаÑика, изÑеÑÑана Ñ Ð¾Ð¿ÐµÑаÑоÑи за пÑÑиÑа. СÑÑаниÑа, коÑÑо изглежда визÑално Ñложна, може да вÑÑне BitmapCount ÑÑÑ ÑÑойноÑÑ Ð½Ñла, ако вÑеки ÐµÐ»ÐµÐ¼ÐµÐ½Ñ Ðµ векÑоÑен. СканиÑаниÑе ÑÑÑаниÑи поÑÑи винаги вÑÑÑÐ°Ñ ÑоÑно едно изобÑажение: ÑкенеÑÑÑ Ð·Ð°Ð¿Ð¸Ñва ÑÑлоÑо ÑканиÑане каÑо един XObject на изобÑажение на ÑÑла ÑÑÑаниÑа пÑи ÑезолÑÑиÑÑа, зададена на ÑкенеÑа. СÑÑаниÑи, ÑÑÑеÑаваÑи ÑекÑÑ Ñ Ð²Ð³Ñадени Ñнимки, вÑÑÑÐ°Ñ Ð¿Ð¾ един Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° вÑÑка Ñнимка. ÐекоÑаÑивниÑе линии, ÑенÑеÑÑиÑе Ñонове и ÑамкиÑе на ÑаблиÑи обикновено изобÑо не Ñе поÑвÑÐ²Ð°Ñ Ð² бÑÐ¾Ñ Ð½Ð° ÑаÑÑеÑниÑе изобÑажениÑ.
ÐÑоÑÑ ÑÑÑо Ñака не вклÑÑва вгÑадени (inline) изобÑÐ°Ð¶ÐµÐ½Ð¸Ñ â?ÑÑдко използвана PDF ÑÑÑÑкÑÑÑа, пÑи коÑÑо данниÑе за изобÑажениеÑо Ñа вгÑадени диÑекÑно в поÑока Ð¾Ñ ÑÑдÑÑжание на ÑÑÑаниÑаÑа, а не каÑо именÑван XObject. Те оÑÑÐ°Ð²Ð°Ñ Ð¸Ð·Ð²Ñн вÑзможноÑÑиÑе на Ñози API; Ñе Ñе ÑÑеÑÐ°Ñ Ñолкова ÑÑдко в Ñеални докÑменÑи, Ñе повеÑеÑо инÑÑÑÑменÑи за извлиÑане пÑоÑÑо не ги поддÑÑжаÑ.
ÐеÑайл, койÑо Ñи ÑÑÑÑва да помниÑе: ÑÑойноÑÑÑа на BitmapCount, коÑÑо ÑеÑеÑе, Ñе оÑнаÑÑ Ð·Ð° ÑекÑÑаÑа ÑÑÑаниÑа кÑм моменÑа на поÑледноÑо задаване на PageNumber. Ðко ваÑиÑÑ ÐºÐ¾Ð´ Ñе ÑазклонÑва или извиква ÑÑнкÑиÑ, коÑÑо пÑÐ¾Ð¼ÐµÐ½Ñ PageNumber Ð¼ÐµÐ¶Ð´Ñ Ð¿ÑебÑоÑванеÑо и извлиÑанеÑо, може да пÑоÑеÑеÑе по-малко изобÑÐ°Ð¶ÐµÐ½Ð¸Ñ Ð¾Ñ Ð¿Ð»Ð°Ð½Ð¸ÑаниÑе или да излезеÑе извÑн гÑаниÑиÑе на индекÑа. ÐÑÑжÑе ÑеÑенеÑо на бÑÐ¾Ñ Ð¸ ÑикÑла Bitmap[] на една и ÑÑÑа ÑÑÑаниÑа, без да пÑоменÑÑе PageNumber междÑвÑеменно.
Ðзползване на TPdfView вÑв VCL пÑиложение
ÐÐ°Ð¼ÐµÑ Ð¸ пÑоизводиÑелноÑÑ Ð¿Ñи пакеÑна обÑабоÑка
ÐÑи големи аÑÑ
иви най-важноÑо неÑо, коеÑо ÑÑÑбва да ÑледиÑе, е бÑджеÑÑÑ Ð½Ð° памеÑÑа. ÐÑÑко извикване на Bitmap[] Ð·Ð°Ð´ÐµÐ»Ñ Ð½Ð¾Ð² TBitmap в кÑпÑинаÑа (heap), коеÑо пÑи ÑканиÑана ÑÑÑаниÑа Ñ 300 DPI е леÑно 25 MB необÑабоÑени пикÑелни данни пÑеди вÑÑкакво кодиÑане. Ðко обÑабоÑваÑе ÑÑÑаниÑиÑе в заÑвоÑен ÑикÑл без оÑвобождаване на памеÑÑа Ð¼ÐµÐ¶Ð´Ñ Ð¸ÑеÑаÑииÑе, обемÑÑ Ð½Ð° заеÑаÑа Ð¿Ð°Ð¼ÐµÑ Ñе наÑаÑÑва линейно Ñ Ð±ÑÐ¾Ñ Ð½Ð° изобÑажениÑÑа. ÐÑавилниÑÑ Ð¿Ð¾Ð´Ñ
од винаги е: извлиÑаÑе един bitmap, извÑÑÑваÑе необÑ
одимиÑе опеÑаÑии, оÑвобождаваÑе го и извлиÑаÑе ÑледваÑиÑ. Ðко ÑÑÑбва да пазиÑе пÑепÑаÑки кÑм нÑколко ÑаÑÑеÑни изобÑÐ°Ð¶ÐµÐ½Ð¸Ñ ÐµÐ´Ð½Ð¾Ð²Ñеменно за ÑÑавнение, пÑÑво ги пÑебÑойÑе Ñ BitmapCount, ÑазпÑеделеÑе ÑÑоÑвеÑно конÑейнеÑа Ñи и Ñлед Ñова оÑвобождавайÑе вÑÑко едно веднага Ñом пÑиклÑÑиÑе Ñ Ð½ÐµÐ³Ð¾, вмеÑÑо да оÑлагаÑе поÑиÑÑванеÑо за кÑÐ°Ñ Ð½Ð° докÑменÑа. ÐÑи докÑÐ¼ÐµÐ½Ñ Ð¾Ñ 500 ÑканиÑани ÑÑÑаниÑи Ñази Ñазлика може да бÑде Ð¼ÐµÐ¶Ð´Ñ 25 MB и 12 GB пикова заеÑоÑÑ Ð½Ð° памеÑÑа (peak RSS).
ÐомпоненÑÑÑ TPdfView пÑедлага ÑÑÑиÑе ÑвойÑÑва BitmapCount и Bitmap[], но ÑÑÑаниÑаÑа, Ð¾Ñ ÐºÐ¾ÑÑо ÑеÑе, е ÑекÑÑо показанаÑа ÑÑÑаниÑа на изгледа, а не TPdf.PageNumber. ÐваÑа ÑказаÑÐµÐ»Ñ Ð·Ð° ÑÑÑаниÑи Ñа незавиÑими; пÑомÑнаÑа на ÐµÐ´Ð¸Ð½Ð¸Ñ Ð½Ðµ пÑемеÑÑва дÑÑгиÑ. ÐÑв VCL пÑиложение Ñ Ð¿Ñеглед на живо можеÑе да извикаÑе Pdf.PageNumber := N, за да ÑпÑавлÑваÑе извлиÑанеÑо ÑÑез TPdf, докаÑо изгледÑÑ Ð¾ÑÑава на ÑÑÑаниÑаÑа, коÑÑо поÑÑебиÑелÑÑ Ð¿Ð¾Ñледно е пÑелиÑÑил. Това Ñазделение е ÑмиÑлено и запазва ÑÑÑÑоÑниеÑо на диÑÐ¿Ð»ÐµÑ Ð½Ð° ÑеÑеÑа ÑиÑÑо, докаÑо извлиÑанеÑо Ñе изпÑлнÑва вÑв Ñонов Ñежим.
СвойÑÑваÑа BitmapCount и Bitmap[], показани ÑÑк, Ñа ÑаÑÑ Ð¾Ñ ÐºÐ¾Ð¼Ð¿Ð¾Ð½ÐµÐ½Ñа PDFium VCL Component за Delphi и C++Builder.