diff --git a/PyPDF2/_writer.py b/PyPDF2/_writer.py index fda42441d..843549ab0 100644 --- a/PyPDF2/_writer.py +++ b/PyPDF2/_writer.py @@ -1066,16 +1066,15 @@ def getNamedDestRoot(self) -> ArrayObject: # pragma: no cover return self.get_named_dest_root() def add_bookmark_destination( - self, dest: PageObject, parent: Optional[TreeObject] = None + self, + dest: Union[PageObject, TreeObject], + parent: Union[None, TreeObject, IndirectObject] = None, ) -> IndirectObject: - dest_ref = self._add_object(dest) - - outline_ref = self.get_outline_root() - if parent is None: - parent = outline_ref + parent = self.get_outline_root() parent = cast(TreeObject, parent.get_object()) + dest_ref = self._add_object(dest) parent.add_child(dest_ref, self) return dest_ref @@ -1107,18 +1106,7 @@ def add_bookmark_dict( action_ref = self._add_object(action) bookmark_obj[NameObject("/A")] = action_ref - bookmark_ref = self._add_object(bookmark_obj) - - outline_ref = self.get_outline_root() - - if parent is None: - parent = outline_ref - - parent = parent.get_object() # type: ignore - assert parent is not None, "hint for mypy" - parent.add_child(bookmark_ref, self) - - return bookmark_ref + return self.add_bookmark_destination(bookmark_obj, parent) def addBookmarkDict( self, bookmark: BookmarkTypes, parent: Optional[TreeObject] = None @@ -1157,39 +1145,26 @@ def add_bookmark( :meth:`addLink()` for details. """ page_ref = NumberObject(pagenum) - action = DictionaryObject() - zoom_args: ZoomArgsType = [] - for a in args: - if a is not None: - zoom_args.append(NumberObject(a)) - else: - zoom_args.append(NullObject()) + zoom_args: ZoomArgsType = [ + NullObject() if a is None else NumberObject(a) for a in args + ] dest = Destination( NameObject("/" + title + " bookmark"), page_ref, NameObject(fit), *zoom_args ) - dest_array = dest.dest_array - action.update( - { - NameObject(GoToActionArguments.D): dest_array, - NameObject(GoToActionArguments.S): NameObject("/GoTo"), - } - ) - action_ref = self._add_object(action) - - outline_ref = self.get_outline_root() - - if parent is None: - parent = outline_ref + action_ref = self._add_object( + DictionaryObject( + { + NameObject(GoToActionArguments.D): dest.dest_array, + NameObject(GoToActionArguments.S): NameObject("/GoTo"), + } + ) + ) bookmark = _create_bookmark(action_ref, title, color, italic, bold) - bookmark_ref = self._add_object(bookmark) - - assert parent is not None, "hint for mypy" - parent_obj = cast(TreeObject, parent.get_object()) - parent_obj.add_child(bookmark_ref, self) - - return bookmark_ref + if parent is None: + parent = self.get_outline_root() + return self.add_bookmark_destination(bookmark, parent) def addBookmark( self, @@ -1567,26 +1542,21 @@ def add_link( else: rect = RectangleObject(rect) - zoom_args: ZoomArgsType = [] - for a in args: - if a is not None: - zoom_args.append(NumberObject(a)) - else: - zoom_args.append(NullObject()) + zoom_args: ZoomArgsType = [ + NullObject() if a is None else NumberObject(a) for a in args + ] dest = Destination( NameObject("/LinkName"), page_dest, NameObject(fit), *zoom_args ) # TODO: create a better name for the link - dest_array = dest.dest_array - lnk = DictionaryObject() - lnk.update( + lnk = DictionaryObject( { NameObject("/Type"): NameObject(PG.ANNOTS), NameObject("/Subtype"): NameObject("/Link"), NameObject("/P"): page_link, NameObject("/Rect"): rect, NameObject("/Border"): ArrayObject(border_arr), - NameObject("/Dest"): dest_array, + NameObject("/Dest"): dest.dest_array, } ) lnk_ref = self._add_object(lnk) diff --git a/docs/user/add-watermark.md b/docs/user/add-watermark.md index a0eabccca..4e852ae07 100644 --- a/docs/user/add-watermark.md +++ b/docs/user/add-watermark.md @@ -10,28 +10,35 @@ content stays the same. ## Stamp (Overlay) ```python -from PyPDF2 import PdfWriter, PdfReader - - -def stamp(content_page, image_page): - """Put the image over the content""" - # Note that this modifies the content_page in-place! - content_page.merge_page(image_page) - return content_page - +from pathlib import Path +from typing import Union, Literal, List -# Read the pages -reader_content = PdfReader("content.pdf") -reader_image = PdfReader("image.pdf") +from PyPDF2 import PdfWriter, PdfReader -# Modify it -modified = stamp(reader_content.pages[0], reader_image.pages[0]) -# Create the new document -writer = PdfWriter() -writer.add_page(modified) -with open("out-stamp.pdf", "wb") as fp: - writer.write(fp) +def stamp( + content_pdf: Path, + stamp_pdf: Path, + pdf_result: Path, + page_indices: Union[Literal["ALL"], List[int]] = "ALL", +): + reader = PdfReader(stamp_pdf) + image_page = reader.pages[0] + + writer = PdfWriter() + + reader = PdfReader(content_pdf) + if page_indices == "ALL": + page_indices = list(range(0, len(reader.pages))) + for index in page_indices: + content_page = reader.pages[index] + mediabox = content_page.mediabox + content_page.merge_page(image_page) + content_page.mediabox = mediabox + writer.add_page(content_page) + + with open(pdf_result, "wb") as fp: + writer.write(fp) ``` ![stamp.png](stamp.png) @@ -39,28 +46,40 @@ with open("out-stamp.pdf", "wb") as fp: ## Watermark (Underlay) ```python +from pathlib import Path +from typing import Union, Literal, List + from PyPDF2 import PdfWriter, PdfReader -def watermark(content_page, image_page): - """Put the image under the content""" - # Note that this modifies the image_page in-place! - image_page.merge_page(content_page) - return image_page +def watermark( + content_pdf: Path, + stamp_pdf: Path, + pdf_result: Path, + page_indices: Union[Literal["ALL"], List[int]] = "ALL", +): + reader = PdfReader(content_pdf) + if page_indices == "ALL": + page_indices = list(range(0, len(reader.pages))) + + reader_stamp = PdfReader(stamp_pdf) + image_page = reader_stamp.pages[0] + writer = PdfWriter() + for index in page_indices: + content_page = reader.pages[index] + mediabox = content_page.mediabox -# Read the pages -reader_content = PdfReader("content.pdf") -reader_image = PdfReader("image.pdf") + # You need to load it again, as the last time it was overwritten + reader_stamp = PdfReader(stamp_pdf) + image_page = reader_stamp.pages[0] -# Modify it -modified = stamp(reader_content.pages[0], reader_image.pages[0]) + image_page.merge_page(content_page) + image_page.mediabox = mediabox + writer.add_page(image_page) -# Create the new document -writer = PdfWriter() -writer.add_page(modified) -with open("out-watermark.pdf", "wb") as fp: - writer.write(fp) + with open(pdf_result, "wb") as fp: + writer.write(fp) ``` ![watermark.png](watermark.png)