บทความเทคนิค

ฝังภาพ AVIF, HEIF และ JPEG XL ใน PDF จาก Delphi

PDF Library for Delphi รับภาพ AVIF, HEIF และ JPEG XL เป็นข้อมูลนำเข้าผ่าน AddModernImageFromFile และรูปแบบสตรีมกับสตริงของมัน โดยคงค่าอัลฟา โปรไฟล์ ICC ที่ฝังไว้ และแชนแนล 16 บิต ไว้ตลอดทางเข้าสู่อ็อบเจกต์ภาพ PDF การตรวจจับรูปแบบทำงานด้วยการอ่านเลขวิเศษที่มีขอบเขตจำกัด และการถอดรหัสทำงานผ่านแบ็กเอนด์ที่แทนที่ได้ ดังนั้นจึงไม่มีการเรียกอะไรจากภายนอกสำหรับไฟล์ที่แท้จริงแล้วไม่ใช่หนึ่งในรูปแบบเหล่านั้น

รูปแบบเหล่านี้มาถึงเวิร์กโฟลว์เอกสารผ่านโทรศัพท์มือถือ iOS สร้าง HEIC เป็นค่าเริ่มต้นมาหลายปีแล้ว อุปกรณ์ Android สร้าง AVIF และช่างเทคนิคภาคสนามที่ถ่ายภาพชิ้นส่วนที่เสียหายจะส่งภาพที่ตัวสร้างรายงาน PDF ที่สร้างขึ้นในปี 2015 เปิดไม่ได้เลย เส้นทางสำรองทั่วไป คือการถอดรหัสผ่านบิตแมปของแพลตฟอร์ม จะให้สีแบบ 8 บิตอย่างสม่ำเสมอ และสูญเสียอัลฟากับโปรไฟล์สีไปตลอดทาง

เส้นทางภาพสมัยใหม่รักษาอะไรไว้ที่การแปลงผ่านบิตแมปสูญเสียไป

สามสิ่ง และแต่ละสิ่งมีเวิร์กโฟลว์ที่พึ่งพามันอยู่ อัลฟารอดชีวิต ซึ่งสำคัญสำหรับโลโก้และภาพตัดขอบผลิตภัณฑ์ที่ประกอบทับเนื้อหาหน้า โปรไฟล์ ICC รอดชีวิต ซึ่งสำคัญสำหรับสิ่งใดก็ตามที่จะถูกพิมพ์หรือจับคู่สี และแชนแนล 16 บิตรอดชีวิต ซึ่งสำคัญสำหรับภาพทางการแพทย์และวิทยาศาสตร์ ที่การควอนไทซ์แบบ 8 บิตจะทำลายระดับความละเอียดอ่อนที่ภาพนั้นถูกถ่ายขึ้นมาเพื่อจับ

การส่งภาพผ่านบิตแมปของแพลตฟอร์มจะสูญเสียทั้งสามอย่างในขั้นตอนเดียว และทำอย่างเงียบๆ ด้วย PDF ที่ได้จะดูถูกต้องโดยประมาณ และไม่มีใครสังเกตเห็นจนกว่าโรงพิมพ์จะถามว่าทำไมสีแดงประจำองค์กรถึงผิด ค่าตัวเลือก 8 บนการเรียกภาพสมัยใหม่คือแฟล็กที่คงอัลฟา ICC และแชนแนล 16 บิตไว้ด้วยกัน และเป็นค่าเริ่มต้นสำหรับการเรียกเหล่านั้น

การเพิ่มภาพหนึ่งภาพลงในหน้า

การเรียกใช้งานคืนค่าตัวระบุภาพ ซึ่งจากนั้นจะถูกเลือกและวาด หรือวาดแล้วปล่อยในขั้นตอนเดียว:

uses
  PDFlibrary, PDFlibModernImage;

var
  Lib: TPDFlib;
  ImageID: Integer;
begin
  Lib := TPDFlib.Create;
  try
    Lib.NewDocument;
    Lib.SetPageSize('A4');
    Lib.NewPage;

    // Options = 8 คงอัลฟา ICC และแชนแนล 16 บิตไว้
    ImageID := Lib.AddModernImageFromFile('site-photo.heic', 8);
    if ImageID > 0 then
      Lib.DrawImageAndRelease(ImageID, 40, 40, 515, 340)
    else
      Lib.DrawText(40, 40, 'image could not be decoded');

    Lib.SaveToFile('inspection-report.pdf');
  finally
    Lib.Free;
  end;
