Home > Net >  Change color of rectangle link contourn created with PyPDF2
Change color of rectangle link contourn created with PyPDF2

Time:10-08

I want to change the color of the rectangle contourn created with addLink command of PyPDF2 from black to blue but I can't find documentation about it and I couldn't find any solution yet.

from PyPDF2 import PdfFileWriter
from pathlib import Path


output = PdfFileWriter()
output.addBlankPage(width=72, height=72) #page 1 with index 0
output.addBlankPage(width=72, height=72) #page 2 with index 1
output.addLink(0, 1, [10, 10, 50, 30], border=[0, 0, 1])

with Path("link_example.pdf").open(mode="wb") as output_file:
    output.write(output_file)

The only information I got is the self-explanation of the comments: "border: if provided, an array describing border-drawing properties. See the PDF spec for details. No border will be drawn if this argument is omitted."

CodePudding user response:

After a lot of research, I figured out that it is not possible to change the color of the contourn using the original PyPDF2 code. For this reason I've modified it a little bit in order to allow an additional parameter for color in RGB.

I've changed the function addLink of file pdf.py that is inside ..PythonXX/Lib/PyPDF2 to include the parameter color

def addLink(self, pagenum, pagedest, rect, border=None, color=None, fit='/Fit', *args):
    """
    Add an internal link from a rectangular area to the specified page.

    :param int pagenum: index of the page on which to place the link.
    :param int pagedest: index of the page to which the link should go.
    :param rect: :class:`RectangleObject<PyPDF2.generic.RectangleObject>` or array of four
        integers specifying the clickable rectangular area
        ``[xLL, yLL, xUR, yUR]``, or string in the form ``"[ xLL yLL xUR yUR ]"``.
    :param border: if provided, an array describing border-drawing
        properties. See the PDF spec for details. No border will be
        drawn if this argument is omitted.
    :param color: if provided, an array describing border-color
        RGB. See the PDF spec for details. Black if this argument is omitted.
    :param str fit: Page fit or 'zoom' option (see below). Additional arguments may need
        to be supplied. Passing ``None`` will be read as a null value for that coordinate.

    Valid zoom arguments (see Table 8.2 of the PDF 1.7 reference for details):
         /Fit       No additional arguments
         /XYZ       [left] [top] [zoomFactor]
         /FitH      [top]
         /FitV      [left]
         /FitR      [left] [bottom] [right] [top]
         /FitB      No additional arguments
         /FitBH     [top]
         /FitBV     [left]
    """

    pageLink = self.getObject(self._pages)['/Kids'][pagenum]
    pageDest = self.getObject(self._pages)['/Kids'][pagedest]  # TODO: switch for external link
    pageRef = self.getObject(pageLink)

    if border is not None:
        borderArr = [NameObject(n) for n in border[:3]]
        if len(border) == 4:
            dashPattern = ArrayObject([NameObject(n) for n in border[3]])
            borderArr.append(dashPattern)
    else:
        borderArr = [NumberObject(0)] * 3

    if color is not None:
        colorArr = [NameObject(n) for n in color[:3]]
    else:
        colorArr = [NumberObject(0)] * 3

    if isString(rect):
        rect = NameObject(rect)
    elif isinstance(rect, RectangleObject):
        pass
    else:
        rect = RectangleObject(rect)

    zoomArgs = []
    for a in args:
        if a is not None:
            zoomArgs.append(NumberObject(a))
        else:
            zoomArgs.append(NullObject())
    dest = Destination(NameObject("/LinkName"), pageDest, NameObject(fit),
                       *zoomArgs)  # TODO: create a better name for the link
    destArray = dest.getDestArray()

    lnk = DictionaryObject()
    lnk.update({
        NameObject('/Type'): NameObject('/Annot'),
        NameObject('/Subtype'): NameObject('/Link'),
        NameObject('/P'): pageLink,
        NameObject('/Rect'): rect,
        NameObject('/Border'): ArrayObject(borderArr),
        NameObject('/C'): ArrayObject(colorArr),
        NameObject('/Dest'): destArray
    })
    lnkRef = self._addObject(lnk)

    if "/Annots" in pageRef:
        pageRef['/Annots'].append(lnkRef)
    else:
        pageRef[NameObject('/Annots')] = ArrayObject([lnkRef])

_valid_layouts = ['/NoLayout', '/SinglePage', '/OneColumn', '/TwoColumnLeft', '/TwoColumnRight', '/TwoPageLeft',
                  '/TwoPageRight']

And now I can get a blue contourn just including the new parameter in the function:

from PyPDF2 import PdfFileWriter
from pathlib import Path


output = PdfFileWriter()
output.addBlankPage(width=72, height=72) #page 1 with index 0
output.addBlankPage(width=72, height=72) #page 2 with index 1
output.addLink(0, 1, [10, 10, 50, 30], border=[0, 0, 1], color=[0, 0, 1])

with Path("link_example.pdf").open(mode="wb") as output_file:
    output.write(output_file)
  • Related