Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java - set DPI to print image

I have a bunch of .jpg images and I want to print them (on paper with ink), at a fixed size (in cm). Let's say image1.png is 400x600 pixels and I want to print it at 300 dpi. I've tried using PrinterJob and Printable implementation, but it seems I can't specify DPI. Here is the code snippets:

PrinterJob job = PrinterJob.getPrinterJob();

job.setPrintable(new PrintableDeck(cardDB));

PrintRequestAttributeSet attr = new HashPrintRequestAttributeSet();
attr.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
attr.add(new MediaPrintableArea(8,21,210-16,296-42,MediaPrintableArea.MM));
attr.add(MediaSizeName.ISO_A4);
attr.add(new Copies(1));
attr.add(OrientationRequested.PORTRAIT);
attr.add(PrintQuality.HIGH);
//attr.add(Fidelity.FIDELITY_TRUE);

job.print(attr);

and

public class PrintableDeck implements Printable {

    BufferedImage image;

    public PrintableDeck(DB cardDB){
        // This load an image into 'image'            
        BufferedImage image = cardDB.getCard(5462).getBufferedImage();
    }

    public int print(Graphics graphics, PageFormat pf, int page)
    throws PrinterException{

        if(page>0){
            return NO_SUCH_PAGE;
        }

        Graphics2D g2 = (Graphics2D) graphics;
        g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);

        double pageHeight = pf.getImageableHeight();
        double pageWidth = pf.getImageableWidth();

        // This print ONLY ~596x842, as if page is 72 DPI
        System.out.println("Imageable WH: "+pageWidth+" x "+pageHeight);

        // This print correctly 400x600
        System.out.println("Image: "+images.get(0).getWidth(null)+" x "+images.get(0).getHeight(null));

        g2.drawImage(image, 0, 0, null);
        g2.dispose();


        return PAGE_EXISTS;
    }
}

As you can see above, I have PageFormat.getImageableHeight() ~ 842 and PageFormat.getImageableWidth() ~ 595. If page would be 300 DPI, I expected these values to be much higher, about 3000 x 2500. What I am missing?

Thank you so much.

like image 898
Sebastian Ikaros Rizzo Avatar asked Mar 21 '26 13:03

Sebastian Ikaros Rizzo


1 Answers

Java sets the image's DPI to the default java 72dpi if there is no previously a defined DPI in the image's meta data, so it was better than scalling your image to its dimensions in the java 72dpi default resolution, it is better to add your 300dpi resolution to your image meta data, thus, it would be adjusted in the better resolution in the right printable area dimensions, and that is besides setting printer resolution, media size, and media printable area attributes, You may set the dpi to your saved image with such method in http://www.javased.com/?post=321736 :

private void saveGridImage(File output,BufferedImage gridImage) throws IOException {
    output.delete();

    final String formatName = "png";

    for (Iterator<ImageWriter> iw = ImageIO.getImageWritersByFormatName(formatName); iw.hasNext();) {
       ImageWriter writer = iw.next();
       ImageWriteParam writeParam = writer.getDefaultWriteParam();
       ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
       IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
       if (metadata.isReadOnly() || !metadata.isStandardMetadataFormatSupported()) {
          continue;
       }

       setDPI(metadata);

       final ImageOutputStream stream = ImageIO.createImageOutputStream(output);
       try {
            writer.setOutput(stream);
            writer.write(metadata, new IIOImage(gridImage, null, metadata), writeParam);
         } finally {
           stream.close();
         }
         break;
    }
}

private void setDPI(IIOMetadata metadata) throws IIOInvalidTreeException {

    double INCH_2_CM = 2.54;

       // for PMG, it's dots per millimeter
    double dotsPerMilli = 1.0 * DPI / 10 / INCH_2_CM;

    IIOMetadataNode horiz = new IIOMetadataNode("HorizontalPixelSize");
    horiz.setAttribute("value", Double.toString(dotsPerMilli));

    IIOMetadataNode vert = new IIOMetadataNode("VerticalPixelSize");
    vert.setAttribute("value", Double.toString(dotsPerMilli));

    IIOMetadataNode dim = new IIOMetadataNode("Dimension");
    dim.appendChild(horiz);
    dim.appendChild(vert);

    IIOMetadataNode root = new IIOMetadataNode("javax_imageio_1.0");
    root.appendChild(dim);

    metadata.mergeTree("javax_imageio_1.0", root);
}

Then add printing attributes such :

   attr.add(new PrinterResolution(300, 300, PrinterResolution.DPI));
   attr.add(new MediaPrintableArea(8,21,210-16,296-42,MediaPrintableArea.MM));
   attr.add(MediaSizeName.ISO_A4);

To have better quality of image's view and resolution.

like image 123
Hamza Muhammed Avatar answered Mar 24 '26 04:03

Hamza Muhammed



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!