Taranmış tıbbi bir slayt, havadan yapılmış bir araştırma karosu, tam dinamik aralıkta arşivlenmiş bir film karesi. Bunlar JPEG 2000 olarak gelen resimlerdir ve bu şekilde gelmelerinin bir nedeni vardır. Biçim, kanal başına 12 veya 16 bit tutar, JPEG'in kullandığı blok DCT yerine bir dalgacık (wavelet) dönüşümü ile sıkıştırır ve aynı resmi tek bir kod akışından (codestream) kayıpsız veya kayıplı olarak kodlayabilir. Bu kaynaklardan oluşturulan bir belgenin PDF olması gerektiğinde, görüntünün PDF spesifikasyonunun tam da bu kodek için ayırdığı bir filtreden geçmesi gerekir
HotPDF v2.228.0, o yol için çalışan bir JPEG 2000 kod çözme motorunu geri yükledi. Daha önceki bir yapı, birimi nil döndüren saplama (stub) işlevleriyle birlikte göndermişti, bu nedenle API mevcuttu ancak hiçbir şeyin kodunu çözmüyordu. Mevcut motor OpenJPEG 2.5.4'ü statik olarak bağlar ve bir JP2 veya J2K kaynağını HotPDF'in bir sayfaya yerleştirebileceği piksellere dönüştürür
PDF'de JPXDecode filtresi
ISO 32000-1, JPXDecode filtresini §7.4.9'da tanımlar. Bir PDF görüntü XObject'i, akış sözlüğünün /Filter girdisinde sıkıştırmasını adlandırır ve JPXDecode, akış verisinin /DCTDecode'un taşıdığı temel (baseline) JPEG yerine bir JPEG 2000 kod akışı olduğunu söyleyen değerdir. Filtre, bir PDF'in yüksek bit derinliğine sahip dalgacık sıkıştırmalı görüntü verilerini tutmasını sağlayan şeydir ve kodecin hem kayıpsız hem de kayıplı modlarını kabul eder, çünkü mod, etrafındaki sarmalayıcının değil, kod akışının kendisinin bir özelliğidir
Tutunmaya değer olan son noktadır. JPEG 2000, iki ayrı biçim değil, kayıpsız özel bir duruma sahip tek bir algoritmadır. Tersine çevrilebilir (reversible) 5/3 dalgacık, orijinal örnekleri tam olarak yeniden oluşturur; tersine çevrilemez (irreversible) 9/7 dalgacık ise bu kesinliği daha küçük bir dosya için takas eder. Bir kod çözücü okuma anında her ikisine de aynı şekilde davranır; işte bu yüzden HotPDF'in bir JPXDecode akışının önüne attığı her şeyi kabul etmesi için yalnızca bir kod çözme yoluna ihtiyacı vardır
Kod çözücünün piksellere yaptığı şey
Yaygın durumda PDF görüntü XObject'leri, DeviceGray veya DeviceRGB'de bileşen başına 8 bit bekler. JPEG 2000 rutin olarak bunu aşar ve bileşen modeli paketlenmiş bir raster'dan daha geneldir, bu nedenle verilerin normal bir görüntü olarak kullanılabilmesi için kod çözücünün yapması gereken üç iş vardır
İlk olarak, yüksek bit derinliğine sahip bileşenler 8 bite yeniden örneklenir. 12 bit veya 16 bitlik bir örnek, sonucun sıradan bir 8 bitlik raster olması için 0 ile 255 aralığına küçültülür. İşaretli bileşenler önce işaretsiz aralığa kaydırılır. Ayrıntı önemlidir çünkü başlı başına kayıplıdır: 16 bit gri tonlamalı bir tarama, 8 bitlik bir PDF görüntüsü olduğu anda derin ton aralığını kaybeder; bu, ekran ve baskı çıktısı için doğru takastır ancak yeniden arşivlemek için değildir
İkinci olarak, bir YCbCr (kodek buna SYCC der) renk uzayı RGB'ye dönüştürülür. JPEG 2000 sıkıştırma verimliliği için rengi genellikle temel JPEG'in kullandığı fikrin aynısı olan luma-kroma (parlaklık-renklilik) uzayında depolar ve kod çözücü sayfanın gerçek RGB'yi alması için standart ters dönüşümü uygular
Üçüncü olarak, alt örneklenmiş (subsampled) bileşenler, en yakın komşu (nearest-neighbor) replikasyonu ile üst örneklenir (upsampled). Kroma kanalları sıklıkla yarı çözünürlükte depolanır, bu nedenle kod çözücü her bileşeni kendi boyutlarında ve kendi örnekleme faktöründe okur, ardından her kanalı birbirine eklemeden (interleaving) önce tam görüntü boyutuna getirmek için örnekleri çoğaltır. En yakın komşu adımı ucuz tutar; doldurduğu kroma zaten düşük frekanslıydı, bu nedenle görünür maliyet küçüktür
JP2 kutularına karşı ham bir J2K kod akışı
Bir JPEG 2000 dosyası iki şekilde gelir ve HotPDF, dosya uzantısından ziyade ilk baytlardan hangisini okuduğunu algılar. Bir JP2 dosyası kutu yapılı (box-structured) bir kapsayıcıdır: 00 00 00 0C 6A 50 20 20 şeklindeki on iki baytlık imza kutusuyla açılır ve kod akışını renk uzayını, çözünürlüğü ve meta verileri açıklayan kutuların yanına sarar. Ham bir J2K kod akışı hiçbir kapsayıcı taşımaz ve SOC işareti FF 4F FF 51 ile başlar. Kod çözücü bu baştaki baytları okur, imzayı tanır ve her durum için eşleşen OpenJPEG kodecini seçer
Her ikisi de doğada (vahşi doğada) meydana geldiği için her iki şekil de ele alınır. Yan meta verilere ihtiyaç duyan yakalama cihazları ve arşivler JP2 yayar; mümkün olan en küçük yükü (payload) isteyen araçlar ise çıplak kod akışını yayar. Biçim türü, jtInvalid, jtJP2, jtJ2K ve jtJPT üyeleriyle bir TJpeg2000FileType sabiti (enum) olarak modellenir. JPT üyesi, JPIP akış varyantını adlandırır; bayt imza dedektörü, kodunu çözebileceği iki şekli, JP2 ve J2K'yı çözer ve desteklenmeyen bir girdinin çöp üretmek yerine temiz bir şekilde başarısız olması için diğer her şeyi jtInvalid olarak bildirir
uses
HPDFJpeg2000;
var
Decoder: THPDFJpeg2000Decoder;
Pixels: TJpeg2000ByteArray;
begin
Decoder := THPDFJpeg2000Decoder.Create;
try
if Decoder.LoadFromStream(Input) then // JP2 or J2K, auto-detected
if Decoder.GetImageData(Pixels) then
// Pixels is 8-bit interleaved, ColorComponents channels wide,
// row-major top to bottom: ready for a DeviceGray/DeviceRGB XObject.
ProcessRaster(Decoder.Width, Decoder.Height,
Decoder.ColorComponents, Pixels);
finally
Decoder.Free;
end;
end;
Kodlama tarafında kayıpsız ve kayıplı
Kod çözücü her iki modu da kendisine hangisi olduğu söylenmeden okur. Seçim, yalnızca diğer yoldan gidip HotPDF'in raster verilerini JP2 olarak yükleyen ve kaydeden bir TBitmap soyundan gelen TJpeg2000Bitmap sınıfı aracılığıyla da yapabileceği bir JPEG 2000 dosyası ürettiğinizde bir parametre haline gelir. İki özellik çıktıyı yönetir. LosslessCompression, doğru olduğunda tersine çevrilebilir dalgacığı seçen bir boolean'dır; CompressionQuality, 1'in küçük ve çirkin, 100'ün ise büyük ve sadık olduğu 1'den 100'e kadar bir tamsayı olan TJpeg2000QualityRange'dir. Varsayılanlar adlandırılmış sabitlerde yaşar: Jpeg2000DefaultLosslessCompression False ve Jpeg2000DefaultLossyQuality 80'dir
Karar bir içerik kararıdır. Kayıpsız, daha sonra yeniden kodlanabilecek ve nesil kaybı biriktirmemesi gereken bir ana kopyaya, tıbbi veya yasal bir taramaya veya herhangi bir şeye uyar. Kalite 80'deki kayıplı mod, dalgacığın zarif bozulmasının okuyucunun yakalayabileceği hiçbir yapaylık (artifact) olmadan gözle görülür şekilde daha küçük bir dosya sağladığı ekran veya baskıya giden bir resme uyar. İşaretlenmesi gereken bir CMYK uyarısı vardır: bit eşlem, dört kanallı verileri RGBA yerine CMYK olarak işaretlemek için SetCMYK'yi açığa çıkarır, bu da ayrımları bozulmamış halde tutan baskı boru hatları (pipelines) için önemlidir
uses
HPDFJpeg2000;
var
Bmp: TJpeg2000Bitmap;
begin
Bmp := TJpeg2000Bitmap.Create;
try
Bmp.LoadFromStream(Source); // decode an existing JP2/J2K
Bmp.LosslessCompression := True; // reversible 5/3 wavelet
// or, for a smaller lossy file:
// Bmp.LosslessCompression := False;
// Bmp.CompressionQuality := 80; // matches the default
Bmp.SaveToStream(Output); // always writes a JP2 file
finally
Bmp.Free;
end;
end;
Neden yüklemede kod çözme (decode-on-load) filtre boru hattı yok
Mimari bir gerçek, tüm bunları nasıl kullanacağınızı şekillendirir ve aksini varsaymak kolaydır. HotPDF'in genel bir yüklemede kod çözme görüntü filtresi yoktur. Zaten bir JPXDecode görüntüsü içeren bir PDF'i açtığınızda, motor o akışın kodunu çözmez. JPEG 2000 baytlarını tam olarak oldukları gibi tutar, böylece bir sayfa kopyası veya belge birleştirmesi, görüntüyü bayt bayt dokunulmamış halde taşır. Kod çözücünün tek bir giriş noktası vardır ve bu oluşturma tarafındadır: dosya tabanlı AddImage, .jp2, .j2k, .jpt ve .jpc kaynaklarını işlemek üzere dosya uzantısına göre gönderilir
Bu bölünme bir sınırlamadan ziyade doğru tasarımdır. Gömülü bir JPX akışını yüklemede çözerken, yalnızca kaydederken yeniden kodlamak, kayıpsız arşivlenmiş bir görüntüyü kayıplı olana dönüştürür ve her bir birleştirmeyi, sırf bir PDF'den diğerine taşımak istediğiniz bir resim için şişirirdi. Akışı kelimesi kelimesine (verbatim) geçirmek kayıpsız ve hızlı bir işlemdir. Kod çözme işlemi yalnızca gerçekten gerekli olduğu ana ertelenir: motora diskten bir JPEG 2000 dosyası verip yeni bir sayfaya yerleştirmek üzere o resmi rasterleştirmesini istediğinizde. O noktada dosyanın piksel olması gerekir ve kod çözücü çalışır
Desteğin kaydedilmesi ve bir resmin yerleştirilmesi
JPEG 2000 resmi kaydı, varsayılan olarak kapalı olan HPDF_REGISTER_JPEG2000_PICTURE derleme anahtarının arkasında isteğe bağlıdır. Bunun nedeni bir önlem değil, gerçek bir çatışmadır: jp2, j2k ve jpc dosya formatlarını küresel olarak TPicture ile kaydetmek, ReportBuilder'ın TppDBImage öğesinin güvendiği BLOB formatı algılamasına müdahale edebilir. Bu entegrasyon devrede olmadığında anahtarı tanımlayın; dosya formatları kaydedilir, böylece TPicture onları tanır; tanımsız bırakın, AddImage uzantı dağıtımı yine de JPEG 2000 dosyalarının kodunu doğrudan çözer, çünkü o yol TPicture üzerinden hiç geçmez
Bu anlaşıldığında, bir JPEG 2000 resmi yerleştirmek diğer tüm HotPDF görüntüleriyle aynı üç çağrılı ritimdir. AddImage öğesine bir .jp2 yolu ve resmin çıktıda nasıl saklanacağına ilişkin bir sıkıştırma türü verin, ardından döndürülen görüntü indeksini ShowImage ile sayfada konumlandırın
var
Pdf: THotPDF;
ImgIndex: Integer;
begin
Pdf := THotPDF.Create(nil);
try
Pdf.BeginDoc;
Pdf.AddPage;
// The .jp2 source is decoded through the OpenJPEG backend, then
// re-embedded with the compression you request here.
ImgIndex := Pdf.AddImage('Scan_16bit.jp2', icJpeg);
// x, y, width, height in points; final 0 is the rotation angle.
Pdf.ShowImage(ImgIndex, 72, 72, 400, 300, 0);
Pdf.EndDoc;
finally
Pdf.Free;
end;
end;
AddImage öğesine ilettiğiniz sıkıştırma, kodu çözülmüş resmin nasıl okunduğunu değil, nasıl yeniden depolandığını denetler. Bit eşleme çözülmüş bir JPEG 2000 dosyası, belgeye hangisi uyuyorsa DCTDecode JPEG, Flate raster veya desteklenen başka bir filtre olarak geri çıkabilir. JP2 veya J2K'dan kod çözme işlemi ne olursa olsun ilk olarak gerçekleşir, bu nedenle aynı çağrı dalgacık sıkıştırmalı bir kaynağı kabul eder ve boru hattınızın geri kalanı hangi biçimi bekliyorsa o biçimde gömer
Görüntülerin ve yazı tiplerinin oluşturulan çıktıya nasıl yerleştiğinin daha geniş resmi için, Delphi'de yazı tipleri ve resimlerle rapor çıktısı hakkındaki notlarımıza bakın. Birleştirdiğiniz belge mevcut PDF'lerden gelen içeriği yeniden kullandığında, burada açıklanan doğrudan geçiş (passthrough) davranışı, nesne akışları ve artımlı güncellemelerdeki birleştirme ve revizyon mekanikleriyle eşleşir. JPEG 2000 kod çözme motoru, bu blogda başka yerlerde ele alınan görüntü, yazı tipi ve belge API'lerinin yanı sıra, Delphi ve C++Builder için HotPDF Component'inin bir parçası olarak gönderilir