From 022e650d18e41867f481d23197e6fd0ec35dbdd2 Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 3 Aug 2023 19:11:35 +1000 Subject: [PATCH 1/3] Set SMaskInData to 1 for PDFs with alpha --- src/PIL/PdfImagePlugin.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index c41f8aee004..40ddf808e5c 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -128,6 +128,7 @@ def _save(im, fp, filename, save_all=False): bits = 8 params = None decode = None + smaskindata = 0 # # Get image characteristics @@ -177,6 +178,7 @@ def _save(im, fp, filename, save_all=False): filter = "JPXDecode" colorspace = PdfParser.PdfName("DeviceRGB") procset = "ImageC" # color images + smaskindata = 1 elif im.mode == "CMYK": filter = "DCTDecode" colorspace = PdfParser.PdfName("DeviceCMYK") @@ -232,6 +234,7 @@ def _save(im, fp, filename, save_all=False): Decode=decode, DecodeParms=params, ColorSpace=colorspace, + SMaskInData=smaskindata, ) # From ddfb7ef14b0a13b05f57203cacadfd295b59e48f Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 3 Aug 2023 22:05:11 +1000 Subject: [PATCH 2/3] Do not set BitsPerComponent for JPXDecode since it is ignored --- src/PIL/PdfImagePlugin.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index 40ddf808e5c..bcb0b393761 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -125,20 +125,19 @@ def _save(im, fp, filename, save_all=False): # (packbits) or LZWDecode (tiff/lzw compression). Note that # PDF 1.2 also supports Flatedecode (zip compression). - bits = 8 params = None decode = None - smaskindata = 0 # # Get image characteristics width, height = im.size + dict_obj = {"BitsPerComponent": 8} if im.mode == "1": if features.check("libtiff"): filter = "CCITTFaxDecode" - bits = 1 + dict_obj["BitsPerComponent"] = 1 params = PdfParser.PdfArray( [ PdfParser.PdfDict( @@ -178,7 +177,7 @@ def _save(im, fp, filename, save_all=False): filter = "JPXDecode" colorspace = PdfParser.PdfName("DeviceRGB") procset = "ImageC" # color images - smaskindata = 1 + dict_obj["SMaskInData"] = 1 elif im.mode == "CMYK": filter = "DCTDecode" colorspace = PdfParser.PdfName("DeviceCMYK") @@ -206,6 +205,7 @@ def _save(im, fp, filename, save_all=False): elif filter == "DCTDecode": Image.SAVE["JPEG"](im, op, filename) elif filter == "JPXDecode": + del dict_obj["BitsPerComponent"] Image.SAVE["JPEG2000"](im, op, filename) elif filter == "FlateDecode": ImageFile._save(im, op, [("zip", (0, 0) + im.size, 0, im.mode)]) @@ -230,11 +230,10 @@ def _save(im, fp, filename, save_all=False): Width=width, # * 72.0 / x_resolution, Height=height, # * 72.0 / y_resolution, Filter=filter, - BitsPerComponent=bits, Decode=decode, DecodeParms=params, ColorSpace=colorspace, - SMaskInData=smaskindata, + **dict_obj, ) # From 6ca38552c98bcd3630f3f8bc4611f4ad6f0e342b Mon Sep 17 00:00:00 2001 From: Andrew Murray Date: Thu, 3 Aug 2023 22:07:36 +1000 Subject: [PATCH 3/3] Do not set ColorSpace for JPXDecode since it is optional --- src/PIL/PdfImagePlugin.py | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/PIL/PdfImagePlugin.py b/src/PIL/PdfImagePlugin.py index bcb0b393761..9566f0bc9cd 100644 --- a/src/PIL/PdfImagePlugin.py +++ b/src/PIL/PdfImagePlugin.py @@ -152,17 +152,17 @@ def _save(im, fp, filename, save_all=False): ) else: filter = "DCTDecode" - colorspace = PdfParser.PdfName("DeviceGray") + dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray") procset = "ImageB" # grayscale elif im.mode == "L": filter = "DCTDecode" # params = f"<< /Predictor 15 /Columns {width-2} >>" - colorspace = PdfParser.PdfName("DeviceGray") + dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray") procset = "ImageB" # grayscale elif im.mode == "P": filter = "ASCIIHexDecode" palette = im.getpalette() - colorspace = [ + dict_obj["ColorSpace"] = [ PdfParser.PdfName("Indexed"), PdfParser.PdfName("DeviceRGB"), 255, @@ -171,16 +171,15 @@ def _save(im, fp, filename, save_all=False): procset = "ImageI" # indexed color elif im.mode == "RGB": filter = "DCTDecode" - colorspace = PdfParser.PdfName("DeviceRGB") + dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceRGB") procset = "ImageC" # color images elif im.mode == "RGBA": filter = "JPXDecode" - colorspace = PdfParser.PdfName("DeviceRGB") procset = "ImageC" # color images dict_obj["SMaskInData"] = 1 elif im.mode == "CMYK": filter = "DCTDecode" - colorspace = PdfParser.PdfName("DeviceCMYK") + dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceCMYK") procset = "ImageC" # color images decode = [1, 0, 1, 0, 1, 0, 1, 0] else: @@ -232,7 +231,6 @@ def _save(im, fp, filename, save_all=False): Filter=filter, Decode=decode, DecodeParms=params, - ColorSpace=colorspace, **dict_obj, )