i currently have an issue with my printerjob, it works great for portrait images, but for landscape images, it cuts part of the image and fills in a white space instead.
Don't use PageFormat#getWidth
or PageFormat#getHeight
, use PageFormat#getImageableWidth
and PageFormat#getImageableHeight
instead
From the JavaDocs
Return the height/width, in 1/72nds of an inch, of the imageable area of the page. This method takes into account the orientation of the page.
You should also translate the printer Graphics
by the ImageableX/Y
...
g2.translate((int)pageFormat.getImageableX(), (int)pageFormat.getImageableY());
Runnable example
This is a simple runnable example. This code was able to take the original (left) and print it both in portrait and landscape without issue...
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
public class PrintTest100 {
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
try {
PrinterJob pj = PrinterJob.getPrinterJob();
pj.setJobName(" Print Component ");
PageFormat pf = pj.defaultPage();
// pf.setOrientation(PageFormat.LANDSCAPE);
// pf = pj.validatePage(pf);
pj.setPrintable(new ImagePrintable(ImageIO.read(new File("..."))), pf);
if (!pj.printDialog()) {
return;
}
try {
pj.print();
} catch (PrinterException ex) {
ex.printStackTrace();
}
} catch (IOException exp) {
exp.printStackTrace();
}
}
});
}
public static class ImagePrintable implements Printable {
private int currentPage = -1;
private Image cachedScaledImage = null;
private BufferedImage master;
public ImagePrintable(BufferedImage master) {
this.master = master;
}
public double getScaleFactor(int iMasterSize, int iTargetSize) {
double dScale = 1;
if (iMasterSize > iTargetSize) {
dScale = (double) iTargetSize / (double) iMasterSize;
} else {
dScale = (double) iTargetSize / (double) iMasterSize;
}
return dScale;
}
public double getScaleFactorToFit(BufferedImage img, Dimension size) {
double dScale = 1;
if (img != null) {
int imageWidth = img.getWidth();
int imageHeight = img.getHeight();
dScale = getScaleFactorToFit(new Dimension(imageWidth, imageHeight), size);
}
return dScale;
}
public double getScaleFactorToFit(Dimension original, Dimension toFit) {
double dScale = 1d;
if (original != null && toFit != null) {
double dScaleWidth = getScaleFactor(original.width, toFit.width);
double dScaleHeight = getScaleFactor(original.height, toFit.height);
dScale = Math.min(dScaleHeight, dScaleWidth);
}
return dScale;
}
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
int result = Printable.NO_SUCH_PAGE;
if (pageIndex == 0) {
result = Printable.PAGE_EXISTS;
Graphics2D graphics2D = (Graphics2D) graphics;
graphics2D.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
int width = (int) Math.round(pageFormat.getImageableWidth());
int height = (int) Math.round(pageFormat.getImageableHeight());
if (currentPage != pageIndex || cachedScaledImage == null) {
currentPage = pageIndex;
double scaleFactor = getScaleFactorToFit(new Dimension(master.getWidth(), master.getHeight()), new Dimension(width, height));
int imageWidth = (int) Math.round(master.getWidth() * scaleFactor);
int imageHeight = (int) Math.round(master.getHeight() * scaleFactor);
cachedScaledImage = master.getScaledInstance(imageWidth, imageHeight, Image.SCALE_SMOOTH);
}
double x = ((pageFormat.getImageableWidth() - cachedScaledImage.getWidth(null)) / 2);
double y = ((pageFormat.getImageableHeight() - cachedScaledImage.getHeight(null)) / 2);
graphics2D.drawImage(cachedScaledImage, (int) x, (int) y, null);
graphics2D.setColor(Color.RED);
graphics2D.drawRect(0, 0, width - 1, height - 1);
}
return result;
}
}
}
nb: I had an issue with Yosemite, trying to figure out how to change the print orientation from the dialog, in the end, I gave up and forced it by changing the PageFormat
from the PrintJob
. I've used this same type of code in countless applications without issues before...
Updated
Original Image: 1920x1200