aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/PIL/PdfImagePlugin.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/PIL/PdfImagePlugin.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are hereHEADmaster
Diffstat (limited to '.venv/lib/python3.12/site-packages/PIL/PdfImagePlugin.py')
-rw-r--r--.venv/lib/python3.12/site-packages/PIL/PdfImagePlugin.py311
1 files changed, 311 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/PIL/PdfImagePlugin.py b/.venv/lib/python3.12/site-packages/PIL/PdfImagePlugin.py
new file mode 100644
index 00000000..e9c20ddc
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/PIL/PdfImagePlugin.py
@@ -0,0 +1,311 @@
+#
+# The Python Imaging Library.
+# $Id$
+#
+# PDF (Acrobat) file handling
+#
+# History:
+# 1996-07-16 fl Created
+# 1997-01-18 fl Fixed header
+# 2004-02-21 fl Fixes for 1/L/CMYK images, etc.
+# 2004-02-24 fl Fixes for 1 and P images.
+#
+# Copyright (c) 1997-2004 by Secret Labs AB. All rights reserved.
+# Copyright (c) 1996-1997 by Fredrik Lundh.
+#
+# See the README file for information on usage and redistribution.
+#
+
+##
+# Image plugin for PDF images (output only).
+##
+from __future__ import annotations
+
+import io
+import math
+import os
+import time
+from typing import IO, Any
+
+from . import Image, ImageFile, ImageSequence, PdfParser, __version__, features
+
+#
+# --------------------------------------------------------------------
+
+# object ids:
+# 1. catalogue
+# 2. pages
+# 3. image
+# 4. page
+# 5. page contents
+
+
+def _save_all(im: Image.Image, fp: IO[bytes], filename: str | bytes) -> None:
+ _save(im, fp, filename, save_all=True)
+
+
+##
+# (Internal) Image save plugin for the PDF format.
+
+
+def _write_image(
+ im: Image.Image,
+ filename: str | bytes,
+ existing_pdf: PdfParser.PdfParser,
+ image_refs: list[PdfParser.IndirectReference],
+) -> tuple[PdfParser.IndirectReference, str]:
+ # FIXME: Should replace ASCIIHexDecode with RunLengthDecode
+ # (packbits) or LZWDecode (tiff/lzw compression). Note that
+ # PDF 1.2 also supports Flatedecode (zip compression).
+
+ params = None
+ decode = None
+
+ #
+ # Get image characteristics
+
+ width, height = im.size
+
+ dict_obj: dict[str, Any] = {"BitsPerComponent": 8}
+ if im.mode == "1":
+ if features.check("libtiff"):
+ decode_filter = "CCITTFaxDecode"
+ dict_obj["BitsPerComponent"] = 1
+ params = PdfParser.PdfArray(
+ [
+ PdfParser.PdfDict(
+ {
+ "K": -1,
+ "BlackIs1": True,
+ "Columns": width,
+ "Rows": height,
+ }
+ )
+ ]
+ )
+ else:
+ decode_filter = "DCTDecode"
+ dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
+ procset = "ImageB" # grayscale
+ elif im.mode == "L":
+ decode_filter = "DCTDecode"
+ # params = f"<< /Predictor 15 /Columns {width-2} >>"
+ dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceGray")
+ procset = "ImageB" # grayscale
+ elif im.mode == "LA":
+ decode_filter = "JPXDecode"
+ # params = f"<< /Predictor 15 /Columns {width-2} >>"
+ procset = "ImageB" # grayscale
+ dict_obj["SMaskInData"] = 1
+ elif im.mode == "P":
+ decode_filter = "ASCIIHexDecode"
+ palette = im.getpalette()
+ assert palette is not None
+ dict_obj["ColorSpace"] = [
+ PdfParser.PdfName("Indexed"),
+ PdfParser.PdfName("DeviceRGB"),
+ len(palette) // 3 - 1,
+ PdfParser.PdfBinary(palette),
+ ]
+ 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":
+ decode_filter = "DCTDecode"
+ dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceRGB")
+ procset = "ImageC" # color images
+ elif im.mode == "RGBA":
+ decode_filter = "JPXDecode"
+ procset = "ImageC" # color images
+ dict_obj["SMaskInData"] = 1
+ elif im.mode == "CMYK":
+ decode_filter = "DCTDecode"
+ dict_obj["ColorSpace"] = PdfParser.PdfName("DeviceCMYK")
+ procset = "ImageC" # color images
+ decode = [1, 0, 1, 0, 1, 0, 1, 0]
+ else:
+ msg = f"cannot save mode {im.mode}"
+ raise ValueError(msg)
+
+ #
+ # image
+
+ op = io.BytesIO()
+
+ if decode_filter == "ASCIIHexDecode":
+ ImageFile._save(im, op, [ImageFile._Tile("hex", (0, 0) + im.size, 0, im.mode)])
+ elif decode_filter == "CCITTFaxDecode":
+ im.save(
+ op,
+ "TIFF",
+ compression="group4",
+ # use a single strip
+ strip_size=math.ceil(width / 8) * height,
+ )
+ elif decode_filter == "DCTDecode":
+ Image.SAVE["JPEG"](im, op, filename)
+ elif decode_filter == "JPXDecode":
+ del dict_obj["BitsPerComponent"]
+ Image.SAVE["JPEG2000"](im, op, filename)
+ else:
+ msg = f"unsupported PDF filter ({decode_filter})"
+ raise ValueError(msg)
+
+ stream = op.getvalue()
+ filter: PdfParser.PdfArray | PdfParser.PdfName
+ if decode_filter == "CCITTFaxDecode":
+ stream = stream[8:]
+ filter = PdfParser.PdfArray([PdfParser.PdfName(decode_filter)])
+ else:
+ filter = PdfParser.PdfName(decode_filter)
+
+ image_ref = image_refs.pop(0)
+ existing_pdf.write_obj(
+ image_ref,
+ stream=stream,
+ Type=PdfParser.PdfName("XObject"),
+ Subtype=PdfParser.PdfName("Image"),
+ Width=width, # * 72.0 / x_resolution,
+ Height=height, # * 72.0 / y_resolution,
+ Filter=filter,
+ Decode=decode,
+ DecodeParms=params,
+ **dict_obj,
+ )
+
+ return image_ref, procset
+
+
+def _save(
+ im: Image.Image, fp: IO[bytes], filename: str | bytes, save_all: bool = False
+) -> None:
+ is_appending = im.encoderinfo.get("append", False)
+ filename_str = filename.decode() if isinstance(filename, bytes) else filename
+ if is_appending:
+ existing_pdf = PdfParser.PdfParser(f=fp, filename=filename_str, mode="r+b")
+ else:
+ existing_pdf = PdfParser.PdfParser(f=fp, filename=filename_str, mode="w+b")
+
+ dpi = im.encoderinfo.get("dpi")
+ if dpi:
+ x_resolution = dpi[0]
+ y_resolution = dpi[1]
+ else:
+ x_resolution = y_resolution = im.encoderinfo.get("resolution", 72.0)
+
+ info = {
+ "title": (
+ None if is_appending else os.path.splitext(os.path.basename(filename))[0]
+ ),
+ "author": None,
+ "subject": None,
+ "keywords": None,
+ "creator": None,
+ "producer": None,
+ "creationDate": None if is_appending else time.gmtime(),
+ "modDate": None if is_appending else time.gmtime(),
+ }
+ for k, default in info.items():
+ v = im.encoderinfo.get(k) if k in im.encoderinfo else default
+ if v:
+ existing_pdf.info[k[0].upper() + k[1:]] = v
+
+ #
+ # make sure image data is available
+ im.load()
+
+ existing_pdf.start_writing()
+ existing_pdf.write_header()
+ existing_pdf.write_comment(f"created by Pillow {__version__} PDF driver")
+
+ #
+ # pages
+ ims = [im]
+ if save_all:
+ append_images = im.encoderinfo.get("append_images", [])
+ for append_im in append_images:
+ append_im.encoderinfo = im.encoderinfo.copy()
+ ims.append(append_im)
+ number_of_pages = 0
+ image_refs = []
+ page_refs = []
+ contents_refs = []
+ for im in ims:
+ im_number_of_pages = 1
+ if save_all:
+ im_number_of_pages = getattr(im, "n_frames", 1)
+ 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:
+ image_refs.append(existing_pdf.next_object_id(0))
+
+ page_refs.append(existing_pdf.next_object_id(0))
+ contents_refs.append(existing_pdf.next_object_id(0))
+ existing_pdf.pages.append(page_refs[-1])
+
+ #
+ # catalog and list of pages
+ existing_pdf.write_catalog()
+
+ page_number = 0
+ for im_sequence in ims:
+ im_pages: ImageSequence.Iterator | list[Image.Image] = (
+ ImageSequence.Iterator(im_sequence) if save_all else [im_sequence]
+ )
+ for im in im_pages:
+ image_ref, procset = _write_image(im, filename, existing_pdf, image_refs)
+
+ #
+ # page
+
+ existing_pdf.write_page(
+ page_refs[page_number],
+ Resources=PdfParser.PdfDict(
+ ProcSet=[PdfParser.PdfName("PDF"), PdfParser.PdfName(procset)],
+ XObject=PdfParser.PdfDict(image=image_ref),
+ ),
+ MediaBox=[
+ 0,
+ 0,
+ im.width * 72.0 / x_resolution,
+ im.height * 72.0 / y_resolution,
+ ],
+ Contents=contents_refs[page_number],
+ )
+
+ #
+ # page contents
+
+ page_contents = b"q %f 0 0 %f 0 0 cm /image Do Q\n" % (
+ im.width * 72.0 / x_resolution,
+ im.height * 72.0 / y_resolution,
+ )
+
+ existing_pdf.write_obj(contents_refs[page_number], stream=page_contents)
+
+ page_number += 1
+
+ #
+ # trailer
+ existing_pdf.write_xref_and_trailer()
+ if hasattr(fp, "flush"):
+ fp.flush()
+ existing_pdf.close()
+
+
+#
+# --------------------------------------------------------------------
+
+
+Image.register_save("PDF", _save)
+Image.register_save_all("PDF", _save_all)
+
+Image.register_extension("PDF", ".pdf")
+
+Image.register_mime("PDF", "application/pdf")