当前位置: 首页 > 知识库问答 >
问题:

使用PDFBox在PDF上绘制矢量图像

宗烨赫
2023-03-14

我想用ApachePDFBox在PDF上绘制一个矢量图像。

这是我用来绘制普通图像的代码

PDPage page = (PDPage) document.getDocumentCatalog().getAllPages().get(1);
PDPageContentStream contentStream = new PDPageContentStream(document, page, true, true);

BufferedImage _prevImage = ImageIO.read(new FileInputStream("path/to/image.png"));
PDPixelMap prevImage = new PDPixelMap(document, _prevImage);
contentStream.drawXObject(prevImage, prevX, prevY, imageWidth, imageHeight);

如果我使用svgwmf图像而不是png,则生成的PDF文档会损坏。

我希望图像是矢量图像的主要原因是,使用PNG或JPG时,图像看起来很糟糕,我认为它会被压缩,所以看起来很糟糕。对于矢量图像,这不应该发生(当我在Inkscape中将svg路径导出为PDF时,它不会发生,矢量路径会被保留)。

有没有办法使用Apache PDFBox将svg或wmf(或其他向量)绘制到PDF?

我目前正在使用PDFBox 1.8,如果这很重要的话。

共有3个答案

濮阳茂材
2023-03-14

对我来说,加载一个SVG文件并将其覆盖在一个PDF文件上的最终工作解决方案(这将SVG呈现在一个500x500框中,位于PDF文档左下角的(0,0)坐标处):

package com.example.svgadder;

import java.io.*;
import java.nio.*;

import org.apache.pdfbox.pdmodel.*;
import org.apache.pdfbox.pdmodel.PDPageContentStream.AppendMode;
import org.apache.pdfbox.pdmodel.graphics.form.PDFormXObject;

import de.rototor.pdfbox.graphics2d.PdfBoxGraphics2D;

import java.awt.geom.AffineTransform;

import com.kitfox.svg.SVGDiagram;
import com.kitfox.svg.SVGException;
import com.kitfox.svg.SVGUniverse;

public class App 
{
    public static void main( String[] args ) throws Exception {
        
        App app = new App();

    }

    public App() throws Exception {
        
        // loading PDF and SVG files

        File pdfFile = new File("input.pdf");
        File svgFile = new File("input.svg");

        PDDocument doc = PDDocument.load(pdfFile);
        PDPage page = doc.getPage(0);

        SVGUniverse svgUniverse = new SVGUniverse();
        SVGDiagram diagram = svgUniverse.getDiagram(svgUniverse.loadSVG(f.toURL()));
        
        PdfBoxGraphics2D graphics = new PdfBoxGraphics2D(doc, 500, 500);

        try {
            diagram.render(graphics);
        } finally {
            graphics.dispose();
        }

        PDFormXObject xform = graphics.getXFormObject();

        try (PDPageContentStream contentWriter = new PDPageContentStream(doc, page, AppendMode.APPEND, false)) {

            AffineTransform transform = AffineTransform.getTranslateInstance(0, 0);
            xform.setMatrix(transform);
            contentWriter.drawForm(xform);
        }

        doc.save("res.pdf");
        doc.close();
    }
}

请使用svgSalamander从这里:https://github.com/mgarin/svgSalamander

请使用Coemgenus建议的方法缩放最终的叠加SVG。我尝试了第二种选择,效果很好。

尼马尔

宣弘新
2023-03-14

我这样做,但不是直接的。首先,使用FOP Library和Batik将SVG文档转换为PDF文档。https://xmlgraphics.apache.org/fop/dev/design/svg.html.

第二次,您可以使用pdfbox中的LayerTubility将新pdf文档转换为PDXObjectForm。之后,只需要在最终的pdf文档中包含PDXObjectForm。

范安歌
2023-03-14

请参阅库pdfbox图形2d,吹捧在这Jira.

您可以通过蜡染或蝾螈或其他方式将SVG绘制到类PdfBoxGraphics2D,该类与iText的模板平行。createGraphics()。有关示例,请参见GitHub页面。