end;

การตรวจจับเกิดขึ้นก่อนการถอดรหัส และถูกทำให้แคบอย่างจงใจ ไลบรารีอ่านเฮดเดอร์ที่มีขอบเขตจำกัด รู้จำแบรนด์รูปแบบไฟล์สื่อฐาน ISO ที่ระบุ AVIF และ HEIF และรู้จำลายเซ็นทั้งแบบดิบและแบบคอนเทนเนอร์ของ JPEG XL แล้วจึงเรียกคืนตำแหน่งสตรีมของผู้เรียก ข้อมูลนำเข้าที่ไม่รู้จักหรือปลอมแปลงไม่มีวันไปถึงตัวแปลงรหัสภายนอกได้เลย ซึ่งป้องกันไม่ให้ไฟล์ปฏิบัติการที่เปลี่ยนชื่อถูกส่งให้ตัวถอดรหัสเสมือนเป็นภาพ

การถอดรหัสเกิดขึ้นที่ไหนจริงๆ

รูปแบบภาพสมัยใหม่เป็นตัวแปลงรหัสขนาดใหญ่และซับซ้อน และการใส่ตัวหนึ่งไว้ในไลบรารี PDF จะเป็นทางเลือกการออกแบบที่แปลกประหลาด แบ็กเอนด์เริ่มต้นโหลดโมดูล MagickWand ที่ปรับใช้ได้แบบไดนามิกในโพรเซสเดียวกัน และค้นหามันตามลำดับที่บันทึกไว้ คือไฟล์หรือไดเรกทอรีที่คุณกำหนดไว้อย่างชัดเจน ตัวแปรสภาพแวดล้อม ไดเรกทอรีของไฟล์ปฏิบัติการ และเส้นทางค้นหาของระบบ

แอปพลิเคชันที่จัดส่งตัวถอดรหัสของตัวเองอยู่แล้ว หรือที่ต้องไม่โหลดโมดูลภายนอกเลย จะลงทะเบียนคอลแบ็กของตัวเองแทน ข้อตกลงมีเพียงเล็กน้อย คืออ่านสตรีมนำเข้า เขียน PNG ไปยังสตรีมส่งออก เคารพการวางแนวที่ร้องขอ:

function MyDecoder(InStream, OutPNG: TStream;
  ImageFormat: TPDFlibModernImageFormat;
  ApplyOrientation: Boolean): Boolean;
begin
  // ถอดรหัส InStream ด้วยตัวแปลงรหัสของคุณเอง และเขียนไบต์ PNG ไปที่ OutPNG
  Result := DecodeWithBundledCodec(InStream, OutPNG,
    ImageFormat, ApplyOrientation);
end;

begin
  RegisterModernImageDecoderBackend(MyDecoder);
  // ... เพิ่มภาพ ...
  ClearModernImageDecoderBackend;    // กลับไปยังแบ็กเอนด์เริ่มต้น
end;

การปรับใช้ได้รับความสะดวกหนึ่งอย่างและการยับยั้งชั่งใจอย่างจงใจหนึ่งอย่าง หากไดเรกทอรีตัวแปลงรหัสมีไดเรกทอรีย่อย modules\coders ไลบรารีจะเติมตัวแปรสภาพแวดล้อมของตัวแปลงรหัสที่ผังเช่นนั้นต้องการ แต่จะทำเฉพาะเมื่อแอปพลิเคชันโฮสต์ยังไม่ได้ตั้งค่าไว้แล้วเท่านั้น แอปพลิเคชันที่มีกลยุทธ์การปรับใช้รันไทม์ของตัวเองจะคงมันไว้ตามเดิม

เหตุใดจึงใช้ PNG เป็นตัวกลาง

การเชื่อมผ่าน PNG ในหน่วยความจำแทนที่จะเป็นบัฟเฟอร์พิกเซลดิบดูเหมือนเป็นขั้นตอนเพิ่มเติม แต่แท้จริงแล้วเป็นวิธีที่ถูกต้องและประหยัดที่สุด PNG แสดงทุกสิ่งที่ต้องรอดชีวิต คืออัลฟา ประเภทสี ความลึกบิต และโปรไฟล์ ICC ที่ฝังไว้ และไลบรารีมีเส้นทางที่เป็นผู้ใหญ่และผ่านการทดสอบมาอย่างดีจาก PNG ไปสู่อ็อบเจกต์ภาพ PDF พร้อมฟิลเตอร์และพื้นที่สีที่ถูกต้องอยู่แล้ว การนำมันมาใช้ซ้ำหมายความว่ารูปแบบสมัยใหม่สืบทอดงานความถูกต้องที่สั่งสมมาหลายปี แทนที่จะต้องมีการนำไปใช้งานแบบคู่ขนาน

