You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@pdfbox.apache.org by "Tilman Hausherr (Jira)" <ji...@apache.org> on 2026/09/09 19:06:00 UTC
[jira] [Assigned] (PDFBOX-5250) Colors in PDF Tile Patterns are off
[ https://issues.apache.org/jira/browse/PDFBOX-5250?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Tilman Hausherr reassigned PDFBOX-5250:
---------------------------------------
Assignee: Tilman Hausherr
> Colors in PDF Tile Patterns are off
> -----------------------------------
>
> Key: PDFBOX-5250
> URL: https://issues.apache.org/jira/browse/PDFBOX-5250
> Project: PDFBox
> Issue Type: Bug
> Components: Rendering
> Affects Versions: 2.0.24
> Reporter: Emmeran Seehuber
> Assignee: Tilman Hausherr
> Priority: Minor
> Attachments: PDFBOX-5250-pattern-reduced2.pdf, PDFBOX-5250-pattern-reduced3.pdf, kachel4.pdf, pattern_colors_broken.pdf
>
>
> I've implementing for my customer some "text with pattern" features. In the attached PDF you see that in action.
> There is a color mapping problem in the patterned text in the left bottom corner in the PDFBox debugger. The colors are way to bright. Acrobat and MacOS Preview render this fine. FoxIt Reader also has some rendering issues with this (image seems distorted...).
> I've also attached the "base" PDF used for the pattern.
> It think the way I embed this should be fine:
> {code:java}
> return new OurPDColorCarrier((PDPageContentStream contentStream) -> {
> PDImageResult pdImage = throwing(() -> textureImage.getPDImageXObject(document, colorSpaceRegistry));
> Objects.requireNonNull(pdImage);
> PDTilingPattern pattern = new PDTilingPattern();
> pattern.setPaintType(PDTilingPattern.PAINT_COLORED);
> pattern.setTilingType(PDTilingPattern.TILING_NO_DISTORTION);
> var anchorInfo = TextRenderer.getTextureTileAnchor(textureImage);
> float textureImageWidth = (float) anchorInfo.originalWidth;
> float textureImageHeight = (float) anchorInfo.originalHeight;
> pattern.setBBox(
> new PDRectangle(0f, 0f, (float) dpi2mm(textureImageWidth), (float) dpi2mm(textureImageHeight)));
> pattern.setXStep((float) anchorInfo.anchor.getWidth());
> pattern.setYStep((float) anchorInfo.anchor.getHeight());
> double scaleFactor = pageWidth / renderTarget.width;
> /* Die Matrix ist lt. Spec für die Phasenverschiebung des Patterns da. */
> double countPhasen = (renderTarget.pageSize.getHeight() / anchorInfo.anchor.getHeight());
> double rest = renderTarget.pageSize.getHeight()
> - DoubleMath.roundToInt(countPhasen, RoundingMode.DOWN) * anchorInfo.anchor.getHeight();
> pattern.setMatrix(AffineTransform.getTranslateInstance(scaleFactor * currentTransform.getTranslateX(),
> renderTarget.pageSize.getHeight() - (scaleFactor * currentTransform.getTranslateY()) + rest));
> PDAppearanceStream appearance = new PDAppearanceStream(document);
> appearance.setResources(pattern.getResources());
> appearance.setBBox(pattern.getBBox());
> PDPageContentStream imageContentStream = new PDPageContentStream(document, appearance,
> ((COSStream) pattern.getCOSObject()).createOutputStream());
> if (pdImage.image instanceof PDFormXObject) {
> imageContentStream.transform(Matrix.getScaleInstance((float) (anchorInfo.originalWidth),
> (float) (anchorInfo.originalHeight)));
> pattern.setBBox(new PDRectangle(0f, 0f, (float) (anchorInfo.originalWidth),
> (float) (anchorInfo.originalHeight)));
> imageContentStream.drawForm((PDFormXObject) pdImage.image);
> } else {
> pattern.setMatrix(AffineTransform.getTranslateInstance(
> scaleFactor * currentTransform.getTranslateX(), renderTarget.pageSize.getHeight()
> - (scaleFactor * currentTransform.getTranslateY()) + rest / scaleFactor));
> imageContentStream.transform(
> Matrix.getScaleInstance((float) (anchorInfo.anchor.getWidth() / textureImageWidth),
> (float) (anchorInfo.anchor.getHeight() / textureImageHeight)));
> imageContentStream.drawImage((PDImageXObject) pdImage.image, 0, 0);
> }
> imageContentStream.close();
> PDResources resources = ModelUtils.getPrivateField(contentStream, "resources");
> COSName tilingPatternName = resources.add(pattern);
> return new PDColor(tilingPatternName, new PDPattern(null));
> });
> {code}
> Yes, in the third bottom line the
> {code:java}
> PDResources resources = ModelUtils.getPrivateField(contentStream, "resources"); {code}
> is an ugly reflection hack - any reason why the ContentStream does not expose its resources with a public API?
> This is with Java 11 on MacOS BigSur.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@pdfbox.apache.org
For additional commands, e-mail: dev-help@pdfbox.apache.org