Как создать PDF-файл с текстом, который нельзя выбрать?

#python #pdf #reportlab #watermark

Вопрос:

Я использую ReportLab для создания PDF-страницы на python. Эта созданная страница содержит одну строку текста. Я хочу, чтобы эта строка стала недоступной для выбора в PDF-файле. Как я могу этого достичь?

Вот пример кода того, как я создаю страницу с помощью одной строки.

 from StringIO import StringIO
from reportlab.pdfgen import canvas
...
buffer = StringIO()
canvas = canvas.Canvas(buffer)
canvas.drawString(30, 30, "Hello world!")
canvas.save()
...
 

В сгенерированном PDF- Hello World! файле он будет выбираться средством просмотра PDF, что нежелательно. Как этого избежать? Я должен выводить строку, которая будет отличаться при каждом запуске программы, поэтому рисование статического изображения не является решением.

Комментарии:

1. Что заставляет вас думать, что это вообще возможно?

2. Возможно, это не так, и это был бы приемлемый ответ. Но почему я должен предполагать, что это невозможно?

Ответ №1:

Как предположил Кей Джей, возможным решением является преобразование строки текста в изображение и визуализация изображения. Недостатком является то, что отображаемый текст имеет ограниченное качество, поскольку он не масштабируется. (SVG нельзя использовать, так как он сохранит строку, и ее можно будет выбрать в формате PDF.)

Вот пример кода того, как выполнить это преобразование с помощью PIL. Предполагается, что текст будет отображаться черным цветом.

 from reportlab.graphics import renderPM
from reportlab.graphics.shape import Drawing, String
from reportlab.lib.utils import ImageReader
from PIL import Image

def drawString(canvas, x, y, string, dpi=72):
    shape = String(0, 0, string)
    s_x, s_y, s_width, s_height = shape.getBounds()
    shape.y -= s_y # correct positioning
    drawing = Drawing(s_width, s_height)
    drawing.add(shape)
    image = drawToPIL(drawing, dpi=dpi)
    # Convert image background to transparent
    image = image.convert("RGBA")
    data = image.getdata()          
    new_data = []
    for item in data:
        tone = item[0]
        new_data.append((0, 0, 0, 255 - tone))
    image.putdata(new_data)
    # render image into canvas
    canvas.drawImage(ImageReader(image), x, y   s_y, 
        width=s_width, height=s_height, mask='auto')
 

(Я должен заметить, что я работаю со старой версией Report Lab, и мне пришлось внести некоторые изменения в библиотеку, чтобы это сработало. Вероятно, мой обходной путь не нужен в более поздних версиях.)