@@ -791,15 +791,20 @@ def decode_stream_data(stream: Any) -> bytes:
791791 return data
792792
793793
794- def _xobj_to_image (x_object : dict [str , Any ]) -> tuple [Optional [str ], bytes , Any ]:
794+ def _xobj_to_image (
795+ x_object : dict [str , Any ],
796+ pil_params : Union [dict [str , Any ], None ] = None
797+ ) -> tuple [Optional [str ], bytes , Any ]:
795798 """
796799 Users need to have the pillow package installed.
797800
798801 It's unclear if pypdf will keep this function here, hence it's private.
799802 It might get removed at any point.
800803
801804 Args:
802- x_object:
805+ x_object:
806+ pil_params: parameters provided to Pillow Image.save() method,
807+ cf. <https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save>
803808
804809 Returns:
805810 Tuple[file extension, bytes, PIL.Image.Image]
@@ -846,6 +851,9 @@ def _apply_alpha(
846851 extension = ".png"
847852 return img , extension , image_format
848853
854+ if pil_params is None :
855+ pil_params = {}
856+
849857 # For error reporting
850858 obj_as_text = (
851859 x_object .indirect_reference .__repr__ ()
@@ -905,6 +913,8 @@ def _apply_alpha(
905913 except UnidentifiedImageError :
906914 img = _extended_image_frombytes (mode , size , data )
907915 elif lfilters == FT .DCT_DECODE :
916+ if "quality" not in pil_params :
917+ pil_params ["quality" ] = "keep"
908918 img , image_format , extension = Image .open (BytesIO (data )), "JPEG" , ".jpg"
909919 # invert_color kept unchanged
910920 elif lfilters == FT .JPX_DECODE :
@@ -950,7 +960,7 @@ def _apply_alpha(
950960 # Save image to bytes
951961 img_byte_arr = BytesIO ()
952962 try :
953- img .save (img_byte_arr , format = image_format )
963+ img .save (img_byte_arr , format = image_format , ** pil_params )
954964 except OSError : # pragma: no cover # covered with pillow 10.3
955965 # in case of we convert to RGBA and then to PNG
956966 img1 = img .convert ("RGBA" )
0 commit comments