Java PrinterJob, high quality printing ends up with 72 DPI anyway

天涯浪子 提交于 2020-02-06 07:52:05

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!