PDDocument document = ...;
PDPage page = ...; // page whereon to draw

String svgXML = "<svg>...</svg>";
double leftX = ...;
double bottomY = ...; // PDFBox coordinates are oriented bottom-up!

// I set these to the SVG size, which I calculated via Salamander.
// Maybe it doesn't matter, as long as the SVG fits on the graphic.
float graphicsWidth = ...;
float graphicsHeight = ...;

// Draw the SVG onto temporary graphics.
var graphics = new PdfBoxGraphics2D(document, graphicsWidth, graphicsHeight);
try {
    int x = 0;
    int y = 0;
    drawSVG(svg, graphics, x, y); // with Batik, Salamander, or whatever you like
} finally {
    graphics.dispose();
}

// Graphics are not visible till a PDFormXObject is added.
var xform = graphics.getXFormObject();

try (var contentWriter = new PDPageContentStream(document, page, AppendMode.APPEND, false)) { // false = don't compress
    // XForm objects have to be placed via transform,
    // since they cannot be placed via coordinates like images.
    var transform = AffineTransform.getTranslateInstance(leftX, bottomY);
    xform.setMatrix(transform);

    // Now the graphics become visible.
    contentWriter.drawForm(xform);
}

和...如果你也想缩放SVG图形到25%大小:

// Way 1: Scale the SVG beforehand
svgXML = String.format("<svg transform=\"scale(%f)\">%s</svg>", .25, svgXML);

// Way 2: Scale in the transform (before calling xform.setMatrix())
transform.concatenate(AffineTransform.getScaleInstance(.25, .25));
 类似资料:
  • 我正试图用PDFbox绘制饼图,但各片之间有白线,有人能帮我吗?是否有此选项? 附上我正在使用的绘制圆弧的代码: 结果的附加图像: 谢啦

  • 问题内容: 我正在学习线性代数课程,我想可视化正在使用的向量,例如向量加法,法向向量等。 例如: 在这种情况下,我想绘制3个向量。 然后,我应该能够添加V1,V2来绘制一个新的向量V12(全部合并在一个图中)。 当我使用以下代码时,情节与预期不符 问题答案: 多亏了每个人,您的每个帖子对我都有很大帮助。 对于我的问题,rbierman代码非常简单,我做了一些修改,并创建了一个函数来绘制给定数组中的

  • 在我的应用程序中,我必须为通知设置一个大图标。LargeIcon必须是位图,我的可绘制内容是矢量图像(Android中的新功能,请参见此链接)。问题是,当我尝试解码矢量图像资源时,返回空值。 以下是代码示例: 在本示例中,当我替换R.drawable时。vector_menu_objectifs带有“普通”图像,例如png,结果不为空(我得到了正确的位图)是否缺少什么?

  • 问题内容: 我必须使用pdfbox绘制一个饼图。 令数据为: 主题分数百分比累计分数 Sub-1 80 80 80 Sub-2 70 70150 Sub-3 65 65215 Sub-4 90 90305 Sub-5 55 55360 令半径和中心为100像素和(250,400)。 让我们取平行于x轴的初始线。 绘图的初始线条语句将为: contentStream.drawLine(250,400

  • 我必须用pdfbox绘制一个饼图。 让数据是: 设半径和中心为100像素和(250,400)。 让我们取平行于x轴的初始线 绘制初始行语句将为: contentStream。抽绳(250400350400); 我坚持: a)在距离初始线一定程度的圆圈上找到点的x, y坐标,以绘制半径 b)使用贝塞尔曲线在两点之间绘制圆弧。 任何帮助解决问题将不胜感激!

  • 我正在尝试使用pdfbox将图像添加到pdf的中心。下面是我的代码,但我无法在pdf中获得图像的正确位置。我在PDFBox中遵循了以下链接,如何更改PDRectangle对象的原点(0,0)?要获得正确的位置,但静止图像偏离中点位置?