mirror of
https://github.com/python-pillow/Pillow.git
synced 2025-07-12 01:02:39 +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 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:
|
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
|
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:
|
def test_save(tmp_path: Path, mode: str) -> None:
|
||||||
helper_save_as_pdf(tmp_path, mode)
|
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:
|
def test_p_alpha(tmp_path: Path) -> None:
|
||||||
# Arrange
|
# Arrange
|
||||||
outfile = str(tmp_path / "temp.pdf")
|
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
|
* 1 mode images are saved using TIFF encoding, or JPEG encoding if libtiff support is
|
||||||
unavailable
|
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
|
* P mode images use HEX encoding
|
||||||
* LA and RGBA mode images use JPEG2000 encoding
|
|
||||||
|
|
||||||
.. _pdf-saving:
|
.. _pdf-saving:
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
||||||
|
|
||||||
params = None
|
params = None
|
||||||
decode = None
|
decode = None
|
||||||
|
smask = None
|
||||||
|
|
||||||
#
|
#
|
||||||
# Get image characteristics
|
# Get image characteristics
|
||||||
|
@ -81,16 +82,16 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
||||||
filter = "DCTDecode"
|
filter = "DCTDecode"
|
||||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
||||||
procset = "ImageB" # grayscale
|
procset = "ImageB" # grayscale
|
||||||
elif im.mode == "L":
|
elif im.mode in ("L", "LA"):
|
||||||
filter = "DCTDecode"
|
filter = "DCTDecode"
|
||||||
# params = f"<< /Predictor 15 /Columns {width-2} >>"
|
# params = f"<< /Predictor 15 /Columns {width-2} >>"
|
||||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
|
||||||
procset = "ImageB" # grayscale
|
procset = "ImageB" # grayscale
|
||||||
elif im.mode == "LA":
|
if im.mode == "LA":
|
||||||
filter = "JPXDecode"
|
smask = im
|
||||||
# params = f"<< /Predictor 15 /Columns {width-2} >>"
|
|
||||||
procset = "ImageB" # grayscale
|
im = im.convert("L")
|
||||||
dict_obj["SMaskInData"] = 1
|
im.encoderinfo = {}
|
||||||
elif im.mode == "P":
|
elif im.mode == "P":
|
||||||
filter = "ASCIIHexDecode"
|
filter = "ASCIIHexDecode"
|
||||||
palette = im.getpalette()
|
palette = im.getpalette()
|
||||||
|
@ -103,19 +104,16 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
||||||
procset = "ImageI" # indexed color
|
procset = "ImageI" # indexed color
|
||||||
|
|
||||||
if "transparency" in im.info:
|
if "transparency" in im.info:
|
||||||
smask = im.convert("LA").getchannel("A")
|
smask = im.convert("LA")
|
||||||
smask.encoderinfo = {}
|
elif im.mode in ("RGB", "RGBA"):
|
||||||
|
|
||||||
image_ref = _write_image(smask, filename, existing_pdf, image_refs)[0]
|
|
||||||
dict_obj["SMask"] = image_ref
|
|
||||||
elif im.mode == "RGB":
|
|
||||||
filter = "DCTDecode"
|
filter = "DCTDecode"
|
||||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceRGB")
|
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceRGB")
|
||||||
procset = "ImageC" # color images
|
procset = "ImageC" # color images
|
||||||
elif im.mode == "RGBA":
|
if im.mode == "RGBA":
|
||||||
filter = "JPXDecode"
|
smask = im
|
||||||
procset = "ImageC" # color images
|
|
||||||
dict_obj["SMaskInData"] = 1
|
im = im.convert("RGB")
|
||||||
|
im.encoderinfo = {}
|
||||||
elif im.mode == "CMYK":
|
elif im.mode == "CMYK":
|
||||||
filter = "DCTDecode"
|
filter = "DCTDecode"
|
||||||
dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceCMYK")
|
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}"
|
msg = f"cannot save mode {im.mode}"
|
||||||
raise ValueError(msg)
|
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
|
# image
|
||||||
|
|
||||||
|
@ -142,9 +147,6 @@ def _write_image(im, filename, existing_pdf, image_refs):
|
||||||
)
|
)
|
||||||
elif filter == "DCTDecode":
|
elif filter == "DCTDecode":
|
||||||
Image.SAVE["JPEG"](im, op, filename)
|
Image.SAVE["JPEG"](im, op, filename)
|
||||||
elif filter == "JPXDecode":
|
|
||||||
del dict_obj["BitsPerComponent"]
|
|
||||||
Image.SAVE["JPEG2000"](im, op, filename)
|
|
||||||
else:
|
else:
|
||||||
msg = f"unsupported PDF filter ({filter})"
|
msg = f"unsupported PDF filter ({filter})"
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
|
@ -236,7 +238,9 @@ def _save(im, fp, filename, save_all=False):
|
||||||
number_of_pages += im_number_of_pages
|
number_of_pages += im_number_of_pages
|
||||||
for i in range(im_number_of_pages):
|
for i in range(im_number_of_pages):
|
||||||
image_refs.append(existing_pdf.next_object_id(0))
|
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))
|
image_refs.append(existing_pdf.next_object_id(0))
|
||||||
|
|
||||||
page_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