问题
I am trying to print an image on 1 inch x 2 inch label with 300 dpi printing quality
public void print() {
RepaintManager currentManager = RepaintManager.currentManager(this);
currentManager.setDoubleBufferingEnabled(false);
PrinterJob job = PrinterJob.getPrinterJob();
try {
HashPrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
set.add(PrintQuality.HIGH);
set.add(MediaSize.findMedia(2.125f, 1f, MediaSize.INCH));
// 2" x 1" PrintableArea
set.add(new MediaPrintableArea(1f/16f, 0f, 2.0f, 1f, MediaPrintableArea.INCH));
set.add(new PrinterResolution(300, 300, ResolutionSyntax.DPI));
set.add(OrientationRequested.PORTRAIT);
job.setPrintable(this);
job.setJobName("Label");
job.print(set);
} catch (PrinterException e) {
// The job did not complete successfully
e.printStackTrace();
}
currentManager.setDoubleBufferingEnabled(true);
}
My BufferedImage is 300 x 600 pixels which should fit
BufferedImage bi = freeze(this); //getting BufferedImage from JPanel
System.out.println("Image dim: "+bi.getWidth()+" X "+bi.getHeight());
Console output: Image dim: 600 X 300.
But the problematic part is when i print out Imageable dimensions like
double x=pf.getImageableX();
double y=pf.getImageableY();
int w = (int)Math.round(pf.getImageableWidth());
int h = (int)Math.round(pf.getImageableHeight());
System.out.println("X: "+x);
System.out.println("Y: "+y);
System.out.println("W: "+w);
System.out.println("H: "+h);
the out put is:
X: 4.50141716003418
Y: 0.0
W: 144
H: 72
from h & w: I'm left with 72 pixel per inch here, and any resizing has no effect, this make no sense,
what is the useful of HashPrintRequestAttributeSet request for 300 DPI ?
回答1:
The API docs of PageFormat#getImageableHeight() clearly says:
Return the height, in 1/72nds of an inch, of the imageable area of the page. This method takes into account the orientation of the page.
(The API docs of getImageableWidth()
is similar.)
As you specified the printable area to be 2x1 inch (see MediaPrintableArea
attribute in your code), the imageable width and height is 144 resp. 72 (1/72nds of an inch).
There is no single word in the method docs about DPIs.
回答2:
The magic just happened, thanks to "Marty Hall" for this Tutorial "Printing Swing Components in Java 1.2" what i did is:
1- don't implement the printable interface on the same panel you want to print 2- Use a utility class (mentioned in the tutorial to do the job) 3- Use one graphic object to draw all the component (position images), don't stack/layout many components to paint the panel
@Override
public void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
RenderingHints rh = new RenderingHints(
RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
rh.put(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHints(rh);
// Grids for testing porpose
for(int i=50; i<=300; i+=50) {
g2d.drawLine(i, 0, i, 600);
g2d.drawString(""+i, i-20,20);
}
for(int i=100; i<=400; i+=100) {
g2d.drawLine(0, i, 300, i);
g2d.drawString(""+i, 10,i-10);
}
g2d.translate(0, 400);
BufferedImage barcodeImage=getBarCode128(String.valueOf(1234567));
g2d.drawImage(barcodeImage, 0, 0, 300, 200, null);
}
4- added HashPrintRequestAttributeSet to the print() method as "Marty Hall" class uses printDialog() to do that, which wasn't applicable for me
public void print() {
PrinterJob printJob = PrinterJob.getPrinterJob();
HashPrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
set.add(PrintQuality.HIGH);
set.add(MediaSize.findMedia(1f, 2.125f, MediaSize.INCH));
set.add(new MediaPrintableArea(0f, 1f/16f, 1f, 2.0f, MediaPrintableArea.INCH));
set.add(new PrinterResolution(300, 300, ResolutionSyntax.DPI));
set.add(OrientationRequested.PORTRAIT);
printJob.setPrintable(this);
try {
printJob.print(set);
} catch(PrinterException pe) {
System.out.println("Error printing: " + pe);
}
}
5-Do the translate and scale as desired then print the panel
public int print(Graphics g, PageFormat pf, int pageIndex) {
if (pageIndex > 0) {
return(NO_SUCH_PAGE);
} else {
Graphics2D g2d = (Graphics2D)g;
g2d.translate(pf.getImageableX(), pf.getImageableY());
g2d.scale(pf.getImageableWidth()/componentToBePrinted.getWidth(), pf.getImageableHeight()/componentToBePrinted.getHeight());
disableDoubleBuffering(componentToBePrinted);
componentToBePrinted.paint(g2d);
enableDoubleBuffering(componentToBePrinted);
return(PAGE_EXISTS);
}
}
the final result is high resolution image readable barcode
来源:https://stackoverflow.com/questions/59622698/java-printerjob-high-quality-printing-ends-up-with-72-dpi-anyway