I need to print a 1800 x 1200 pixels, 300 dpi image on 4" x 6" paper (also known as 4r)
What I have Tried
I have created a PrintRequestAttributeSet
which takes care of my PrintableArea
(4 x 6), Printer print DPI
, Orientation
. I have attached a MCVE at the bottom.
Problem
While the code works, and I get a PageFormat
with the following attributes(for my printer) :
x= 12.0
y= 12.32
w= 276.0
h= 419.67
The width and height are little less, because my printer doesn't support Zero Margin
. (This is what I have considered. If anyone is aware of a way other than this through which I can force zero margin, please let me know)
I am supplying the margin as 0
, because these images will be printed via printers which support zero margin(Photobooth Printers).
aset.add(new MediaPrintableArea(0, 0, 4, 6, MediaPrintableArea.INCH));
The printable area including the margin is roughly 4 x 6 as required. The problem occurs when I scale the image to print inside the printable area.
Since image is 1800 x 1200, it supports an aspect ratio of 3:2, which means the image is created to get printed on a 4 x 6 paper(after getting rotated and scaled). For Reference.
Now, since the pageWidth and pageHeight of the PageFormat
are not exactly divisible by the ImageWidth and ImageHeight. I am getting scaling issues.
Note : I rotate the image because it has to be printed on 4 x 6 and not 6 x 4.
The image which is supposed to take 4 x 6 space is taking somewhere close to 4 x 5. The image size is also reduced drastically.
How do I overcome this issue?
Code
Please find the MCVE here :
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
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.print.attribute.HashPrintRequestAttributeSet;
import javax.print.attribute.PrintRequestAttributeSet;
import javax.print.attribute.standard.MediaPrintableArea;
import javax.print.attribute.standard.OrientationRequested;
import javax.print.attribute.standard.PrintQuality;
import javax.print.attribute.standard.PrinterResolution;
public class ImgPrinter implements Printable {
Image img;
@Override
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
throws PrinterException {
Graphics2D g2d = (Graphics2D) graphics;
g2d.translate((int) (pageFormat.getImageableX()),
(int) (pageFormat.getImageableY()));
if (pageIndex == 0) {
double pageWidth = pageFormat.getImageableWidth();
double pageHeight = pageFormat.getImageableHeight();
/**
* Swapping width and height, coz the image is later rotated
*/
double imageWidth = img.getHeight(null);
double imageHeight = img.getWidth(null);
double scaleX = pageWidth / imageWidth;
double scaleY = pageHeight / imageHeight;
g2d.scale(scaleX, scaleY);
g2d.rotate(Math.toRadians(90), img.getWidth(null) / 2,
img.getHeight(null) / 2);
g2d.drawImage(img, 0, 0, null);
return Printable.PAGE_EXISTS;
}
return Printable.NO_SUCH_PAGE;
}
public void printPage(String file, String size) {
try {
Image img = ImageIO.read(new File(file));
this.img = img;
PrintRequestAttributeSet aset = createAsetForMedia(size);
PrinterJob pj = PrinterJob.getPrinterJob();
PageFormat pageFormat = pj.getPageFormat(aset);
pj.setPrintable(this, pageFormat);
pj.print();
} catch (PrinterException ex) {
ex.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private PrintRequestAttributeSet createAsetForMedia(String size) {
PrintRequestAttributeSet aset = null;
try {
aset = new HashPrintRequestAttributeSet();
aset.add(PrintQuality.NORMAL);
aset.add(OrientationRequested.PORTRAIT);
/**
* Suggesting the print DPI as 300
*/
aset.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
/**
* Setting the printable area and the margin as 0
*/
if (size.equals("3r")) {
aset.add(new MediaPrintableArea(0, 0, 3, 5,
MediaPrintableArea.INCH));
} else if (size.equals("4r")) {
aset.add(new MediaPrintableArea(0, 0, 4, 6,
MediaPrintableArea.INCH));
} else if (size.equals("5r")) {
aset.add(new MediaPrintableArea(0, 0, 5, 7,
MediaPrintableArea.INCH));
} else if (size.equals("6r")) {
aset.add(new MediaPrintableArea(0, 0, 6, 8,
MediaPrintableArea.INCH));
}
} catch (Exception e) {
e.printStackTrace();
}
return aset;
}
public static void main(String[] args) {
new ImgPrinter().printPage("/Some_URL/sam.jpg",
"4r");
}
}
To run the program, just supply a 1800x1200 image path to the main program and it will print to the default printer.
4*72=288
and height as6*72=432
(as everything is 72dpi in java). But the image gets distorted. Its prints a image of 3.7 x 4 and uses a printable area of 4 x 5.2. The print quality was also decreased drastically. The link to the edited code. I am not sure, if I am using the correct process to convert from and back to BufferedImage to Image. – Railhead