0

I extracted some stamped signature images(png file) from pdf. like this

Lots of them are normal but few images are crashed. crashed image

original appearance

I can guess some reasons: the image is encrypted? confused? when signing.

I'm new to itext, any idea will be appreciated.

Swell Yu
  • 50
  • 5

1 Answers1

2

The reason is that the image you see is created by drawing that mostly red image

image

with a soft mask derived from another image

soft mask

I.e. where the soft mask is white, the red from the image is drawn completely opaquely; where the mask is black it is drawn completely transparently, invisibly; and where the mask is some gray in-between, the red is drawn somewhat transparently.

The ImageRenderListener you use in your previous answer is from this older answer and only extracts the base image, not the mask.

You can improve it like this to also extract the soft masks directly associated with the respective base image:

public class ExtImageRenderListener : IRenderListener
{
    public List<System.Drawing.Image> Images = new List<System.Drawing.Image>();
    public List<System.Drawing.Image> Masks = new List<System.Drawing.Image>();

    public void BeginTextBlock()
    { }

    public void EndTextBlock()
    { }

    public void RenderText(TextRenderInfo renderInfo)
    { }

    public void RenderImage(ImageRenderInfo renderInfo)
    {
        PdfImageObject imageObject = renderInfo.GetImage();
        if (imageObject == null)
        {
            Console.WriteLine("Image {0} could not be read.", renderInfo.GetRef().Number);
        }
        else
        {
            Images.Add(imageObject.GetDrawingImage());
            PRStream maskStream = (PRStream) imageObject.GetDictionary().GetAsStream(PdfName.SMASK);
            if (maskStream != null)
            {
                PdfImageObject maskImageObject = new PdfImageObject(maskStream);
                Masks.Add(maskImageObject.GetDrawingImage());
            }
            else
            {
                Masks.Add(null);
            }
        }
    }
}

Now you can process both the image and the mask:

String source = @"stampForDebug.pdf";
String signatureFieldName = "Signature12";

using (PdfReader sourceReader = new PdfReader(source))
{
    PdfStream xObject = (PdfStream)PdfReader.GetPdfObjectRelease(sourceReader.AcroFields.GetNormalAppearance(signatureFieldName));
    PdfDictionary resources = xObject.GetAsDict(PdfName.RESOURCES);
    ExtImageRenderListener strategy = new ExtImageRenderListener();
    PdfContentStreamProcessor processor = new PdfContentStreamProcessor(strategy);
    processor.ProcessContent(ContentByteUtils.GetContentBytesFromContentObject(xObject), resources);
    System.Drawing.Image drawingImage = strategy.Images.First();
    System.Drawing.Image drawingMask = strategy.Masks.First();
    if (drawingImage != null)
    {
        drawingImage.Save(@"Signature12Image.png");
    }
    if (drawingMask != null)
    {
        drawingMask.Save(@"Signature12Mask.png");
    }
}
mkl
  • 90,588
  • 15
  • 125
  • 265
  • Thanks for your time. It works fine! But now they are all black-ground white images. By customize the soft mask(I guess) if it's possible to get the same appearance as the base image(i,e, white-ground red image)? @mkl – Swell Yu May 14 '20 at 09:35
  • The mask is a mask. To get a single image out of the base image and the mask image, you have to add each mask image pixel value as opacity (alpha) value to the respective base image pixel. Unfortunately I don't know bitmap APIs that well and what I know is from Java APIs, not .Net APIs. – mkl May 14 '20 at 15:56
  • Thanks @mkl. You always give the best answer and the excellent idea :D – Swell Yu May 15 '20 at 01:53