Annotation(PdfName.STAMP)被itextsharp5.5.13.1弄平后丢失。我有两个PDF。一种有效,另一种无效。任何想法将不胜感激。
下面的代码
string outFile = inputFile + "_f.pdf";
using (PdfReader pdfReader = new PdfReader(inputFileName))
{
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(outFile, FileMode.Create, FileAccess.Write, FileShare.None))
//pdfStamper.FormFlattening = true;
//pdfStamper.FreeTextFlattening = true;
pdfStamper.AnnotationFlattening = true;
//pdfStamper.AcroFields.GenerateAppearances = true;
}
[Cause是iTextSharp中的一个错误,如果其边界框未将原点用作左下角,则注释拼合无法正确计算出扁平化注释的位置。
[如果查看PdfStamperImp.FlattenAnnotations(bool)
的代码,您会很快意识到if (app != null)
块中的计算仅在边界框位于原点或不需要缩放以适合外观边界框的情况下才有意义进入注释矩形。
(由于边界框的左下角通常是原点,因此不会经常弹出。)
因此,要展平这样的注释,您必须使用其他方法展平,例如像这样:
using (PdfReader pdfReader = new PdfReader(inputFileName))
{
PdfStamper pdfStamper = new PdfStamper(pdfReader, new FileStream(outFile, FileMode.Create, FileAccess.Write, FileShare.None));
ImprovedAnnotationFlattening(pdfStamper);
pdfStamper.Close();
}
使用这些辅助方法:
void ImprovedAnnotationFlattening(PdfStamper pdfStamper)
{
double[] DEFAULT_MATRIX = { 1, 0, 0, 1, 0, 0 };
PdfReader reader = pdfStamper.Reader;
for (int page = 1; page <= reader.NumberOfPages; ++page)
{
PdfDictionary pageDic = reader.GetPageN(page);
PdfArray annots = pageDic.GetAsArray(PdfName.ANNOTS);
if (annots == null)
continue;
for (int idx = 0; idx < annots.Size; ++idx)
{
PdfObject annoto = annots.GetDirectObject(idx);
if (!(annoto is PdfDictionary))
continue;
PdfDictionary annDic = (PdfDictionary)annoto;
PdfNumber ff = annDic.GetAsNumber(PdfName.F);
int flags = ff != null ? ff.IntValue : 0;
if ((flags & PdfFormField.FLAGS_PRINT) == 0 || (flags & PdfFormField.FLAGS_HIDDEN) != 0)
continue;
PdfObject obj1 = annDic.Get(PdfName.AP);
if (obj1 == null)
continue;
PdfDictionary appDic = obj1 is PdfIndirectReference
? (PdfDictionary)PdfReader.GetPdfObject(obj1)
: (PdfDictionary)obj1;
PdfObject obj = appDic.Get(PdfName.N);
PdfStream objDict = appDic.GetAsStream(PdfName.N);
if (objDict != null)
{
Rectangle rect = PdfReader.GetNormalizedRectangle(annDic.GetAsArray(PdfName.RECT));
Rectangle bbox = PdfReader.GetNormalizedRectangle(objDict.GetAsArray(PdfName.BBOX));
PdfContentByte cb = pdfStamper.GetOverContent(page);
cb.SetLiteral("Q ");
PdfArray matrixArray = objDict.GetAsArray(PdfName.MATRIX);
double[] matrix = matrixArray != null ? matrixArray.AsDoubleArray() : DEFAULT_MATRIX;
AffineTransform transform = new AffineTransform(matrix);
double[] bboxCorners = { bbox.Left, bbox.Bottom, bbox.Right, bbox.Bottom, bbox.Right, bbox.Top, bbox.Left, bbox.Top };
transform.Transform(bboxCorners, 0, bboxCorners, 0, 4);
double minX = Min(bboxCorners, 0, 2);
double maxX = Max(bboxCorners, 0, 2);
double minY = Min(bboxCorners, 1, 2);
double maxY = Max(bboxCorners, 1, 2);
transform.preConcatenate(AffineTransform.GetTranslateInstance(-minX, -minY));
transform.preConcatenate(AffineTransform.GetScaleInstance(rect.Width/(maxX-minX), rect.Height/(maxY-minY)));
transform.preConcatenate(AffineTransform.GetTranslateInstance(rect.Left, rect.Bottom));
transform.GetMatrix(matrix);
cb.AddFormXObj(objDict, GenerateName(), matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
cb.SetLiteral("q ");
annots.Remove(idx);
--idx;
}
}
}
}
double Min(double[] array, int start, int step)
{
double result = array[start];
for (int i = start + step; i < array.Length; i+=step)
{
result = Math.Min(result, array[i]);
}
return result;
}
double Max(double[] array, int start, int step)
{
double result = array[start];
for (int i = start + step; i < array.Length; i += step)
{
result = Math.Max(result, array[i]);
}
return result;
}
PdfName GenerateName()
{
PdfName name = new PdfName("XXX" + formXObjectsCounter);
++formXObjectsCounter;
return name;
}
int formXObjectsCounter = 4711;
要当心:我只是编写了这些方法(从原始拼合代码中尽可能多地复制),并且仅对示例文件进行了测试。某些边境条件可能仍必须考虑作为一般用途。特别是我没有进行所有相关的null
或0
测试。另外,我也没有尝试支持适当的标记。