iTextSharp 用另一个 PDF 替换图像
iTextSharp replace image with another PDF
我有一个包含一些图像的 PDF 文件,我想将其替换为其他 PDF。代码通过 pdf 并获取图像引用:
PdfDocument pdf = new PdfDocument(new PdfReader(args[0]), new PdfWriter(args[1]));
for(int i=1; i<=pdf.GetNumberOfPages(); ++i)
{
PdfDictionary pageDict = pdf.GetPage(i).GetPdfObject();
PdfDictionary resources = pageDict.GetAsDictionary(PdfName.Resources);
PdfDictionary xObjects = resources.GetAsDictionary(PdfName.XObject);
foreach (PdfName imgRef in xObjects.KeySet())
{
// image reference
}
}
对于我所有的图像,我都有一个相应的 PDF,我想用它来替换图像。我尝试的是 Put
另一个 PDF(始终是单页)作为对象:
PdfDocument other = new PdfDocument(new PdfReader("replacement.pdf"));
xObjects.Put(imgRef, other.GetFirstPage().GetPdfObject().Clone());
但是在关闭 PdfDocument
时抛出异常:
iText.Kernel.PdfException: 'Pdf indirect object belongs to other PDF document. Copy object to current pdf document.'
如何实现用另一个 PDF(的内容)替换图像?
更新
我还尝试了一些其他方法,这些方法可能会改善结果。为了克服之前的错误信息,我通过以下方式将页面复制到原始 pdf:
var page = other.GetFirstPage().CopyTo(pdf);
但是,替换 xObject 不起作用:
xObjects.Put(imgRef, page.GetPdfObject());
导致 PDF 损坏。
要将原始页面复制到另一个文档中以用作图像替换,您可以使用 PdfPage#CopyAsFormXObject
。
所以假设我们有这个 PDF 作为模板,我们想用另一个 PDF 的内容替换沙漠的图像:
我们还假设我们要用作替换的 PDF 如下所示:
问题在于,如果我们盲目地将原始图像替换为 PDF 的内容,很可能会得到这样的结果:
因此我们会感觉一切正常,但视觉效果仍然很差。问题是坐标对于普通光栅图像和矢量 XObjects(PDF 替换)的工作方式有点不同。所以我们还需要调整我们新建的XObject的变换矩阵(/Matrix
键)。
因此代码可能如下所示:
PdfDocument pdf = new PdfDocument(new PdfReader(@"template.pdf"), new PdfWriter(@"out.pdf"));
for(int i=1; i<=pdf.GetNumberOfPages(); ++i) {
PdfDictionary pageDict = pdf.GetPage(i).GetPdfObject();
PdfDictionary resources = pageDict.GetAsDictionary(PdfName.Resources);
PdfDictionary xObjects = resources.GetAsDictionary(PdfName.XObject);
IDictionary<PdfName, PdfStream> toReplace = new Dictionary<PdfName, PdfStream>();
foreach (PdfName imgRef in xObjects.KeySet()) {
PdfStream previousXobject = xObjects.GetAsStream(imgRef);
PdfDocument imageReplacementDoc =
new PdfDocument(new PdfReader(@"insert.pdf"));
PdfXObject imageReplacement = imageReplacementDoc.GetPage(1).CopyAsFormXObject(pdf);
toReplace[imgRef] = imageReplacement.GetPdfObject();
adjustXObjectSize(imageReplacement);
imageReplacementDoc.Close();
}
foreach (var x in toReplace) {
xObjects.Put(x.Key, x.Value);
}
}
pdf.Close();
UPD:adjustXObjectSize
的实现(感谢mkl):
private void adjustXObjectSize(PdfXObject pageXObject) {
float scaleXobject = 1 / Math.Max(pageXObject.GetWidth(), pageXObject.GetHeight());
AffineTransform transform = new AffineTransform();
transform.Scale(scaleXobject, scaleXobject);
float[] matrix = new float[6];
transform.GetMatrix(matrix);
pageXObject.GetPdfObject().Put(PdfName.Matrix, new PdfArray(matrix));
}
在 运行 我描述的示例的上述代码之后的视觉结果如下所示:
我有一个包含一些图像的 PDF 文件,我想将其替换为其他 PDF。代码通过 pdf 并获取图像引用:
PdfDocument pdf = new PdfDocument(new PdfReader(args[0]), new PdfWriter(args[1]));
for(int i=1; i<=pdf.GetNumberOfPages(); ++i)
{
PdfDictionary pageDict = pdf.GetPage(i).GetPdfObject();
PdfDictionary resources = pageDict.GetAsDictionary(PdfName.Resources);
PdfDictionary xObjects = resources.GetAsDictionary(PdfName.XObject);
foreach (PdfName imgRef in xObjects.KeySet())
{
// image reference
}
}
对于我所有的图像,我都有一个相应的 PDF,我想用它来替换图像。我尝试的是 Put
另一个 PDF(始终是单页)作为对象:
PdfDocument other = new PdfDocument(new PdfReader("replacement.pdf"));
xObjects.Put(imgRef, other.GetFirstPage().GetPdfObject().Clone());
但是在关闭 PdfDocument
时抛出异常:
iText.Kernel.PdfException: 'Pdf indirect object belongs to other PDF document. Copy object to current pdf document.'
如何实现用另一个 PDF(的内容)替换图像?
更新
我还尝试了一些其他方法,这些方法可能会改善结果。为了克服之前的错误信息,我通过以下方式将页面复制到原始 pdf:
var page = other.GetFirstPage().CopyTo(pdf);
但是,替换 xObject 不起作用:
xObjects.Put(imgRef, page.GetPdfObject());
导致 PDF 损坏。
要将原始页面复制到另一个文档中以用作图像替换,您可以使用 PdfPage#CopyAsFormXObject
。
所以假设我们有这个 PDF 作为模板,我们想用另一个 PDF 的内容替换沙漠的图像:
我们还假设我们要用作替换的 PDF 如下所示:
问题在于,如果我们盲目地将原始图像替换为 PDF 的内容,很可能会得到这样的结果:
因此我们会感觉一切正常,但视觉效果仍然很差。问题是坐标对于普通光栅图像和矢量 XObjects(PDF 替换)的工作方式有点不同。所以我们还需要调整我们新建的XObject的变换矩阵(/Matrix
键)。
因此代码可能如下所示:
PdfDocument pdf = new PdfDocument(new PdfReader(@"template.pdf"), new PdfWriter(@"out.pdf"));
for(int i=1; i<=pdf.GetNumberOfPages(); ++i) {
PdfDictionary pageDict = pdf.GetPage(i).GetPdfObject();
PdfDictionary resources = pageDict.GetAsDictionary(PdfName.Resources);
PdfDictionary xObjects = resources.GetAsDictionary(PdfName.XObject);
IDictionary<PdfName, PdfStream> toReplace = new Dictionary<PdfName, PdfStream>();
foreach (PdfName imgRef in xObjects.KeySet()) {
PdfStream previousXobject = xObjects.GetAsStream(imgRef);
PdfDocument imageReplacementDoc =
new PdfDocument(new PdfReader(@"insert.pdf"));
PdfXObject imageReplacement = imageReplacementDoc.GetPage(1).CopyAsFormXObject(pdf);
toReplace[imgRef] = imageReplacement.GetPdfObject();
adjustXObjectSize(imageReplacement);
imageReplacementDoc.Close();
}
foreach (var x in toReplace) {
xObjects.Put(x.Key, x.Value);
}
}
pdf.Close();
UPD:adjustXObjectSize
的实现(感谢mkl):
private void adjustXObjectSize(PdfXObject pageXObject) {
float scaleXobject = 1 / Math.Max(pageXObject.GetWidth(), pageXObject.GetHeight());
AffineTransform transform = new AffineTransform();
transform.Scale(scaleXobject, scaleXobject);
float[] matrix = new float[6];
transform.GetMatrix(matrix);
pageXObject.GetPdfObject().Put(PdfName.Matrix, new PdfArray(matrix));
}
在 运行 我描述的示例的上述代码之后的视觉结果如下所示: