Создание группы прозрачности или настройка мягкой маски графического состояния с помощью PDFBox - PullRequest
1 голос
/ 13 февраля 2020

У меня есть изображение в градациях серого, которое служит мягкой маской, и я хочу использовать его для группы объектов PDF (изображений или контуров).

Маска и объекты не обязательно используют одну и ту же матрицу преобразования, и может быть несколько маскируемых объектов, что исключает возможность использования атрибута SMask словаря ImageXObject.

Итак, после прочтения некоторых спецификаций PDF, я должен сделать следующее: создать группу прозрачности с объектами для маскировки, а затем нарисовать ее с помощью мягкой маски, установленной в графическом состоянии.

Будет ли это работать? Как мне этого добиться, желательно с PDFBox?


Вот пример. У меня есть эти два изображения: маска и другое изображение.

mask image

  • Изображение маски - 200x200. Он нарисован с помощью матрицы [[4 0 100] [0 4 100]].
  • Изображение 400х300. Он рисуется с матрицей [[2 0 100] [0 2 150]].
  • Кроме того, черный квадрат 400x400 рисуется под изображением без матрицы преобразования.

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

result

Довольно уродливо, насколько эффект идет, но это только пример.

1 Ответ

2 голосов
/ 17 февраля 2020

Насколько я вижу, создание расширенной графической программной маски состояния - очень ручная задача в PDFBox. Вы можете сделать это следующим образом:

try (   PDDocument document = new PDDocument()  ) {
    final PDImageXObject image = RETRIEVE PHOTO IMAGE;
    final PDImageXObject mask = RETRIEVE MASK IMAGE;

    PDTransparencyGroupAttributes transparencyGroupAttributes = new PDTransparencyGroupAttributes();
    transparencyGroupAttributes.getCOSObject().setItem(COSName.CS, COSName.DEVICEGRAY);

    PDTransparencyGroup transparencyGroup = new PDTransparencyGroup(document);
    transparencyGroup.setBBox(PDRectangle.A4);
    transparencyGroup.setResources(new PDResources());
    transparencyGroup.getCOSObject().setItem(COSName.GROUP, transparencyGroupAttributes);
    try (   PDFormContentStream canvas = new PDFormContentStream(transparencyGroup)   ) {
        canvas.drawImage(mask, new Matrix(400, 0, 0, 400, 100, 100));
    }

    COSDictionary softMaskDictionary = new COSDictionary();
    softMaskDictionary.setItem(COSName.S, COSName.LUMINOSITY);
    softMaskDictionary.setItem(COSName.G, transparencyGroup);

    PDExtendedGraphicsState extendedGraphicsState = new PDExtendedGraphicsState();
    extendedGraphicsState.getCOSObject().setItem(COSName.SMASK, softMaskDictionary);

    PDPage page = new PDPage(PDRectangle.A4);
    document.addPage(page);
    try (   PDPageContentStream canvas = new PDPageContentStream(document, page)   ) {
        canvas.saveGraphicsState();
        canvas.setGraphicsStateParameters(extendedGraphicsState);
        canvas.setNonStrokingColor(Color.BLACK);
        canvas.addRect(100, 100, 400, 400);
        canvas.fill();
        canvas.drawImage(image, new Matrix(400, 0, 0, 300, 100, 150));
        canvas.restoreGraphicsState();
    }

    document.save(new File(RESULT_FOLDER, "SoftMaskedImageAndRectangle.pdf"));
}

Результат:

screen shot

На вашем месте я бы не стал используйте растровое изображение для мягкой маски, но вместо этого градиент PDF. Скорее всего, результат будет гораздо менее точечным.

...