สะพานเชื่อมนี้อยู่ในหน่วยความจำทั้งหมด ดังนั้นจึงไม่มีการสร้างไฟล์ชั่วคราว และไม่ต้องล้างข้อมูลเมื่อเกิดการล่ม มีจุดขรุขระหนึ่งจุดที่ต้องจัดการอย่างชัดเจน คือการแปลงบางแบบทิ้งโปรไฟล์ ICC เมื่อเปลี่ยนรูปแบบ แบ็กเอนด์จึงจับโปรไฟล์ต้นทางไว้ก่อนการสลับรูปแบบ บีบอัดด้วย Flate สร้างชิ้น iCCP ที่ถูกต้องพร้อม CRC ที่คำนวณใหม่ และลบชิ้น sRGB ใดๆ ที่จะขัดแย้งกับมัน ในการทดสอบ AVIF ที่ถอดรหัสแล้วคง RGBA แบบ 16 บิตพร้อมอัลฟา 16 บิตไว้ และโปรไฟล์ที่สกัดจาก PDF ผลลัพธ์ตรงกับโปรไฟล์ต้นทางแบบไบต์ต่อไบต์ที่ 60,960 ไบต์

ข้อสังเกตเชิงปฏิบัติก่อนเปิดใช้งานในระบบใช้งานจริง

ตรวจสอบความพร้อมใช้งานตอนเริ่มต้น ไม่ใช่ตอนภาพถ่ายแรก ModernImageCodecAvailable รายงานว่าแบ็กเอนด์สามารถใช้งานได้หรือไม่ และ SetModernImageCodecLibrary ชี้ไปยังไฟล์หรือไดเรกทอรีที่ชัดเจนเมื่อการปรับใช้ของคุณวางตัวแปลงรหัสไว้ในที่ที่ไม่เป็นมาตรฐาน:

Lib.SetModernImageCodecLibrary('C:\MyApp\codecs');
if Lib.ModernImageCodecAvailable = 0 then
  Log('modern image input unavailable - HEIC and AVIF will be refused');

จับตาดูขนาดไฟล์ของผลลัพธ์ ภาพ RGBA แบบ 16 บิตพร้อมโปรไฟล์ที่ฝังไว้เป็นอ็อบเจกต์ภาพ PDF ขนาดใหญ่ และรายงานที่มีสี่สิบภาพเช่นนั้นจะมีขนาดใหญ่มาก เมื่อเอกสารมีปลายทางสำหรับการดูบนหน้าจอแทนที่จะเป็นการพิมพ์ การลดความละเอียดก่อนฝังคือทางเลือกที่คุ้มค่า และตัวปรับขนาดทั่วไปอธิบายไว้ในการปรับขนาดไฟล์ PDF ให้เหมาะสม

สุดท้าย ให้ตัดสินใจนโยบายสีอย่างจงใจ การคงโปรไฟล์ต้นทางไว้ถูกต้องสำหรับงานเก็บถาวรและงานพิมพ์ การแปลงเป็นพื้นที่สีทั้งเอกสารถูกต้องเมื่อชุดภาพถ่ายที่ผสมกันต้องดูสอดคล้องกัน และเส้นทางการแปลงอธิบายไว้ในการเปลี่ยนสีเอกสารไปเป็นพื้นที่สีอื่น หากคุณต้องการยืนยันว่ามีอะไรลงเอยอยู่ในไฟล์จริงๆ เส้นทางการตรวจสอบในการสกัดข้อความ ภาพ และฟอนต์ จะรายงานอ็อบเจกต์ภาพที่เอกสารพกอยู่

การนำเข้าภาพสมัยใหม่ การจัดการสี และการปรับขนาดภาพให้เหมาะสม เป็นส่วนหนึ่งของไลบรารีเดียวกันสำหรับ Delphi, C++Builder และ Free Pascal รายการคุณสมบัติทั้งหมดอยู่ที่หน้า PDF Library for Delphi