From bb620c8f0634bfbf06441188a0f749ada0bc8da6 Mon Sep 17 00:00:00 2001 From: John Whitington Date: Mon, 1 Jan 2024 11:46:32 +0000 Subject: [PATCH] Extend PNG loading to greyscale and 16bpp --- Changes | 1 + cpdfimage.ml | 30 +++++++++++++++--------------- cpdfpng.ml | 16 +++++++++++----- cpdfpng.mli | 4 +++- 4 files changed, 30 insertions(+), 21 deletions(-) diff --git a/Changes b/Changes index 44b4de2..e4988a5 100644 --- a/Changes +++ b/Changes @@ -24,6 +24,7 @@ Extended features: o -list-images-used[-json] extends -image-resolution o Use -raw with -extract-images to get PNMs o -extract-images can extract JBIG2 images and their globals +o more PNGs - greyscale 1, 2, 4, 8, 16bpp and RGB 16bpp Fixes: diff --git a/cpdfimage.ml b/cpdfimage.ml index c792070..173d57d 100644 --- a/cpdfimage.ml +++ b/cpdfimage.ml @@ -429,21 +429,21 @@ let obj_of_jpeg_data data = let obj_of_png_data data = let png = Cpdfpng.read_png (Pdfio.input_of_bytes data) in - let d = - ["/Length", Pdf.Integer (Pdfio.bytes_size png.idat); - "/Filter", Pdf.Name "/FlateDecode"; - "/Subtype", Pdf.Name "/Image"; - "/BitsPerComponent", Pdf.Integer 8; - "/ColorSpace", Pdf.Name "/DeviceRGB"; - "/DecodeParms", Pdf.Dictionary - ["/BitsPerComponent", Pdf.Integer 8; - "/Colors", Pdf.Integer 3; - "/Columns", Pdf.Integer png.width; - "/Predictor", Pdf.Integer 15]; - "/Width", Pdf.Integer png.width; - "/Height", Pdf.Integer png.height] - in - Pdf.Stream {contents = (Pdf.Dictionary d, Pdf.Got png.idat)}, [] + let d = + ["/Length", Pdf.Integer (Pdfio.bytes_size png.idat); + "/Filter", Pdf.Name "/FlateDecode"; + "/Subtype", Pdf.Name "/Image"; + "/BitsPerComponent", Pdf.Integer png.bitdepth; + "/ColorSpace", Pdf.Name (match png.colortype with 0 -> "/DeviceGray" | 2 -> "/DeviceRGB" | _ -> error "obj_of_png_data 1"); + "/DecodeParms", Pdf.Dictionary + ["/BitsPerComponent", Pdf.Integer png.bitdepth; + "/Colors", Pdf.Integer (match png.colortype with 0 -> 1 | 2 -> 3 | _ -> error "obj_of_png_data 2"); + "/Columns", Pdf.Integer png.width; + "/Predictor", Pdf.Integer 15]; + "/Width", Pdf.Integer png.width; + "/Height", Pdf.Integer png.height] + in + Pdf.Stream {contents = (Pdf.Dictionary d, Pdf.Got png.idat)}, [] let jbig2_dimensions data = (bget data 11 * 256 * 256 * 256 + bget data 12 * 256 * 256 + bget data 13 * 256 + bget data 14, diff --git a/cpdfpng.ml b/cpdfpng.ml index a55f56e..48d8c11 100644 --- a/cpdfpng.ml +++ b/cpdfpng.ml @@ -1,12 +1,15 @@ -(* Read non-interlaced, non-transparent 24 bit PNGs. Such a PNG may +(* Read non-interlaced, non-transparent PNGs. Such a PNG may be loaded into a PDF simply by extracting its width and height from the - IHDR, and concatenating all its IDAT data sections together. *) + IHDR, and concatenating all its IDAT data sections together, and specifying + the appropriate Filter and Predictor.*) open Pdfutil open Pdfio type t = {width : int; height : int; + bitdepth : int; + colortype : int; idat : bytes} (* Writing *) @@ -121,9 +124,8 @@ let read_png i = let width = read_unsigned_4byte hdr in let height = read_unsigned_4byte hdr in let bitdepth = hdr.input_byte () in - if bitdepth <> 8 then raise (Pdf.PDFError "read_png: bit depth not 8") else let colortype = hdr.input_byte () in - if colortype <> 2 then raise (Pdf.PDFError "read_png: only 24 bit non-alpha PNGs") else + if colortype <> 2 && colortype <> 0 then raise (Pdf.PDFError "read_png: only non-alpha non-palette PNGs") else let _ (*compressionmethod*) = hdr.input_byte () in let _ (*filtermethod*) = hdr.input_byte () in let interlacemethod = hdr.input_byte () in @@ -137,6 +139,10 @@ let read_png i = with _ -> () end; - {width = i32toi width; height = i32toi height; idat = concat_bytes (rev !idat)} + {width = i32toi width; + height = i32toi height; + colortype; + bitdepth; + idat = concat_bytes (rev !idat)} with e -> raise (Pdf.PDFError (Printf.sprintf "read_png: failed on %s" (Printexc.to_string e))) diff --git a/cpdfpng.mli b/cpdfpng.mli index 6729e46..d8247bf 100644 --- a/cpdfpng.mli +++ b/cpdfpng.mli @@ -4,7 +4,9 @@ type t = {width : int; height : int; + bitdepth : int; + colortype : int; idat : Pdfio.bytes} -(** Read a non-interlaced, non-transparent 24 bit PNG for inclusion in a PDF file. *) +(** Read a non-interlaced, non-alpha, non-palette PNG for inclusion in a PDF file. *) val read_png : Pdfio.input -> t