Аннотации (штамп) пропущены после расплющивания - PullRequest
1 голос
/ 28 мая 2020

Аннотация (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;

}

1 Ответ

2 голосов
/ 28 мая 2020

Причина - ошибка в 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. Также я не пытался поддерживать правильную маркировку.

...