4

I wrote a program that generates a BufferedImage to be displayed on the screen and then printed. Part of the image includes grid lines that are 1 pixel wide. That is, the line is 1 pixel, with about 10 pixels between lines. Because of screen resolution, the image is displayed much bigger than that, with several pixels for each line. I'd like to draw it smaller, but when I scale the image (either by using Image.getScaledInstance or Graphics2D.scale), I lose significant amounts of detail.

I'd like to print the image as well, and am dealing with the same problem. In that case, I am using this code to set the resolution:

HashPrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
PrinterResolution pr = new PrinterResolution(250, 250, ResolutionSyntax.DPI);
set.add(pr);
job.print(set);

which works to make the image smaller without losing detail. But the problem is that the image is cut off at the same boundary as if I hadn't set the resolution. I'm also confused because I expected a larger number of DPI to make a smaller image, but it's working the other way.

I'm using java 1.6 on Windows 7 with eclipse.

OscarRyz
  • 196,001
  • 113
  • 385
  • 569
Ingrid
  • 41
  • 1
  • 1
  • 2

5 Answers5

3

Regarding the image being cut-off on the page boundary, have you checked the clip region of the graphics? I mean try :

System.out.println(graphics.getClipBounds());

and make sure it is correctly set.

Bobby
  • 11,419
  • 5
  • 44
  • 69
Charouti
  • 31
  • 2
1

I had the same problem. Here is my solution.

First change the resolution of the print job...

    PrinterJob job = PrinterJob.getPrinterJob();
    // Create the paper size of our preference
    double cmPx300 = 300.0 / 2.54;
    Paper paper = new Paper();
    paper.setSize(21.3 * cmPx300, 29.7 * cmPx300);
    paper.setImageableArea(0, 0, 21.3 * cmPx300, 29.7 * cmPx300);
    PageFormat format = new PageFormat();
    format.setPaper(paper);
    // Assign a new print renderer and the paper size of our choice !
    job.setPrintable(new PrintReport(), format);

    if (job.printDialog()) {
        try {
            HashPrintRequestAttributeSet set = new HashPrintRequestAttributeSet();
            PrinterResolution pr = new PrinterResolution((int) (dpi), (int) (dpi), ResolutionSyntax.DPI);
            set.add(pr);
            job.setJobName("Jobname");
            job.print(set);
        } catch (PrinterException e) {
        }
    }

