Save 1 mode PDF using CCITTFaxDecode filter

This commit is contained in:
Andrew Murray 2022-08-01 20:38:47 +10:00
parent 7e7a48479b
commit f5b27f90f7
2 changed files with 36 additions and 10 deletions

View File

@ -43,7 +43,7 @@ def test_monochrome(tmp_path):
# Act / Assert # Act / Assert
outfile = helper_save_as_pdf(tmp_path, mode) outfile = helper_save_as_pdf(tmp_path, mode)
assert os.path.getsize(outfile) < 15000 assert os.path.getsize(outfile) < 5000
def test_greyscale(tmp_path): def test_greyscale(tmp_path):

View File

@ -21,10 +21,11 @@
## ##
import io import io
import math
import os import os
import time import time
from . import Image, ImageFile, ImageSequence, PdfParser, __version__ from . import Image, ImageFile, ImageSequence, PdfParser, TiffImagePlugin, __version__
# #
# -------------------------------------------------------------------- # --------------------------------------------------------------------
@ -123,8 +124,26 @@ def _save(im, fp, filename, save_all=False):
params = None params = None
decode = None decode = None
#
# Get image characteristics
width, height = im.size
if im.mode == "1": if im.mode == "1":
filter = "DCTDecode" filter = "CCITTFaxDecode"
bits = 1
params = PdfParser.PdfArray(
[
PdfParser.PdfDict(
{
"K": -1,
"BlackIs1": True,
"Columns": width,
"Rows": height,
}
)
]
)
colorspace = PdfParser.PdfName("DeviceGray") colorspace = PdfParser.PdfName("DeviceGray")
procset = "ImageB" # grayscale procset = "ImageB" # grayscale
elif im.mode == "L": elif im.mode == "L":
@ -161,6 +180,11 @@ def _save(im, fp, filename, save_all=False):
if filter == "ASCIIHexDecode": if filter == "ASCIIHexDecode":
ImageFile._save(im, op, [("hex", (0, 0) + im.size, 0, im.mode)]) ImageFile._save(im, op, [("hex", (0, 0) + im.size, 0, im.mode)])
elif filter == "CCITTFaxDecode":
original_strip_size = TiffImagePlugin.STRIP_SIZE
TiffImagePlugin.STRIP_SIZE = math.ceil(im.width / 8) * im.height
im.save(op, "TIFF", compression="group4")
TiffImagePlugin.STRIP_SIZE = original_strip_size
elif filter == "DCTDecode": elif filter == "DCTDecode":
Image.SAVE["JPEG"](im, op, filename) Image.SAVE["JPEG"](im, op, filename)
elif filter == "FlateDecode": elif filter == "FlateDecode":
@ -170,22 +194,24 @@ def _save(im, fp, filename, save_all=False):
else: else:
raise ValueError(f"unsupported PDF filter ({filter})") raise ValueError(f"unsupported PDF filter ({filter})")
# stream = op.getvalue()
# Get image characteristics if filter == "CCITTFaxDecode":
stream = stream[8:]
width, height = im.size filter = PdfParser.PdfArray([PdfParser.PdfName(filter)])
else:
filter = PdfParser.PdfName(filter)
existing_pdf.write_obj( existing_pdf.write_obj(
image_refs[page_number], image_refs[page_number],
stream=op.getvalue(), stream=stream,
Type=PdfParser.PdfName("XObject"), Type=PdfParser.PdfName("XObject"),
Subtype=PdfParser.PdfName("Image"), Subtype=PdfParser.PdfName("Image"),
Width=width, # * 72.0 / resolution, Width=width, # * 72.0 / resolution,
Height=height, # * 72.0 / resolution, Height=height, # * 72.0 / resolution,
Filter=PdfParser.PdfName(filter), Filter=filter,
BitsPerComponent=bits, BitsPerComponent=bits,
Decode=decode, Decode=decode,
DecodeParams=params, DecodeParms=params,
ColorSpace=colorspace, ColorSpace=colorspace,
) )