Compare commits
4 commits
3b117e674b
...
fb4b96452a
Author | SHA1 | Date | |
---|---|---|---|
fb4b96452a | |||
c553e169a4 | |||
d9345ac767 | |||
1d52530229 |
1 changed files with 68 additions and 23 deletions
|
@ -22,7 +22,17 @@ import sys
|
|||
import os
|
||||
import zlib
|
||||
import argparse
|
||||
from PIL import Image, TiffImagePlugin
|
||||
from PIL import Image, TiffImagePlugin, GifImagePlugin
|
||||
|
||||
if hasattr(GifImagePlugin, "LoadingStrategy"):
|
||||
# Pillow 9.0.0 started emitting all frames but the first as RGB instead of
|
||||
# P to make sure that more than 256 colors can be represented. But palette
|
||||
# images compress far better than RGB images in PDF so we instruct Pillow
|
||||
# to only emit RGB frames if the palette differs and return P otherwise.
|
||||
# This works since Pillow 9.1.0.
|
||||
GifImagePlugin.LOADING_STRATEGY = (
|
||||
GifImagePlugin.LoadingStrategy.RGB_AFTER_DIFFERENT_PALETTE_ONLY
|
||||
)
|
||||
|
||||
# TiffImagePlugin.DEBUG = True
|
||||
from PIL.ExifTags import TAGS
|
||||
|
@ -91,7 +101,10 @@ ImageFormat = Enum("ImageFormat", "JPEG JPEG2000 CCITTGroup4 PNG GIF TIFF MPO ot
|
|||
|
||||
PageMode = Enum("PageMode", "none outlines thumbs")
|
||||
|
||||
PageLayout = Enum("PageLayout", "single onecolumn twocolumnright twocolumnleft twopageright twopageleft")
|
||||
PageLayout = Enum(
|
||||
"PageLayout",
|
||||
"single onecolumn twocolumnright twocolumnleft twopageright twopageleft",
|
||||
)
|
||||
|
||||
Magnification = Enum("Magnification", "fit fith fitbh")
|
||||
|
||||
|
@ -389,6 +402,28 @@ class ExifOrientationError(Exception):
|
|||
pass
|
||||
|
||||
|
||||
# temporary change the attribute of an object using a context manager
|
||||
class temp_attr:
|
||||
def __init__(self, obj, field, value):
|
||||
self.obj = obj
|
||||
self.field = field
|
||||
self.value = value
|
||||
|
||||
def __enter__(self):
|
||||
self.exists = False
|
||||
if hasattr(self.obj, self.field):
|
||||
self.exists = True
|
||||
self.old_value = getattr(self.obj, self.field)
|
||||
print(f"setting {self.obj}.{self.field} = {self.value}")
|
||||
setattr(self.obj, self.field, self.value)
|
||||
|
||||
def __exit__(self, exctype, excinst, exctb):
|
||||
if self.exists:
|
||||
setattr(self.obj, self.field, self.old_value)
|
||||
else:
|
||||
delattr(self.obj, self.field)
|
||||
|
||||
|
||||
# without pdfrw this function is a no-op
|
||||
def my_convert_load(string):
|
||||
return string
|
||||
|
@ -1106,8 +1141,16 @@ class pdfdoc(object):
|
|||
[initial_page, PdfName.XYZ, NullObject, NullObject, 0]
|
||||
)
|
||||
|
||||
# the /OpenAction array must contain the page as an indirect object
|
||||
# The /OpenAction array must contain the page as an indirect object.
|
||||
# This changed some time after 4.2.0 and on or before 5.0.0 and current
|
||||
# versions require to use .obj or otherwise we get:
|
||||
# TypeError: Can't convert ObjectHelper (or subclass) to Object
|
||||
# implicitly. Use .obj to get access the underlying object.
|
||||
# See https://github.com/pikepdf/pikepdf/issues/313 for details.
|
||||
if self.engine == Engine.pikepdf:
|
||||
if isinstance(initial_page, pikepdf.Page):
|
||||
initial_page = self.writer.make_indirect(initial_page.obj)
|
||||
else:
|
||||
initial_page = self.writer.make_indirect(initial_page)
|
||||
|
||||
if self.magnification == Magnification.fit:
|
||||
|
@ -1410,27 +1453,29 @@ def transcode_monochrome(imgdata):
|
|||
# into putting everything into a single strip. Thanks to Andrew Murray for
|
||||
# the hack.
|
||||
#
|
||||
# This can be dropped once this gets merged:
|
||||
# https://github.com/python-pillow/Pillow/pull/5744
|
||||
# Since version 8.4.0 Pillow allows us to modify the strip size explicitly
|
||||
tmp_strip_size = (imgdata.size[0] + 7) // 8 * imgdata.size[1]
|
||||
if hasattr(TiffImagePlugin, "STRIP_SIZE"):
|
||||
# we are using Pillow 8.4.0 or later
|
||||
with temp_attr(TiffImagePlugin, "STRIP_SIZE", tmp_strip_size):
|
||||
im.save(newimgio, format="TIFF", compression="group4")
|
||||
else:
|
||||
# only needed for Pillow 8.3.x but works for versions before that as
|
||||
# well
|
||||
pillow__getitem__ = TiffImagePlugin.ImageFileDirectory_v2.__getitem__
|
||||
|
||||
def __getitem__(self, tag):
|
||||
overrides = {
|
||||
TiffImagePlugin.ROWSPERSTRIP: imgdata.size[1],
|
||||
TiffImagePlugin.STRIPBYTECOUNTS: [
|
||||
(imgdata.size[0] + 7) // 8 * imgdata.size[1]
|
||||
],
|
||||
TiffImagePlugin.STRIPBYTECOUNTS: [tmp_strip_size],
|
||||
TiffImagePlugin.STRIPOFFSETS: [0],
|
||||
}
|
||||
return overrides.get(tag, pillow__getitem__(self, tag))
|
||||
|
||||
# use try/finally to make sure that __getitem__ is reset even if save()
|
||||
# raises an exception
|
||||
try:
|
||||
TiffImagePlugin.ImageFileDirectory_v2.__getitem__ = __getitem__
|
||||
with temp_attr(
|
||||
TiffImagePlugin.ImageFileDirectory_v2, "__getitem__", __getitem__
|
||||
):
|
||||
im.save(newimgio, format="TIFF", compression="group4")
|
||||
finally:
|
||||
TiffImagePlugin.ImageFileDirectory_v2.__getitem__ = pillow__getitem__
|
||||
|
||||
# Open new image in memory
|
||||
newimgio.seek(0)
|
||||
|
|
Loading…
Reference in a new issue