Now you can draw everything you like into the new high resolution paper like this !

    public class PrintReport implements Printable {

    @Override
    public int print(Graphics g, PageFormat pf, int page) throws PrinterException {
        // Convert pixels to cm to lay yor page easy on the paper...
        double cmPx = dpi / 2.54;
        Graphics2D g2 = (Graphics2D) g;
        int totalPages = 2; // calculate the total pages you have...
        if (page < totalPages) {

            // Draw Page Header
            try {
                BufferedImage image = ImageIO.read(ClassLoader.getSystemResource(imgFolder + "largeImage.png"));
                g2.drawImage(image.getScaledInstance((int) (4.8 * cmPx), -1, BufferedImage.SCALE_SMOOTH), (int) (cmPx),
                        (int) (cmPx), null);
            } catch (IOException e) {
            }
            // Draw your page as you like...
            // End of Page
            return PAGE_EXISTS;
        } else {
            return NO_SUCH_PAGE;
        }
    }
brokenGear
  • 11
  • 3
0

Code for Convert image with dimensions using Java and print the converted image.

Class: ConvertImageWithDimensionsAndPrint.java

package com.test.convert;

import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

public class ConvertImageWithDimensionsAndPrint {
    private static final int IMAGE_WIDTH = 800;
    private static final int IMAGE_HEIGHT = 1000;

public static void main(String[] args) {
    try {
        String sourceDir = "C:/Images/04-Request-Headers_1.png";
        File sourceFile = new File(sourceDir);
        String destinationDir = "C:/Images/ConvertedImages/";//Converted images save here
        File destinationFile = new File(destinationDir);
        if (!destinationFile.exists()) {
            destinationFile.mkdir();
        }
        if (sourceFile.exists()) {
            String fileName = sourceFile.getName().replace(".png", "");
            BufferedImage bufferedImage = ImageIO.read(sourceFile);
            int type = bufferedImage.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : bufferedImage.getType();

            BufferedImage resizedImage = new BufferedImage(IMAGE_WIDTH, IMAGE_HEIGHT, type);
            Graphics2D graphics2d = resizedImage.createGraphics();
            graphics2d.drawImage(bufferedImage, 0, 0, IMAGE_WIDTH, IMAGE_HEIGHT, null);//resize goes here
            graphics2d.dispose();

            ImageIO.write(resizedImage, "png", new File( destinationDir + fileName +".png" ));

            int oldImageWidth = bufferedImage.getWidth();
            int oldImageHeight = bufferedImage.getHeight();
            System.out.println(sourceFile.getName() +" OldFile with Dimensions: "+ oldImageWidth +"x"+ oldImageHeight);
            System.out.println(sourceFile.getName() +" ConvertedFile converted with Dimensions: "+ IMAGE_WIDTH +"x"+ IMAGE_HEIGHT);

            //Print the image file
            PrintActionListener printActionListener = new PrintActionListener(resizedImage);
            printActionListener.run();
        } else {
            System.err.println(destinationFile.getName() +" File not exists");
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

Reference of PrintActionListener.java

package com.test.convert;

import java.awt.Graphics;
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;

public class PrintActionListener implements Runnable {

private BufferedImage image;

public PrintActionListener(BufferedImage image) {
    this.image = image;
}

@Override
public void run() {
    PrinterJob printJob = PrinterJob.getPrinterJob();
    printJob.setPrintable(new ImagePrintable(printJob, image));

    if (printJob.printDialog()) {
        try {
            printJob.print();
        } catch (PrinterException prt) {
            prt.printStackTrace();
        }
    }
}

public class ImagePrintable implements Printable {

    private double x, y, width;

    private int orientation;

    private BufferedImage image;

    public ImagePrintable(PrinterJob printJob, BufferedImage image) {
        PageFormat pageFormat = printJob.defaultPage();
        this.x = pageFormat.getImageableX();
        this.y = pageFormat.getImageableY();
        this.width = pageFormat.getImageableWidth();
        this.orientation = pageFormat.getOrientation();
        this.image = image;
    }

    @Override
    public int print(Graphics g, PageFormat pageFormat, int pageIndex) throws PrinterException {
        if (pageIndex == 0) {
            int pWidth = 0;
            int pHeight = 0;
            if (orientation == PageFormat.PORTRAIT) {
                pWidth = (int) Math.min(width, (double) image.getWidth());
                pHeight = pWidth * image.getHeight() / image.getWidth();
            } else {
                pHeight = (int) Math.min(width, (double) image.getHeight());
                pWidth = pHeight * image.getWidth() / image.getHeight();
            }
            g.drawImage(image, (int) x, (int) y, pWidth, pHeight, null);
            return PAGE_EXISTS;
        } else {
            return NO_SUCH_PAGE;
        }
    }

}

}

Output:

04-Request-Headers_1.png OldFile with Dimensions: 1224x1584
04-Request-Headers_1.png ConvertedFile converted with Dimensions: 800x1000

After conversion of a image a Print window will be open for printing the converted image. The window displays like below, Select the printer from Name dropdown and Click OK button.

Print Window

Community
  • 1
  • 1
UdayKiran Pulipati
  • 6,579
  • 7
  • 67
  • 92
0

It sounds like your problem is that you are making the grid lines part of the BufferedImage and it doesn't look good when scaled. Why not use drawLine() to produce the grid after your image has been drawn?

Justin
  • 4,437
  • 6
  • 32
  • 52
  • I'm not sure exactly what you're suggesting. Maybe that I should scale the image, then draw the lines? I don't want to scale the image or the lines, and my screen and printer both have plenty of DPI to display all the detail. I mentioned the lines, but there are also lots of small (10 pixels square) icons which become indistinct if I scale by 1/2. It's not making sense to me that this isn't easy (presumably it is easy, and I just don't know how to do it). – Ingrid Jun 17 '10 at 01:02
  • Printable provides a Graphics2D object: `public int print(Graphics g, PageFormat pf, int page)`. Instead of rendering your page as a huge pixelated image, render it as vector graphics calls: e.g. multiple `g.drawLine()` and `g.drawImage()` calls. – Justin Jun 17 '10 at 11:43
  • I'll try that and see how it looks. If I'm understanding correctly though, this will just make the less detailed display look better. Is there no way to display and print all of the detail? – Ingrid Jun 17 '10 at 18:38
  • You can only print the detail which is in the image to begin with. This should add infinite detail to line elements. If individual icons have more detail than the resolution of your giant BufferedImage this will fix that too. – Justin Jun 17 '10 at 18:56
  • Thank you for your patience! I was mistaken about the screen display. You're right that it's just displaying what I'm asking it to, and there's no way to make it smaller without losing detail. But am still not able to print the detail I want. I put all of the detail that I wanted into my original image. When printing, it prints huge, using multiple dots for each pixel. I can use PrinterResolution to make it draw smaller without losing detail, but the image is being cut off where the page boundary would be if I hadn't set the resolution. – Ingrid Jun 17 '10 at 19:33
  • Figured it out! I needed to use Pageable instead of Printable. That way, I can set the Paper, and setImageableArea to bigger than the paper. That way, when I use PrinterResolution, it will not cut off my image. – Ingrid Jun 18 '10 at 01:09
-1

You can use either of the following to improve the quality of the scaling. I believe BiCubic gives better results but is slower than BILINEAR.

g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);

I would also not use Image.getScaledInstance() as it is very slow. I'm not sure about the printing as I'm struggling with similar issues.

Jay Askren
  • 10,282
  • 14
  • 53
  • 75