3

I'm trying to write a photobooth program but I'm having a hard time making a borderless print. I'm very close but the image does not fill a 4" x 6" print. I would appreciate any tips on achieving a borderless print.

Cheers!

    final BufferedImage img = ImageIO.read(new File(image));

    // Assuming that images are going to be 300 DPI
    PrinterResolution pr = new PrinterResolution(300, 300,
        PrinterResolution.DPI);

    PrintRequestAttributeSet pras = new HashPrintRequestAttributeSet();
    pras.add(pr);

    // Set print job so the image name shows (in the print queue)
    this.pj.setJobName(new File(image).getName());

    PageFormat pf = this.pj.getPageFormat(null);
    Paper paper = pf.getPaper();
    paper.setSize(4 * 72, 6 * 72);
    paper.setImageableArea(
        0.0, 0.0,
        paper.getWidth(), paper.getHeight()
    );

    if(img.getWidth(null) > img.getHeight(null))
        pf.setOrientation(PageFormat.LANDSCAPE);
    else
        pf.setOrientation(PageFormat.PORTRAIT);

    pf.setPaper(paper);

    // Create the page
    this.pj.setPrintable(new Printable() {
        public int print(Graphics g, PageFormat pf, int i) throws 
            PrinterException {
            if (i != 0)
                return NO_SUCH_PAGE;

            double width = img.getWidth(null);
            double height = img.getHeight(null);

            double w = Math.floor(pf.getImageableWidth() - 
                pf.getImageableX()) / (width * 1.0);

            double h = Math.floor(pf.getImageableHeight() - 
                pf.getImageableY()) / (height * 1.0);

            double scale = Math.min(w, h);

            Graphics2D g2 = (Graphics2D) g;
            g2.translate(0, 0);
            g2.scale(scale, scale);
            g2.drawImage(img, 0, 0, (int)width, (int)height, null);

            return PAGE_EXISTS;
        }
    }, this.pj.validatePage(pf));

    // Get number of copies
    int nCopies = SetPrintQuantity.getPrintQuantity(new File(image));

    // Print
    if(nCopies != 0)
        for(int i = 0; i < nCopies; i++)
            this.pj.print(pras);

    System.out.println(nCopies + ((nCopies == 1) ? " copy" : " copies"));

this.pj = PrinterJob

Johnny
  • 31
  • 2
  • Unless the printer supports [full bleed](http://en.wikipedia.org/wiki/Bleed_%28printing%29), this may not be possible. – trashgod May 15 '12 at 05:33
  • I'm not sure if the printers can do full bleed but I know that I can get borderless prints by using the print function in Windows Image Viewer. So I guess my goal is to achieve something like that. – Johnny May 15 '12 at 06:28
  • I've got the same situation but on a Mac. `lp` from the command line has no problem printing a full bleed 4x6, but Java puts huge margins on each side which `setImageableArea` can't seem to remove. – Alexander Ljungberg Jan 30 '13 at 18:15

1 Answers1

2

I have been fighting the same problems for a while now. Here is my solution:

Determine the actual page size of your printer:

final PrinterJob printJob = PrinterJob.getPrinterJob();
printJob.setPrintService(ps);
final PageFormat pf = printJob.defaultPage();
System.out.println("Printer Page width=" + pf.getWidth() + " height=" + pf.getHeight());

For my HiTi P720L Photo Printers with 4"x6" paper it was actually 4.133"x6.147".

Create and set a new Paper object with the full page size and full imageable area:

final Paper paper = new Paper();
paper.setSize(pageWidth * 72.0f, pageHeight * 72.0f);
paper.setImageableArea(0.0, 0.0, paper.getWidth(), paper.getHeight());
pf.setPaper(paper);

Then the final trick, draw to x/y coordinates outside the range. In my case I had to scale the x coordinates by 10% and translate the x coordinate by -55 (placing it into negative x values).

printJob.setPrintable(new Printable() {
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
    Graphics2D g2 = (Graphics2D) graphics;
    final double xScale = 1.1;
    final double xTranslate = -55;
    final double yScale = 1;
    final double yTranslate = 0;
    final double widthScale = (pageFormat.getWidth() / image.getWidth()) * xScale;
    final double heightScale = (pageFormat.getHeight() / image.getHeight()) * yScale;
    System.out.println("Setting scale to " + widthScale + "x" + heightScale);
    final AffineTransform at = AffineTransform.getScaleInstance(widthScale, heightScale);
    System.out.println("Setting translate to " + xTranslate + "x" + yTranslate);
    at.translate(xTranslate, yTranslate);
    if (pageIndex != 0) {
        return NO_SUCH_PAGE;
    }
    g2.drawRenderedImage(image, at);
    return PAGE_EXISTS;
}
}, pf);
  • Where did you get the 10% / -55 dots? Trial and error? – Matthieu Dec 14 '20 at 09:35
  • @Matthieu did you use this code? wondering same 10% / -55 thing. for me the image size could be 4x8 or 4x5. So really want something so that i don't have to keep on changing logic for different image size. Also image size can change for different customers. – coder771 Jan 11 '22 at 15:10
  • @coder771 no I didn't, for that exact reason: page size is user-dependent and that looked like trial'n'error that should be changed for each paper size. And as those are not metric it makes the whole computation obscure and I didn't want to reverse-engineer it. Unfortunately user1224399 is not here anymore so I guess we'll never know... – Matthieu Jan 11 '22 at 15:26
  • @Matthieu have you implemented anything for this then? – coder771 Jan 11 '22 at 15:38
  • @coder771 no, I just arrived here to check information on how to handle margins. I guess you'll have to play with PDF printing and pages, like I did. – Matthieu Jan 11 '22 at 19:24