我有以下方法,该方法应该在给定坐标处的 pdf 文件上标记图像,并在图层仍然分离(即未展平)的情况下返回它,我设置了 FormFlattening 属性,但它不起作用。
经过一番实验,我发现当我调用 getPdfLayers 方法时,文件不会被展平,为什么会这样呢?
public static byte[] StampLayer(System.Drawing.Image image, int x, int y, string layername)
{
var iImage = iTextSharp.text.Image.GetInstance(image, ImageFormat.Tiff);
var reader = new PdfReader(_pdfFile);
using (var ms = new MemoryStream())
{
using (var stamper = new PdfStamper(reader, ms))
{
//Don't delete otherwise the stamper flattens the layers
var layers = stamper.GetPdfLayers();
stamper.FormFlattening = false;
var logoLayer = new PdfLayer(layername, stamper.Writer);
PdfContentByte cb = stamper.GetUnderContent(1);
cb.BeginLayer(logoLayer);
//300dpi
iImage.ScalePercent(24f);
iImage.SetAbsolutePosition(x, y);
cb.AddImage(iImage);
cb.EndLayer();
stamper.Close();
return (ms.GetBuffer());
}
}
}
Run Code Online (Sandbox Code Playgroud)
iTextSharp版本是:5.5.6
我尝试过 png 和 jpg 图像,结果是一样的。
我正在使用这个文件来测试。
您似乎在 iText(Sharp) 中发现了一个错误。但您的代码中还存在一个额外的弱点。
PdfStamperImp( 的类stamper.Writer) 派生自PdfWriter。PdfWriter保存它所写入的 PDF 图层的集合:
protected Dictionary<IPdfOCG, object> documentOCG = new Dictionary<IPdfOCG,object>();
Run Code Online (Sandbox Code Playgroud)
PdfStamperImp仅使用文档的现有层延迟初始化该成员,例如在其方法中GetPdfLayers:
virtual public Dictionary<string,PdfLayer> GetPdfLayers()
{
if (documentOCG.Count == 0)
{
ReadOCProperties();
}
...
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,它使用字典的计数documentOCG作为初始化是否已经发生的指示器。
但不幸的是,
var logoLayer = new PdfLayer(layername, stamper.Writer);
Run Code Online (Sandbox Code Playgroud)
打破了这个惰性初始化方案:它执行
writer.RegisterLayer(this);
Run Code Online (Sandbox Code Playgroud)
并被RegisterLayer定义PdfWriter为
documentOCG[layer] = null;
Run Code Online (Sandbox Code Playgroud)
在给定的情况下。
因此,在大于0后,这会阻止惰性层初始化,因此在标记期间有效地删除了重要的层信息,除非之前已经发生过初始化。new PdfLayer(layername, stamper.Writer)documentOCG.Count
您的解决方法
//Don't delete otherwise the stamper flattens the layers
var layers = stamper.GetPdfLayers();
Run Code Online (Sandbox Code Playgroud)
本质上强制在调用构造函数之前进行初始化。PdfLayer
这个错误可以通过覆盖来修复RegisterLayer(PdfStamperImp当然它必须是虚拟的);覆盖必须首先触发延迟初始化本身。实际上,延迟初始化应该使用独立标志并检查字典计数作为健全性检查。
iText 中存在模拟错误,可以使用StampInLayer.java重现。
你归来
return (ms.GetBuffer());
Run Code Online (Sandbox Code Playgroud)
这是完全错误的:缓冲区通常比实际文件大,即您返回的 PDF 带有长尾垃圾字节。使用
return (ms.ToArray());
Run Code Online (Sandbox Code Playgroud)
反而。
在您的问题和代码中,您认为您的问题是形式扁平化并试图进行干预。不过,表单扁平化与您的问题无关。表单扁平化是指扁平化(合并到内容中)AcroForm 表单字段值,例如文本字段或复选框。
| 归档时间: |
|
| 查看次数: |
1031 次 |
| 最近记录: |