Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image bounds displaced from real position #39

Open
frojasg1 opened this issue May 7, 2020 · 3 comments
Open

Image bounds displaced from real position #39

frojasg1 opened this issue May 7, 2020 · 3 comments

Comments

@frojasg1
Copy link

frojasg1 commented May 7, 2020

Hello,

The previous request was because I wanted to use that ami3 function, because mine (based also on the one of ami3) with some books adds an offset to position of images.
But I have checked, linking from my library to ami3 and using ami3 getBoundingRect().
That function gives also the displaced location on images of some books.

You can check with that pdf example:
https://www.frojasg1.com/Test-1.pdf

It gives an offset to the position of the image at the bottom.

@frojasg1
Copy link
Author

frojasg1 commented May 7, 2020

I have found the issue with my code (may be ami3 is not supposed to take those displacements into account, I do not know).

Any way, I place here the code to extract the image bounds placed on the page image at 72dpi, with all transformations done: (my code, only deals with Rectangle, instead of with SVGRect)

public class MyPDFRenderer extends PDFRenderer
{
	protected List<GlyphWrapper> _listOfGlyphs = new ArrayList<>();
	protected List<ImageWrapper> _listOfImages = new ArrayList<>();

	private AffineTransform flipAT;
	private AffineTransform rotateAT;
	private AffineTransform transAT;

	...

		// copied from DrawPrintTextLocations.java pdfbox example
		protected void createTransformations()
		{
			PDPage pdPage = getCurrentPage();
			PDRectangle cropBox = pdPage.getCropBox();

			flipAT = new AffineTransform();
			flipAT.translate(0, pdPage.getBBox().getHeight());
			flipAT.scale(1, -1);

			// pageIndex may be rotated
			rotateAT = new AffineTransform();
			int rotation = pdPage.getRotation();
			if (rotation != 0)
			{
				PDRectangle mediaBox = pdPage.getMediaBox();
				switch (rotation)
				{
					case 90:
						rotateAT.translate(mediaBox.getHeight(), 0);
						break;
					case 270:
						rotateAT.translate(0, mediaBox.getWidth());
						break;
					case 180:
						rotateAT.translate(mediaBox.getWidth(), mediaBox.getHeight());
						break;
					default:
						break;
				}
				rotateAT.rotate(Math.toRadians(rotation));
			}

			// cropbox
			transAT = AffineTransform.getTranslateInstance(-cropBox.getLowerLeftX(), cropBox.getLowerLeftY());
		}

		private Rectangle getBoundingRect() {

			Matrix ctm = getGraphicsState().getCurrentTransformationMatrix();
			AffineTransform at = ctm.createAffineTransform();
			Shape bbox = new Rectangle2D.Float(0, 0, 1, 1);
			bbox = at.createTransformedShape(bbox);

			bbox = flipAT.createTransformedShape(bbox);
			bbox = rotateAT.createTransformedShape(bbox);
			bbox = transAT.createTransformedShape(bbox);

			Rectangle result = bbox.getBounds();

			return( result );
		}

		protected ImageWrapper createImageWrapper( PDImage pdImage )
		{
			ImageWrapper result = null;
			RenderedImage image = ExecutionFunctions.instance().safeFunctionExecution( () -> pdImage.getImage() );
			if( image != null )
			{
				createTransformations();
				Rectangle rect = getBoundingRect();
				result = new ImageImpl( image, rect );
			}

			return( result );
		}


		@Override
		public void drawImage(PDImage pdImage) throws IOException {
			super.drawImage(pdImage);

			ImageWrapper image = createImageWrapper( pdImage );
			if( image != null )
				_listOfImages.add( image );
		}

	...
}

Sorry for so many messages.

@petermr
Copy link
Owner

petermr commented May 7, 2020 via email

@frojasg1
Copy link
Author

frojasg1 commented May 7, 2020

Well, I am not an expert on your ami3 tool.
What I can do, is to show you the difference between the image positions extracted before and after the correction, with a suitable PDF for the test.
In the application before the correction, image positions were extracted in the same way as ami3 does.
In the application after the correction Image positions are extracted with the function I pasted in my previous comment.

You can download the two versions of the application here:

You can find the pdf for testing here:
https://www.frojasg1.com/Test-1.pdf

Start the two versions of the application, open the pdf for testing and place mouse cursor over the image on the bottom.
A blue frame with the boundaries of the image will be shown.
Notice the difference between the frame showed with the two versions.

I think it must have to do with:

	PDPage pdPage = getCurrentPage();
	PDRectangle cropBox = pdPage.getCropBox();
	transAT = AffineTransform.getTranslateInstance(-cropBox.getLowerLeftX(), cropBox.getLowerLeftY());
	bbox = transAT.createTransformedShape(bbox);

Which may be is not taken into account with the previous way (copied from ami3) to calculate those bounds.

But as I said in a previous comment, I do not know if ami3 is supposed to have into account those details, or if its output is accurate enough for the purpose it is intended to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants