Yerel Delphi PDF bileşeni HotPDF, CCITTFaxDecode görsellerini T.4/T.6 sıkıştırılmamış mod uzantısı ve DamagedRowsBeforeError tarafından yönlendirilen hasarlı satır kurtarması için tam destekle çözer. Sıkıştırılmamış mod yalnızca 111 ile biten uzantı koduyla açılır ve hasarlı satırlar yalnızca EndOfLine bayrağı ayarlı Group 3 verisi için onarılır. Geri kalan her şey çarpık bir sayfa üretmek yerine temiz biçimde başarısız olur
Faks kodlamalı görseller, PDF görsel çözmenin uzun kuyruğudur. Karşılaştığınız CCITT akışlarının çoğu, yalnızca düz Group 4 üreten bir tarayıcı sürücüsünden ya da belge yakalama hattından gelir ve yaygın durumu halleden bir çözücü, ona fırlattığınız her testi geçer. Sonra on beş yıllık bir faks sunucusundan gelen bir arşiv ulaşır, bir sayfa 400. satırdan aşağı doğru çapraz gürültü olarak render olur ve ITU-T tavsiyelerinin kimsenin uygulmadığı iki parçasının, o dosyanın tam olarak kullandığı iki parça olduğunu fark edersiniz. Bu yazı o iki parçayı HotPDF'in onları ele aldığı biçimle ve bir çözücünün doğru görünürken yanlış gidebileceği yerlerle gezinir
Hangi CCITTFaxDecode parametreleri bit akışını gerçekten değiştirir?
DecodeParms sözlüğündeki dört giriş, çözücünün bit akışını nasıl çerçevelediğini değiştirir: K, EndOfLine, EncodedByteAlign ve DamagedRowsBeforeError. Bunları ISO 32000-1 §7.4.6 (Tablo 11) tanımlar ve herhangi birini yanlış yapmak, ilk uyuşmazlıktan sonraki her satırı kaydırır. BlackIs1, Columns, Rows ve EndOfBlock de önemlidir; ama bunlar bir satır sınırının nasıl bulunacağını değil, kutupluluğu, geometriyi ve çözmenin nerede duracağını etkiler
Kkodlama şemasını seçer: negatif saf iki boyutlu Group 4 (T.6) demektir, sıfır tek boyutlu Modified Huffman (Group 3 1D) demektir, pozitif ise karışık Group 3 2D demektir; burada her EOL'den sonraki bir tag biti, sonraki satırın 1D mi 2D mi olduğunu söylerEndOfLine, her Group 3 satırından önce bir EOL kodu geldiğini söyler: on bir sıfır bit ve ardından bir birEncodedByteAlign, kodlanmış her satırın bir bayt sınırında başladığını söyler; böylece çözücü okumadan önce dolgu bitlerini atmak zorundadırDamagedRowsBeforeError, çözücünün vazgeçmeden önce kaç bozuk satırı tolere edebileceğidir ve varsayılanı 0'dır
HotPDF, THotPDF.ExtractLoadedImage ya da THotPDF.DecodeLoadedImageStream çağırdığınızda bunların hepsini görsel sözlüğünden okur. Bilinmesinde fayda olan kasıtlı bir sapma var: Columns eksik olduğunda HotPDF, şartnamedeki 1728 varsayılanı yerine görselin Width değerine döner ve Rows eksik olduğunda Height kullanır. 2480 piksellik bir A4 taramasında Columns atlayan bir üretici yanlış yapar; ama bu o kadar yaygındır ki görsel geometrisine güvenmek, harfiyen varsayımın çöp üreteceği yerde kullanılabilir bir sayfa verir
000000 neden bloğun sonu gibi ele alınamaz?
İki boyutlu satırlarda baştaki altı sıfır bit belirsizdir ve bunları EOFB'nin başlangıcı gibi okuyan bir çözücü, geçerli bir sıkıştırılmamış mod girişini görselin sonu gibi yanlış okur. Group 4'te satırlar arasında EOL yoktur; sıfır ağırlıklı tek kodlar, arka arkaya iki EOL olan EOFB ile ITU-T T.4 ve T.6'dan gelen uzantı kodlarıdır. Her ikisi 000000 ile başlar ve yedinci bit, ayrıldıkları yerdir
HotPDF CCITT çözücüsü öneki bit bit çözer. 1 olan yedinci bit, sonraki üç bitin bir uzantı kodu olduğu anlamına gelir; tam desen 0000001xxx biçimindedir. Yalnızca xxx = 111 sıkıştırılmamış moda girer; diğer her uzantı değeri bozuk sayılır, çünkü bir PDF faks filtresinin diğerlerine ihtiyacı yoktur. 0 olan yedinci bit yalnızca bir EOL'nin devamı olabilir; bu yüzden çözücü ardından dört sıfır bit daha ve kapanış olarak bir 1 ister, toplamda on bir sıfır ve bir bir, EOFB bildirmeden önce. Daha kısa ya da daha uzun her şey bir hatadır, affedici bir görsel sonu değil
Afedici sürüm cazip görünür, çünkü bozuk dosyaların bütün bir sınıfını sağlam gösterir: çözme erken durur ve siz istisnasız kısa bir görsel alırsınız. O aynı zamanda meşru faksları, sıkıştırılmamış verinin ilk uzantısında kesen tam olarak budur; taranmış bir formda bu genellikle yoğun bir imza ya da bir kaşedir. HotPDF katı okumayı seçer; böylece kısa bir görsel, kodlayıcının gerçekten orada bittiği anlamına gelir
Sıkıştırılmamış mod pikselleri nasıl kodlar?
Sıkıştırılmamış mod, çalışma uzunluğu kodlamasını (run-length) harfî piksel desenleriyle değiştirir; her kod sözcüğü en fazla beş piksel taşır ve bir çıkış kodu geri dönene kadar böyle sürer. Tek boyutlu satırlar 12 bitlik 000000001111 koduyla içine girer; iki boyutlu satırlar yukarıda anlatılan 10 bitlik 0000001111 uzantısını kullanır. Kodlayıcılar, bir ya da iki piksellik run uzunluklarının piksellerin kendisinden pahalıya geleceği halftone benzeri bölgeler için bu moda geçer
Modun içinde kod sözcükleri baştaki sıfırlarına göre sayılır. Sıfırdan dörde kadar sıfır ve ardından bir 1, o kadar beyaz piksel ve sonra bir siyah piksel demektir. Beş sıfır ve ardından bir 1, yalnızca beş beyaz piksel demektir. Altı ile on arası sıfır ve ardından bir 1 çıkış kodlarıdır: altıyı aşan sıfırlar dört beyaz piksele kadar daha üretir ve çıkış kodundan sonraki tek bit, tag biti, sıradan run kodlaması devam ettiğinde sonraki run'ın rengini belirler
{ Sıkıştırılmamış mod kod sözcükleri (ITU-T T.4 / T.6)
W = beyaz piksel, B = siyah piksel, T = tag biti
1 B
01 W B
001 W W B
0001 W W W B
00001 W W W W B
000001 W W W W W
0000001T çıkış, sonra T rengiyle run'lara devam
00000001T W, çıkış
000000001T W W, çıkış
0000000001T W W W, çıkış
00000000001T W W W W, çıkış
ondan fazla sıfır: bozuk }
Tag bit ince kısımdır. Run kodlaması durum tutar: bir 1D satır beyaz ve siyah run'ları sırayla değiştirir ve bir 2D satır, geçerli değişen elemanın a0 rengini izler. Çıkış kodundan sonra çözücü, tag'in hangi rengi adlandırdığıyla devam etmek zorundadır; bu son harfî pikselle uyuşabilir de uyuşmayabilir de. HotPDF çözücüsü, tag izlediği renkten farklıysa geçerli konumda bir renk değişimi kaydeder; böylece sonraki run doğru renkten başlar. Tag'i yok sayarsanız satırın geri kalanı renk ters çevrilmiş çıkar ve 2D modda sonraki her satır bu hasarı referans hattı üzerinden devralır
DamagedRowsBeforeError neyi kurtarır, neyi kurtarmaz?
DamagedRowsBeforeError, HotPDF'nin bozuk bir satırı değiştirip devam etmesini sağlar; ama yalnızca K değeri 0 ya da pozitif ve EndOfLine true olduğunda. O iki koşul keyfî değil. Kurtarma, bitler anlam ifade etmeyi bıraktıktan sonra sonraki satırın nerede başladığını bulmanın bir yolunu ister ve CCITT akışındaki tek güvenilir kilometre taşı EOL kodudur. Group 4 verisinde EOL yoktur ve zorunlu EOL'süz Group 3 verisi bir EOL'nin var olacağını garantilemez; bu yüzden her iki durumda da hasarlı bir satır, parametre değerine bakılmaksızın çözmeyi bitirir
Bir satır başarısız olduğunda HotPDF çözücüsü, en az on bir sıfır bit ve ardından bir birden oluşan sonraki EOL'ye ileri tarar ve bir yedek satır koyar. İyi bir satırdan sonraki ilk hasarlı satır, önceki satırın bir kopyasıyla değiştirilir; taranmış bir metin sayfasında bu genellikle görünmez olacak kadar yakındır. Doğrudan başka bir hasarlı satırı izleyen hasarlı bir satır ise bunun yerine tertemiz beyaz bir satırla değiştirilir; çünkü kopyanın kopyasını almak bir metin satırını uzun bir siyah şeride dönüştürür. Yedek sonra sonraki 2D satır için referans hattına dönüşür ve karma mod bir akışın onarımdan sonra çözülebilir kalmasını sağlayan da budur
İki sınır gözden kaçmaya müsaittir. Bütçe, kötü satır dizileri başına değil, bütün görsel boyunca kümülatiftir; bu yüzden DamagedRowsBeforeError 3 toplam üç hasarlı satırı tolere eder ve dördüncü çözmeyi düşürür. HotPDF'de başarısız bir çözme ya hep ya hiçtir: THotPDF.ExtractLoadedImage, yırtık alt kenarlı bir bitmap yerine nil döndürür. THPDFLoadedImageInfo.Decodable, filtrenin desteklendiğini bildirir; bu özel akışın sağlam olduğunu değil. Bu yüzden bitmap'i her zaman nil için denetleyin
Tarama neden EOL'nin başında durmalı?
Yeniden eşitleme taraması okuyucuyu EOL'nin ilk sıfır bitinde bırakır, ardından değil. Çözücünün tek bir çerçeveleme döngüsü vardır: EOL'leri tüketir, bloğu bitiren çift EOL'yi denetler ve karma mod tag bitini okur. Kurtarma taraması EOL'nin kendisini yutarsa o döngü, EOL'süz bir satır görür, onu da hasarlı sayar ve iyi bir satırı atarken bütçenin ikinci birimini yakar. Daha kötüsü, atlanan bir tag biti, bir 2D satırın 1D ya da tersi olarak çözülmesi demektir. Aynı kural, 1D run çözücüsü satır ortasında beklenmeyen bir EOL'ye çarptığında da geçerlidir: run kodunun başladığı yere geri sarar; böylece işaret, kurtarma taraması için yerinde kalır
Yüklenmiş bir PDF'de CCITT görsellerini envanterlemek
Arşivlenmiş bir faks yığınına güvenmeden önce hangi görsellerin CCITTFaxDecode kullandığını ve hangilerinin çözülemediğini listeleyin. THotPDF.GetLoadedImageInfo, hiçbir şey çözmeden size geometriyi ve filtre adını verir; THotPDF.ExtractLoadedImage ise akışın hayatta kalıp kalmadığını söyler. Görsel dağıtıcının her filtreyi nasıl yönlendirdiğinin daha geniş resmi için yüklenmiş PDF görsellerini ve decode filtrelerini çıkarma rehberine bakın
var
Pdf: THotPDF;
Info: THPDFLoadedImageInfo;
Bmp: TBitmap;
I: Integer;
begin
Pdf := THotPDF.Create(nil);
try
if Pdf.LoadFromFile('fax-archive.pdf', '') <= 0 then
Exit;
for I := 0 to Pdf.GetLoadedImageCount - 1 do
begin
if not Pdf.GetLoadedImageInfo(I, Info) then
Continue;
if Pos('CCITT', UpperCase(String(Info.Filter))) = 0 then
Continue;
Bmp := Pdf.ExtractLoadedImage(I); // akış çok hasarlıyken nil
try
if Bmp = nil then
Writeln(Format('obj %d: %dx%d CCITT failed to decode',
[Info.ObjectNumber, Info.Width, Info.Height]))
else
Bmp.SaveToFile(Format('fax_%d.bmp', [I]));
finally
Bmp.Free; // bitmap'in sahibi çağırandır
end;
end;
finally
Pdf.Free;
end;
end;
Başarısızlıklar için kanıtı saklayın. Varsayılan lismEncoded moduyla THotPDF.ExtractLoadedImageToStream, saklanan akış baytlarına dokunmadan yazar; bu, ikinci bir çözücüye vermek, inceleme için bir TIFF kabına sarmak ya da bir hata kaydına eklemek isteyeceğiniz şeydir. Hasarlı bir faksı yeniden kodlamak yalnızca hasarın nerede olduğunu gizler
procedure SaveRawFax(Pdf: THotPDF; ImageIndex: Integer; const FileName: string);
var
Fs: TFileStream;
begin
Fs := TFileStream.Create(FileName, fmCreate);
try
if not Pdf.ExtractLoadedImageToStream(ImageIndex, Fs, lismEncoded) then
raise Exception.CreateFmt('Image %d has no stream data', [ImageIndex]);
finally
Fs.Free;
end;
end;
Görsel akışlarını kendiniz THotPDF.CollectLoadedImageStreams üzerinden geziyorsanız her THPDFStreamObject'i THotPDF.DecodeLoadedImageStream'e geçirin; aynı CCITT yolunu, parametrelerini ve kurtarma kurallarını alırsınız. Döndürülen listeyi serbest bırakın ama içindeki akış nesnelerini değil; onların sahibi belge olarak kalır
Denetlemediğiniz dosyalarda DamagedRowsBeforeError'u yükseltmeli misiniz?
Hayır; PDF'yi düzenleyerek de hayır, genellikle hiç hayır. Parametre, iletim kanalının bit düşürüp düşürmediğini bilen tek taraf olan üreticiye aittir. DamagedRowsBeforeError 0 bildirip sonra içinde hasarlı bir satır barındıran dosya, size arşiv kopyasının bozuk olduğunu söylüyor ve dürüst sonuç, günlüğe yazabileceğiniz bir çözme başarısızlığıdır. Bir sözleşmede ya da sağlık kaydında satırları sessizce yamamak, saptanabilir bir kusuru, eksik bir satırlı inandırıcı görünümlü bir görsele dönüştürür; sonradan ona güvenen herkes için bu daha kötü bir sonuçtur
Güvenilmeyen arşivler için daha güvenli desen, çözmeyi katı tutmak, hangi nesne numaralarının başarısız olduğunu kaydetmek ve onları bir insana ya da ayrı bir çözücüye yönlendirmektir. Arşiv büyükse ve birçok kaynaktan geliyorsa görsel çözmeyi process dışında çalıştırmak, düşmanca bir akışın ana uygulamaya yapabileceklerini sınırlar; güvenilmeyen PDF'leri işlerken görsel codec'lerini izole etme yazısı o kurulumu anlatır ve JBIG2 bilevel sıkıştırma rehberi, aynı taranmış arşivlerde bulacağınız diğer bilevel filtreyi karşılaştırır
FAQ
HotPDF, Group 4 görsellerinde CCITT sıkıştırılmamış modu destekliyor mu?
Evet. HotPDF, iki boyutlu satırlarda 10 bitlik 0000001111 uzantısını ve tek boyutlu satırlarda 12 bitlik 000000001111 giriş kodunu tanır, harfî kod sözcüklerini çözer ve run kodlaması devam ettiğinde çıkış tag bitine uyar
DamagedRowsBeforeError neden Group 4 faksimde hiçbir etki yaratmıyor?
Kurtarma, yeniden eşitleme için EOL işaretleri ister. HotPDF, DamagedRowsBeforeError değerini yalnızca K değeri 0 ya da pozitif ve EndOfLine true olduğunda uygular; Group 4 verisinde (K negatif) EOL yoktur, bu yüzden herhangi bir hasarlı satır çözmeyi bitirir
ExtractLoadedImage hasarlı bir CCITT görseli için ne döndürür?
THotPDF.ExtractLoadedImage, hasar DamagedRowsBeforeError'un izin verdiğinden fazlaysa ya da hiç kurtarılamıyorsa nil döndürür. Asla kısmi bir bitmap döndürmez; bu yüzden nil için test edin ve ham baytları saklamak için ExtractLoadedImageToStream kullanın
HotPDF, yüklenmiş PDF'lerdeki CCITT, JBIG2, JPEG, JPEG 2000 ve Flate görsellerini sıradan Delphi ve C++Builder kodundan, faks yolu için harici bir DLL olmadan halleder. Ayrıntılar ve sürümler HotPDF Delphi PDF component sayfasında