logo
Welcome Guest! To enable all features please Login or Register.

Notification

Icon
Error

Options
Go to last post Go to first unread
bav  
#1 Posted : Wednesday, January 11, 2023 11:01:28 AM(UTC)
bav

Rank: Newbie

Groups: Registered
Joined: 1/11/2023(UTC)
Posts: 6
United States

One of our requirements for processing our data into PDFs is to place images in pre-defined locations. Using other PDF libraries, using a button field and changing the icon has always been the simplest way. The button allows for the icon properties to be pre-defined. Then the processing engine only needs to swap out the icon on the button. Then the image is already in the correct place and size on the page. Is this achievable with the Patagames Pdfium SDK?


The whole process is this:
-Open a template page
-Fill in form fields
-Add annotation text
-Place images in pre-defined locations***
-Set the page label
-Merge the template page into the output document
-Repeat for N pages...

Right now I am hung up on inserting the images.
Paul Rayman  
#2 Posted : Wednesday, January 11, 2023 11:17:40 PM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 1,075

Thanks: 6 times
Was thanked: 124 time(s) in 121 post(s)
Hello,

Here is the acroforms documentation to understand how to access/create/manipulate buttons and other forms.
https://pdfium.patagames...WorkingSDK_AcroForms.htm

And here is an example of how to create a button with an icon.
Code:

using (var doc = PdfDocument.CreateNew(new PdfForms()))
{
    //Set default appearance. Helvetica and autosize is used by default
    if (!doc.FormFill.InterForm.HasDefaultAppearance())
        doc.FormFill.InterForm.SetDefaultAppearance();

    //Create a pushbutton field 
    var pushbuttonField = new PdfPushButtonField(doc.FormFill.InterForm);

	//Create a pushbutton control that uses default appearance.
	var page = doc.Pages.InsertPageAt(0, 500, 500);
    var icon = PdfBitmap.FromFile(@"e:\0\stamp.jpg");
    var btnRect = new FS_RECTF(10, page.Height - 10, 10 + icon.Width, page.Height - 10 - icon.Height);
    var pushbuttonCtrl = new PdfPushButtonControl(pushbuttonField, page, btnRect, "Button caption", null, null, null, null, null, 0, icon, FormHighlightingMode.Push, TextPositions.TEXTPOS_ICON);

    //Add the form field to the document.
    doc.FormFill.InterForm.Fields.Add(pushbuttonField);

    //Save the document
    doc.Save(@"e:\22\test.pdf", Patagames.Pdf.Enums.SaveFlags.NoIncremental);
}


And here's how to change the icon on an existing button.
Code:

using (var doc = PdfDocument.Load(@"e:\22\test.pdf", new PdfForms()))
{
	var pushbuttonField = doc.FormFill.InterForm.Fields[0];
	var pushbuttonCtrl = pushbuttonField.Controls[0];
	var widget = pushbuttonCtrl.GetWidget();
	var page = widget.Page;
    var icon = PdfBitmap.FromFile(@"e:\0\logo_square.png");

    widget.MK.NormalIcon.Clear();
	widget.MK.NormalIcon.Add(PdfImageObject.Create(doc, icon, 0, 0));
	widget.MK.GenerateAppearance(AppearanceStreamModes.Normal);

    //Save the document
    doc.Save(@"e:\22\test2.pdf", Patagames.Pdf.Enums.SaveFlags.NoIncremental);

}
bav  
#3 Posted : Thursday, January 12, 2023 10:02:06 AM(UTC)
bav

Rank: Newbie

Groups: Registered
Joined: 1/11/2023(UTC)
Posts: 6
United States

I thank you for your response. That is pretty one of the ways that I tried to implement the desired behavior.

However, if I implement it exactly as you have it, "widget.MK.NormalIcon" throws a "KeyNotFoundException". To overcome this, I made a call to "widget.MK.CreateEmptyAppearance(AppearanceStreamModes.Normal);" This allowed the code to proceed, but the results are not what is expected.

The shows up way too large on the button, even though the original template file had "Fit To Bounds" option checked for the button icon. If I return to the form button icon properties in the output document, that option is still checked. Then when I close the options, the image scales to the correct size of the button.

Another observation: The original template file is 3.8 MB, the image is 3 MB, and the output after executing this code is 24MB. Why is the result document so large? Is there a way to have it downsample the image?

Code:

[Test]
        public void TestSetButtonIcon()
        {
            PdfCommon.Initialize(License);

            var form = new PdfForms();

            using (var doc = PdfDocument.Load(PdfTestHelper.TemplatePath, form))
            {
                foreach (var pdfField in doc.FormFill.InterForm.Fields.OfType<PdfPushButtonField>())
                {
                    if (pdfField.FullName == "image_context")
                    {
                        if (pdfField.Controls[0] is PdfPushButtonControl control)
                        {
                            var widget = control.GetWidget();

                            using (var bitmap = PdfBitmap.FromFile("Test Files/1d40e024-6bce-4b72-9502-18a104c5b968.jpg"))
                            {
                                var pdfImageObject = PdfImageObject.Create(doc, bitmap, 0, 0);

                                widget.MK.CreateEmptyAppearance(AppearanceStreamModes.Normal);

                                widget.MK.NormalIcon.Clear();

                                widget.MK.NormalIcon.Add(pdfImageObject);

                                widget.MK.GenerateAppearance(AppearanceStreamModes.Normal);
                            }
                        }
                    }
                }

                doc.Save("test_output.pdf", SaveFlags.NoIncremental);
            }
        }


Paul Rayman  
#4 Posted : Friday, January 13, 2023 2:12:40 AM(UTC)
Paul Rayman

Rank: Administration

Groups: Administrators
Joined: 1/5/2016(UTC)
Posts: 1,075

Thanks: 6 times
Was thanked: 124 time(s) in 121 post(s)
First of all, update to the latest version (4.78.2704) which fixed a couple of issues related to your task.
https://forum.patagames....released-on-Jan-13--2023


Originally Posted by: bav Go to Quoted Post

"widget.MK.NormalIcon" throws a "KeyNotFoundException".

this issue has been fixed, but calling the CreateEmptyAppearance method is more welcome.

Quote:

The shows up way too large on the button, even though the original template file had "Fit To Bounds" option checked for the button icon.


A Widget annotation has its own appearance stream, which is generated based on the properties of this annotation, including the group of MK properties. Therefore, you need to regenerate such a stream, as shown in the example below.

Quote:

The original template file is 3.8 MB, the image is 3 MB, and the output after executing this code is 24MB. Why is the result document so large? Is there a way to have it downsample the image?


A way to reduce the size of the resulting file is to use jpeg instead of PdfBitmap, where each pixel is represented by four bytes.
You can also use these saving flags:
Code:
SaveFlags.NoIncremental | SaveFlags.ObjectStream | SaveFlags.RemoveUnusedObjects


Code:

public static void TestSetButtonIcon()
{
    using (var doc = PdfDocument.Load(@"e:\22\test.pdf", new PdfForms()))
    {
        foreach (var pdfField in doc.FormFill.InterForm.Fields.OfType<PdfPushButtonField>())
        {
            if (pdfField.FullName == "image_context")
            {
                if (pdfField.Controls[0] is PdfPushButtonControl control)
                {
                    string imgFile = @"e:\19\d66ae37d46e00a1ecacfe9531986690a-9ba9622-2.jpg";
                    var widget = control.GetWidget();

                    //Create an empty image object
                    var pdfImageObject = PdfImageObject.Create(doc);
                    //Initiate it with a joeg file in order to reduce the image size
                    //(use packed jpeg instead of bitmap mask when the PdfBitmap is used)
                    pdfImageObject.LoadJpegFile(imgFile);
                    //Set the image Matrix
                    pdfImageObject.Matrix = new FS_MATRIX(pdfImageObject.Bitmap.Width, 0, 0, pdfImageObject.Bitmap.Height, 0, 0);
                    //Create/recreate the appearance stream
                    widget.MK.CreateEmptyAppearance(AppearanceStreamModes.Normal);
                    widget.MK.NormalIcon.Add(pdfImageObject);
                    widget.MK.GenerateAppearance(AppearanceStreamModes.Normal);

                    //The widget has its own appearance stream, which was generated based on the MK.
                    //Since we have changed the icon in MK, we also need to regenerate the appearance stream of this widget.
                    pdfField.Controls[0].RegenerateAppearance();
                }
            }
        }

        doc.Save(@"e:\22\test_output.pdf", SaveFlags.NoIncremental | SaveFlags.ObjectStream | SaveFlags.RemoveUnusedObjects);
    }
}

Edited by user Friday, January 13, 2023 2:23:54 AM(UTC)  | Reason: Not specified

bav  
#5 Posted : Friday, January 13, 2023 11:34:50 AM(UTC)
bav

Rank: Newbie

Groups: Registered
Joined: 1/11/2023(UTC)
Posts: 6
United States

Thank you, that seemed to have solved my issue with setting the button icon image. I was missing setting the PdfImageObject matrix and regenerating the appearance on the control.
Users browsing this topic
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.