@@ -791,15 +791,17 @@ 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 (x_object : dict [str , Any ], pil_params : Union [ dict , None ] = None ) -> tuple [Optional [str ], bytes , Any ]:
795795 """
796796 Users need to have the pillow package installed.
797797
798798 It's unclear if pypdf will keep this function here, hence it's private.
799799 It might get removed at any point.
800800
801801 Args:
802- x_object:
802+ x_object:
803+ pil_params: parameters provided to Pillow Image.save() method,
804+ cf. <https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.save>
803805
804806 Returns:
805807 Tuple[file extension, bytes, PIL.Image.Image]
@@ -846,6 +848,9 @@ def _apply_alpha(
846848 extension = ".png"
847849 return img , extension , image_format
848850
851+ if pil_params is None :
852+ pil_params = {}
853+
849854 # For error reporting
850855 obj_as_text = (
851856 x_object .indirect_reference .__repr__ ()
@@ -905,6 +910,8 @@ def _apply_alpha(
905910 except UnidentifiedImageError :
906911 img = _extended_image_frombytes (mode , size , data )
907912 elif lfilters == FT .DCT_DECODE :
913+ if "quality" not in pil_params :
914+ pil_params ["quality" ] = "keep"
908915 img , image_format , extension = Image .open (BytesIO (data )), "JPEG" , ".jpg"
909916 # invert_color kept unchanged
910917 elif lfilters == FT .JPX_DECODE :
@@ -950,7 +957,7 @@ def _apply_alpha(
950957 # Save image to bytes
951958 img_byte_arr = BytesIO ()
952959 try :
953- img .save (img_byte_arr , format = image_format )
960+ img .save (img_byte_arr , format = image_format , ** pil_params )
954961 except OSError : # pragma: no cover # covered with pillow 10.3
955962 # in case of we convert to RGBA and then to PNG
956963 img1 = img .convert ("RGBA" )
0 commit comments