mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-04-20 17:22:00 +03:00
Use DCTDecode and SMask when saving LA and RGBA images
This commit is contained in:
parent
4f4b0bc748
commit
225de5baa8
|
@ -12,7 +12,7 @@ import pytest
|
|||
|
||||
from PIL import Image, PdfParser, features
|
||||
|
||||
from .helper import hopper, mark_if_feature_version, skip_unless_feature
|
||||
from .helper import hopper, mark_if_feature_version
|
||||
|
||||
|
||||
def helper_save_as_pdf(tmp_path: Path, mode: str, **kwargs: Any) -> str:
|
||||
|
@ -41,17 +41,11 @@ def helper_save_as_pdf(tmp_path: Path, mode: str, **kwargs: Any) -> str:
|
|||
return outfile
|
||||
|
||||
|
||||
@pytest.mark.parametrize("mode", ("L", "P", "RGB", "CMYK"))
|
||||
@pytest.mark.parametrize("mode", ("L", "LA", "P", "RGB", "RGBA", "CMYK"))
|
||||
def test_save(tmp_path: Path, mode: str) -> None:
|
||||
helper_save_as_pdf(tmp_path, mode)
|
||||
|
||||
|
||||
@skip_unless_feature("jpg_2000")
|
||||
@pytest.mark.parametrize("mode", ("LA", "RGBA"))
|
||||
def test_save_alpha(tmp_path: Path, mode: str) -> None:
|
||||
helper_save_as_pdf(tmp_path, mode)
|
||||
|
||||
|
||||
def test_p_alpha(tmp_path: Path) -> None:
|
||||
# Arrange
|
||||
outfile = str(tmp_path / "temp.pdf")
|
||||
|
|
|
@ -1585,9 +1585,8 @@ files. Different encoding methods are used, depending on the image mode.
|
|||
|
||||
* 1 mode images are saved using TIFF encoding, or JPEG encoding if libtiff support is
|
||||
unavailable
|
||||
* L, RGB and CMYK mode images use JPEG encoding
|
||||
* L, LA, RGB, RGBA and CMYK mode images use JPEG encoding
|
||||
* P mode images use HEX encoding
|
||||
* LA and RGBA mode images use JPEG2000 encoding
|
||||
|
||||
.. _pdf-saving:
|
||||
|
||||
|
|
|
@ -54,6 +54,7 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
|||
|
||||
params = None
|
||||
decode = None
|
||||
smask = None
|
||||
|
||||
#
|
||||
# Get image characteristics
|
||||
|
@ -81,16 +82,16 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
|||
filter = "DCTDecode"
|
||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
||||
procset = "ImageB" # grayscale
|
||||
elif im.mode == "L":
|
||||
elif im.mode in ("L", "LA"):
|
||||
filter = "DCTDecode"
|
||||
# params = f"<< /Predictor 15 /Columns {width-2} >>"
|
||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
||||
procset = "ImageB" # grayscale
|
||||
elif im.mode == "LA":
|
||||
filter = "JPXDecode"
|
||||
# params = f"<< /Predictor 15 /Columns {width-2} >>"
|
||||
procset = "ImageB" # grayscale
|
||||
dict_obj["SMaskInData"] = 1
|
||||
if im.mode == "LA":
|
||||
smask = im
|
||||
|
||||
im = im.convert("L")
|
||||
im.encoderinfo = {}
|
||||
elif im.mode == "P":
|
||||
filter = "ASCIIHexDecode"
|
||||
palette = im.getpalette()
|
||||
|
@ -103,19 +104,16 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
|||
procset = "ImageI" # indexed color
|
||||
|
||||
if "transparency" in im.info:
|
||||
smask = im.convert("LA").getchannel("A")
|
||||
smask.encoderinfo = {}
|
||||
|
||||
image_ref = _write_image(smask, filename, existing_pdf, image_refs)[0]
|
||||
dict_obj["SMask"] = image_ref
|
||||
elif im.mode == "RGB":
|
||||
smask = im.convert("LA")
|
||||
elif im.mode in ("RGB", "RGBA"):
|
||||
filter = "DCTDecode"
|
||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceRGB")
|
||||
procset = "ImageC" # color images
|
||||
elif im.mode == "RGBA":
|
||||
filter = "JPXDecode"
|
||||
procset = "ImageC" # color images
|
||||
dict_obj["SMaskInData"] = 1
|
||||
if im.mode == "RGBA":
|
||||
smask = im
|
||||
|
||||
im = im.convert("RGB")
|
||||
im.encoderinfo = {}
|
||||
elif im.mode == "CMYK":
|
||||
filter = "DCTDecode"
|
||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceCMYK")
|
||||
|
@ -125,6 +123,13 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
|||
msg = f"cannot save mode {im.mode}"
|
||||
raise ValueError(msg)
|
||||
|
||||
if smask:
|
||||
smask = smask.getchannel("A")
|
||||
smask.encoderinfo = {}
|
||||
|
||||
image_ref = _write_image(smask, filename, existing_pdf, image_refs)[0]
|
||||
dict_obj["SMask"] = image_ref
|
||||
|
||||
#
|
||||
# image
|
||||
|
||||
|
@ -142,9 +147,6 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
|||
)
|
||||
elif filter == "DCTDecode":
|
||||
Image.SAVE["JPEG"](im, op, filename)
|
||||
elif filter == "JPXDecode":
|
||||
del dict_obj["BitsPerComponent"]
|
||||
Image.SAVE["JPEG2000"](im, op, filename)
|
||||
else:
|
||||
msg = f"unsupported PDF filter ({filter})"
|
||||
raise ValueError(msg)
|
||||
|
@ -236,7 +238,9 @@ def _save(im, fp, filename, save_all=False):
|
|||
number_of_pages += im_number_of_pages
|
||||
for i in range(im_number_of_pages):
|
||||
image_refs.append(existing_pdf.next_object_id(0))
|
||||
if im.mode == "P" and "transparency" in im.info:
|
||||
if im.mode in ("LA", "RGBA") or (
|
||||
im.mode == "P" and "transparency" in im.info
|
||||
):
|
||||
image_refs.append(existing_pdf.next_object_id(0))
|
||||
|
||||
page_refs.append(existing_pdf.next_object_id(0))
|
||||
|
|
Loading…
Reference in New Issue
Block a user