LibrePDF / OpenPDF

OpenPDF is a free Java library for creating and editing PDF files, with a LGPL and MPL open source license. OpenPDF is based on a fork of iText. We welcome contributions from other developers. Please feel free to submit pull-requests and bugreports to this GitHub repository.
Other
3.64k stars 599 forks source link

Setting page size doesn't take effect until new page #739

Open tbessie opened 2 years ago

tbessie commented 2 years ago

Describe the bug When I create a new Document and add images to it, I set the page size for each image received before adding the image. However, the page size I set doesn't appear to take effect until the next page. This worked differently in the older version of iText we ported this from.

To Reproduce

    /**
     * Convert TIFF to PDF.
     * Used for processing incoming Fax data.
     */
    public byte[] convertTIFFToPDF(byte[] originalBytes) throws Throwable {

        // Make sure input is non-null
        originalBytes = (originalBytes == null) ? new byte[0] : originalBytes;

        Document document = new Document();
        ByteArrayOutputStream outfile = new ByteArrayOutputStream();
        ByteArrayInputStream bais = null;

        PdfWriter writer = PdfWriter.getInstance(document, outfile);
        writer.setStrictImageSequence(true);
        document.open();

        bais = new ByteArrayInputStream(originalBytes);

        ImageInputStream iis = ImageIO.createImageInputStream(bais);

        if (iis == null) {
            throw new IllegalStateException("Cannot create ImageInputStream for bytes");
        }

        ImageReader reader = getTIFFImageReader();
        reader.setInput(iis);
        int pages = reader.getNumImages(true);
        for (int imageIndex = 0; imageIndex < pages; imageIndex++) {
            BufferedImage bufferedImage = reader.read(imageIndex);
            Image image = Image.getInstance(bufferedImage, null, false);
            if (image.getDpiX() > 0 && image.getDpiY() > 0) {
                image.scalePercent(7200f / image.getDpiX(), 7200f / image.getDpiY());
            }

            document.setPageSize(new Rectangle(image.getScaledWidth(), image.getScaledHeight()));

            image.setAlignment(Image.MIDDLE);

            /* ---> PROBLEM HERE: THIS IMAGE APPEARS IN PDF AS DEFAULT PAGE SIZE (A4)
             * FOR FIRST PAGE INSTEAD OF PAGE SIZE WE JUST SET.  IN THIS LOOP, PAGE SIZE SEEMS
             * TO LAG FROM LAST PAGE SIZE SET.
             */
            /* This worked in an older version of iText, but not in current version of OpenPDF */
            document.add(image);

            document.newPage();
        }
    }

    private static ImageReader getTIFFImageReader() {

        Iterator<ImageReader> imageReaders = ImageIO.getImageReadersByFormatName("TIFF");

        if (!imageReaders.hasNext()) {
            throw new UnsupportedOperationException("No TIFF Reader found");
        }

        return imageReaders.next();
    }

Expected behavior Page size applies to current page, not next page.

Screenshots

System (please complete the following information):

Additional context Add any other context about the problem here.

Brooklyn-0 commented 2 years ago

Hi, can I work on this issue?

tbessie commented 2 years ago

Hi, can I work on this issue?

Not sure if you're asking me, or someone who's in charge of the project. :-)

If you do, in any case, when I stepped through what's happening, I suspected the various listener events that are being fired and how they are responded to. Perhaps they are being ignored for page size change for current page. I don't know what the listeners are doing, though, as I didn't step into them.

tbessie commented 2 years ago

NOTE: I also noticed that the default MediaBox value per PDF page is the same as the resolution of the image that page contains. In the iText version we were using, the default value is A4 (which appears the default pagesize overall). I'm not sure if this is a bug in the old iText library or a bug in OpenPDF - probably debateable.

tbessie commented 2 years ago

It looks like this (and associated behavior) is the culprit, from PdfDocument:

public boolean setPageSize(Rectangle pageSize) {
    if (this.writer != null && this.writer.isPaused()) {
        return false;
    } else {
        this.nextPageSize = new Rectangle(pageSize);
        return true;
    }
}
bluesunxp commented 1 year ago

hi tbessie, i moved document.open() after document.setPageSize, it works fine.