How to add image to a specific position on PDF file in WinForms

441 Views Asked by At

In my project, I'm using PDFiumViewer to view my pdf file on Winforms and iText7 to do saving operations.

This software can open any PDF on PDFiumViewer and show it to the user. There is also an "add" button to add images on PDF.

The user can adjust the position of the added image and can also adjust the size of it.

I add the image with PictureBox.

Here is the problem,

The image on the document needs to be saved on the desired location. However, when saving it, I cannot adjust the picturebox's position correctly no matter what.

I know the reason is I cannot calculate the PDF size, the form size and the PDFiumViewer size correctly.

Can you please help me with the calculation method? Or tell me a correct method to position it.

I'm freely open for any suggestion on SDKs other than PDFium or iText7.

Here is my "btnSavePdf_Click" method;

 private void btnSavePdf_Click(object sender, EventArgs e)
    {

        var saveFileDialog = new SaveFileDialog();
        saveFileDialog.Filter = "PDF Files (*.pdf)|*.pdf|All Files (*.*)|*.*";

        if (saveFileDialog.ShowDialog() == DialogResult.OK)
        {
            string outputPdfPath = saveFileDialog.FileName;

            var pdfWriter = new iText.Kernel.Pdf.PdfWriter(outputPdfPath);
            var pdfReader = new iText.Kernel.Pdf.PdfReader(loadedPdfFilename);
            using (var pdfDoc = new iText.Kernel.Pdf.PdfDocument(pdfReader,pdfWriter))
            {

                int currentPageNumber = pdfViewer1.Renderer.Page;

                var pageNum =  pdfDoc.GetPage(currentPageNumber + 1);

                Document document = new Document(pdfDoc);

                foreach (Control control in pdfViewer1.Controls)
                {
                    if (control is NewPictureBox newPictureBox)
                    {
                        System.Drawing.Image image = newPictureBox.Image;

                        // Load image from the newPictureBox
                        ImageData imageData = ImageDataFactory.Create(ImageToByteArray(image));

                        // Create iText Image object and set its properties
                        iText.Layout.Element.Image pdfImage = new iText.Layout.Element.Image(imageData)
                            .ScaleAbsolute(newPictureBox.Width * newPictureBox.ZoomFactor, newPictureBox.Height * newPictureBox.ZoomFactor);


                        float yPosition = pageNum.GetPageSize().GetHeight() - ((newPictureBox.Location.Y + pdfImage.GetImageScaledHeight()) * newPictureBox.ZoomFactor);
                        float xPosition = pageNum.GetPageSize().GetWidth() - ((newPictureBox.Location.X + pdfImage.GetImageScaledWidth()) * newPictureBox.ZoomFactor);

                        pdfImage.SetFixedPosition(xPosition, yPosition);


                        document.Add(pdfImage);


                    }
                }
                document.Close();
            }

            MessageBox.Show("PDF saved successfully.");
        }
    }

    // Helper method to convert System.Drawing.Image to byte array
    private byte[] ImageToByteArray(System.Drawing.Image image)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            image.Save(memoryStream, System.Drawing.Imaging.ImageFormat.Png);
            return memoryStream.ToArray();
        }
    }

I added the image as shown on the screenshot below. Don't forget that I dragged the picturebox to that position and adjusted its size from the borders on runtime.

In the output PDF file, there is no image. I tested it, its position is somewhere far away from the Form borders.

PS: I found a method on this platform;

image1.SetAbsolutePosition((PageSize.A4.Width - image1.ScaledWidth) / 2, (PageSize.A4.Height - image1.ScaledHeight) / 2);

With this method, I was able to put the image in the center of the PDF file. Maybe this will be our leading clue.

1

There are 1 best solutions below

0
K J On

When dragging and placing images on a PDF page it is best to stick visibly to user screen co-ordinates HERE 217 x 524 but they will be converted on placement see 217.38832 & 267.71174 below.

this is done by convert the height of page (612 x 792) less usage height (524) = 268

enter image description here

435 0 obj
<</Type/Annot/Subtype/Image/Rect[217.38832 103.27893 417.3883 267.71174]/C[0 0 0 0]/P 399 0 R/F 4/M(D:20230814144757Z)/AP<</N 439 0 R>>>>
endobj

However you need to be aware not all pages are bottom left origin so should check media size starts [0 0 ... ] and watch out for rotation or scaling factors.

If you use a runtime viewer like when working with latex then you can see the effects of moving things about text wise in notepad editor .

so here moving down to 10 units away from lower left we see the reduction in values

435 0 obj
<</Type/Annot/Subtype/Image/Rect[10.360537 10.260437 210.36054 174.69324]/C[0 0 0 0]/P 399 0 R/F 4/M(D:20230814144757Z)/AP<</N 439 0 R>>>>
endobj

enter image description here

Another thing you need to keep watching for is Annotation BLOAT when I changed that image first to second location, the whole file was rewritten with a second appendage for the new location. This if unmanaged, can excessively add more and more bytes onto the source file, because in separate "incremental saves" prior annotations are often flagged "hidden" and the new positioned object take on its old number (435 in this case, so only 2 of those at this stage!).
Hence best if you can find the prior one and edit its values without altering number of bytes. Here is the effect of working the position in a program, BUT NOTE importantly I had to alter the core X,Y precision when changing from 2 digit offset to 3 digits

enter image description here