From 5f8c53eb149547e4fbeba3da381be4ea9c0b6907 Mon Sep 17 00:00:00 2001 From: John Whitington Date: Fri, 22 Mar 2024 15:24:48 +0000 Subject: [PATCH] JPEG2000 embedding --- cpdfcommand.ml | 1 + cpdfjpeg2000.ml | 39 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/cpdfcommand.ml b/cpdfcommand.ml index 76da0c8..fbe2665 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -1063,6 +1063,7 @@ let anon_fun s = | a::b::c::'.'::r when implode (map Char.uppercase_ascii [c; b; a]) = "JPG" -> set_input_jpeg s | a::b::c::'.'::r when implode (map Char.uppercase_ascii [c; b; a]) = "JP2" -> set_input_jpeg2000 s | a::b::c::'.'::r when implode (map Char.uppercase_ascii [c; b; a]) = "JPX" -> set_input_jpeg2000 s + | a::b::c::'.'::r when implode (map Char.uppercase_ascii [c; b; a]) = "JPF" -> set_input_jpeg2000 s | a::b::c::'.'::r when implode (map Char.uppercase_ascii [c; b; a]) = "PNG" -> set_input_png s | _ -> args.inputs <- (InFile s, "all", "", "", ref false, None)::args.inputs end; diff --git a/cpdfjpeg2000.ml b/cpdfjpeg2000.ml index a27acd1..ac058ed 100644 --- a/cpdfjpeg2000.ml +++ b/cpdfjpeg2000.ml @@ -1,5 +1,40 @@ open Pdfutil open Pdfio +open Cpdferror -(* Return the width and height of a JPEG2000 image. *) -let jpeg2000_dimensions bs = (28, 30) +let read_word i = + let a = i32ofi (i.input_byte ()) in + let b = i32ofi (i.input_byte ()) in + let c = i32ofi (i.input_byte ()) in + let d = i32ofi (i.input_byte ()) in + lor32 (lor32 (lor32 (lsl32 a 24) (lsl32 b 16)) (lsl32 c 8)) d + +exception Answer of int * int + +let id_IMAGE_HEADER_BOX = 0x69686472l (* ihdr *) + +(* Return the width and height of a JPEG2000 (.jp2 or .jpx) image. *) +let jpeg2000_dimensions_inner bs = + let i = Pdfio.input_of_bytes bs in + let a = read_word i in + let b = read_word i in + let c = read_word i in + if a <> 0x0000000cl || b <> 0x6a502020l || c <> 0x0d0a870al then + Cpdferror.error "bad JPEG2000 header" + else + while true do + let box = read_word i in + if box = id_IMAGE_HEADER_BOX then + begin + let h = read_word i in + let w = read_word i in + raise (Answer (i32toi w, i32toi h)) + end; + (* Read words starting at each byte until we find ihdr. *) + i.seek_in (i.pos_in () - 3) + done + +let jpeg2000_dimensions bs = + try jpeg2000_dimensions_inner bs; (0, 0) with + | Answer (w, h) -> (w, h) + | Exit -> error "could not determine JPEG2000 dimensions"