Image is placed at wrong position

As provided in sample code provided at below path, some of the PDFs are getting image placed on wrong position or rotated image is getting place in PDF document.
Please suggest if any workaround or other solution is there to place an image. The same code is working fine with most of the documents. for some PDFs this issue is happening.

@Ekta_Vegad

Please share the sample PDF document along with sample image with us. We will test the scenario in our environment and address it accordingly.

Dear Asad,

Ekta and I from same team, please find attached document and signed document and signature. Please look into this issue on priority.
signplace_replaced is with replacement of “Signed by” text annotation.
What we want to achieve is replace text annotation with sign image

	com.aspose.pdf.Document pdfDocument = new com.aspose.pdf.Document("D:\\workspace\\Asposeconversion\\Mai-Letter.pdf");
for (Page page : pdfDocument.getPages()) {
	
	for(Annotation textAnnotation : page.getAnnotations()){							
		if (textAnnotation.getContents() != null
				&& (textAnnotation.getContents().trim().equalsIgnoreCase("Signed by")
						|| textAnnotation.getContents().trim().equalsIgnoreCase("Signed by" ))) {
com.aspose.pdf.Rectangle rect = textAnnotation.getRect();
page.getContents().add(new com.aspose.pdf.operators.GSave());

			Matrix matrix = new Matrix(new double[] { rect.getURX() - rect.getLLX(), 0, 0, rect.getURY() - rect.getLLY(), rect.getLLX(), rect.getLLY() });
			// below is a same code provided to place an image in existing file \\Using ConcatenateMatrix (concatenate matrix) operator: definegs how image must be placed
			page.getContents().add(new com.aspose.pdf.operators.ConcatenateMatrix(matrix));
			XImage ximage = page.getResources().getImages().get_Item(page.getResources().getImages().size());
			// Using Do operator: this operator draws image
			page.getContents().add(new com.aspose.pdf.operators.Do(ximage.getName()));
			// Using GRestore operator: this operator restores graphics state
			page.getContents().add(new com.aspose.pdf.operators.GRestore());

Mai-Letter of Credit - Novatex Limited.pdf (3.3 MB)
signplace_replaced.pdf (562.4 KB)
signature1.jpg (2.5 KB)

Thanks

@yalshaiba

We tested the scenario in our environment while using Aspose.PDF for Java 21.1 and were able to notice the issue. We also tried textAnnotation.getRectangle(true); method to get the rectangle of text annotation while considering rotation but, it did not give any success. Therefore, an issue as PDFJAVA-40187 has been logged in our issue tracking system. We will further look into its details and keep you posted with the status of its correction. Please be patient and spare us some time.

We are sorry for the inconvenience.

Dear Asad,

We are using Aspose libraries since more than 4 years now. We deployed the solution on live system with the replacement of rectangle with an image.

Let us know if we need to wait long to resolve this issue “PDFJAVA-40187”. Also we are looking for any other way to achieve this using aspose jar. Let us know if any other function or procedure we can follow to achieve the requirements.

We are looking for the solution to apply the image on the PDF at the position that is obtained with a rectangle text box.

It will be great help for us to resolve this issue on priority.

Thanks,

image001.jpg (2.82 KB)

image002.jpg (14.4 KB)

@Ekta_Vegad

Sometimes, the issue is related only to a specific type of PDF document. The API may behave differently in case of different PDF files due to their different structures and complexity. Would you kindly share a sample source PDF and sample image for our reference. Please also share some details that with which text you want to replace image. We will test the scenario in our environment and share our feedback with you accordingly.

Dear Asad,

I updated the PDF and signature in previous replied from my colleague “Yousuf”. Also find other sample PDF files and image attached. We are trying to replace Signed by1 in this PDF. Please find attached “Signplace_replaced” with the sign applied on other place than the rectangle textbox. i.e. textAnnotation in aspose.

Thanks,

image001.jpg (2.82 KB)

image002.jpg (14.4 KB)

image003.jpg (181 Bytes)

signplace_replaced.pdf (1020 KB)

signature1.jpg (2.46 KB)

EESCO.pdf (1020 KB)

@Ekta_Vegad

We tried to use a different approach to replace the annotation with image using following code snippet and Aspose.PDF for Java 21.2. We did not get much success. The image was added at wrong position:

Document pdfDocument = new Document(dataDir + "EESCO.pdf");
for (Page page : pdfDocument.getPages()) {

 for (com.aspose.pdf.Annotation textAnnotation : page.getAnnotations()) {
  if (textAnnotation.getContents() != null
   && (textAnnotation.getContents().trim().equalsIgnoreCase("Signed by1")
   || textAnnotation.getContents().trim().equalsIgnoreCase("Signed by1"))) {
    com.aspose.pdf.Rectangle rectangle = textAnnotation.getRectangle(true);
    ImageStamp img = new ImageStamp(dataDir + "signature1.jpg");
    img.setXIndent(rectangle.getLLX());
    img.setYIndent(rectangle.getLLX());
    img.setHeight(rectangle.getHeight());
    img.setWidth(rectangle.getWidth());
    page.addStamp(img);
   }
  }
 }
pdfDocument.save(dataDir + "output.pdf");

Hence, we have created a new ticket as PDFJAVA-40249 in our issue tracking system for this problem. We will further investigate the reasons behind this behavior of the API and let you know as soon as the ticket is resolved. Please be patient and spare us some time.

We are sorry for the inconvenience.

@Ekta_Vegad

We have investigated the earlier logged ticket(s) and found that your code fragment 1 - does not take into account the page rotation (it is 270 degrees clockwise for the current document) and donot isolate existing content from the influence of other applied matrix.

The following code can fix it:

Document pdfDocument = new Document(dataDir + "EESCO.pdf");
        for (Page page : pdfDocument.getPages()) {

            for (com.aspose.pdf.Annotation textAnnotation : page.getAnnotations()) {
                if (textAnnotation.getContents() != null
                        && textAnnotation.getContents().trim().equalsIgnoreCase("Signed by1")) {
                    com.aspose.pdf.Rectangle rectangle = textAnnotation.getRectangle(true);
                    java.io.FileInputStream imageStream = new java.io.FileInputStream(new java.io.File(dataDir + "signature1.jpg"));

                    // Add an image to the Images collection of the page resources
                    page.getResources().getImages().add(imageStream);

                    //fix 1: wrap and isolate previous GState
                    page.getContents().insert(1, new com.aspose.pdf.operators.GSave());
                    page.getContents().add(new com.aspose.pdf.operators.GRestore());

                    // Using the GSave operator: this operator saves current graphics state
                    page.getContents().add(new com.aspose.pdf.operators.GSave());
                    //fix 2: calculate matrix taking into account page rotation:
//                    Matrix matrix = new Matrix(new double[] { rectangle.getURX() - rectangle.getLLX(), 0, 0, rectangle.getURY() - rectangle.getLLY(), rectangle.getLLX(), rectangle.getLLY() });
                    Matrix matrix;
                    if (page.getRotate()==Rotation.on270) {
                        Rectangle pageRect = page.getPageRect(true);
                        matrix = new Matrix(new double[]{
                                0,
                                -rectangle.getWidth(),
                                rectangle.getHeight(),
                                0,
                                rectangle.getLLY(),
                                pageRect.getWidth() - rectangle.getLLX()
                        });
                    }else{
                        //no rotation
                        matrix = new Matrix(new double[] { rectangle.getURX() - rectangle.getLLX(), 0, 0, rectangle.getURY() - rectangle.getLLY(), rectangle.getLLX(), rectangle.getLLY() });
                    }
                    // Using ConcatenateMatrix (concatenate matrix) operator: defines how image must be placed
                    page.getContents().add(new com.aspose.pdf.operators.ConcatenateMatrix(matrix));
                    XImage ximage = page.getResources().getImages().get_Item(page.getResources().getImages().size());

                    // Using Do operator: this operator draws image
                    page.getContents().add(new com.aspose.pdf.operators.Do(ximage.getName()));

                    // Using GRestore operator: this operator restores graphics state
                    page.getContents().add(new com.aspose.pdf.operators.GRestore());
                }
            }
        }
        pdfDocument.save(dataDir + "output_21_5__fixed2.pdf");

Also, the second code fragment with image stamp has mistake in this line: img.setYIndent(rectangle.getLLX()); whereas the correct is the following:

img.setYIndent(rectangle.getLLY());

The next code will also work fine:

Document pdfDocument = new Document(dataDir + "EESCO.pdf");
        for (Page page : pdfDocument.getPages()) {

            for (com.aspose.pdf.Annotation textAnnotation : page.getAnnotations()) {
                if (textAnnotation.getContents() != null
                        && textAnnotation.getContents().trim().equalsIgnoreCase("Signed by1")) {
                    com.aspose.pdf.Rectangle rectangle = textAnnotation.getRectangle(true);
                    ImageStamp img = new ImageStamp(dataDir + "signature1.jpg");
                    img.setXIndent(rectangle.getLLX());
                    img.setYIndent(rectangle.getLLY());
                    img.setHeight(rectangle.getHeight());
                    img.setWidth(rectangle.getWidth());

                    img.setBottomMargin(0);
                    img.setLeftMargin(0);
                    page.addStamp(img);
                }
            }
        }
        pdfDocument.save(dataDir + "output_21_5__fixed.pdf");

Also, the following condition checks the same twice, need to refactor it reducing duplicate. A single check is enough for the current case or add a separate check for each annotation that should be replaced by a separate image.

textAnnotation.getContents().trim().equalsIgnoreCase("Signed by1")
   || textAnnotation.getContents().trim().equalsIgnoreCase("Signed by1")

In addition, after placing images - we can remove annotations that cover posted images.
For example, the following code will place 4 images into annotations positions on page 1 and then remove annotations from that page:

Document pdfDocument = new Document(dataDir + "EESCO.pdf");
        for (Page page : pdfDocument.getPages()) {

            ArrayList<com.aspose.pdf.Annotation> annotationsForDelete = new ArrayList<>();
            for (com.aspose.pdf.Annotation textAnnotation : page.getAnnotations()) {
                if (textAnnotation.getContents() != null
                        && (textAnnotation.getContents().trim().equalsIgnoreCase("Signed by1")
                        ||textAnnotation.getContents().trim().equalsIgnoreCase("Signed by2")
                        ||textAnnotation.getContents().trim().equalsIgnoreCase("Signed by3")
                        ||textAnnotation.getContents().trim().equalsIgnoreCase("Signed by4"))) {
                    com.aspose.pdf.Rectangle rectangle = textAnnotation.getRectangle(true);

                    ImageStamp img = new ImageStamp(dataDir + "signature1.jpg");
                    img.setXIndent(rectangle.getLLX());
                    img.setYIndent(rectangle.getLLY());
                    img.setHeight(rectangle.getHeight());
                    img.setWidth(rectangle.getWidth());

                    img.setBottomMargin(0);
                    img.setLeftMargin(0);
                    page.addStamp(img);
                    annotationsForDelete.add(textAnnotation);
                }
            }
            for (Annotation annotation: annotationsForDelete)
            {
                page.getAnnotations().delete(annotation);
            }
        }
        pdfDocument.save(dataDir + "output_21_5__fixed1_noAnnotations.pdf"); 

output_21_5__fixed1.pdf (1015.1 KB)
output_21_5__fixed2.pdf (1014.8 KB)
output_21_5__fixed1_noAnnotations.pdf (1.0 MB)