Cannot load image from file name using method Toolkit.getDefaultToolkit().getImage(filename); - java

I have problem to load image by file name by using method Toolkit.getDefaultToolkit().getImage(filename); MediaTracker return false which means there is no image loaded isn't? How to solve this problem? Thanks in advance. Below is my code:
String name = "example.jpg";
File inputFile = new File(UPLOAD_DIRECTORY + File.separator + name);
BufferedImage thumbImage = getThumbnail(name, 200, 120, 0, name);
File outputfile = new File(UPLOAD_DIRECTORY + File.separator + "2"+name);
ImageIO.write(thumbImage, "jpg", outputfile);
getThumbnail method :
private static BufferedImage getThumbnail(String filename, int thumbWidth, int thumbHeight, int quality, String outFileName)
throws InterruptedException, FileNotFoundException, IOException {
//load image from filename
Image image = Toolkit.getDefaultToolkit().getImage(filename);
MediaTracker mediaTracker = new MediaTracker(new Container());
mediaTracker.addImage(image, 0);
mediaTracker.waitForID(0);
// use this to test for errors at this point:
System.out.println(mediaTracker.isErrorAny());
//determine thumbnail size from WIDTH and HEIGHT
double thumbRatio = (double)thumbWidth / (double)thumbHeight;
int imageWidth = image.getWidth(null);
int imageHeight = image.getHeight(null);
double imageRatio = (double)imageWidth / (double) imageHeight;
if (thumbRatio < imageRatio){
thumbHeight = (int)(thumbWidth / imageRatio);
} else{
thumbWidth = (int)(thumbHeight * imageRatio);
}
//draw original image to thumbnail image object and
//scale it to the new size
BufferedImage thumbImage = new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
//save thumbnail image to outFileName
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(outFileName));
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.getDefaultJPEGEncodeParam(thumbImage);
quality = Math.max(0, Math.min(quality, 100));
param.setQuality((float)quality / 100.0f, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(thumbImage);
out.close();
return thumbImage;
}

Shouldn't
BufferedImage thumbImage = getThumbnail(name, 200, 120, 0, name);
be
BufferedImage thumbImage = getThumbnail(UPLOAD_DIRECTORY + File.separator + name, 200, 120, 0, name);
?

Image img = Toolkit.getDefaultToolkit().getImage(URL or file path);
The Toolkit is a class in the java.awt package that provides various resources and tools for the display system. One of the Toolkit methods is getImage() that functions much like the getImage() method in the Applet class. It is overloaded to take either a String filename parameter specifying the location of the image file or a URL parameter identifying the image file.
Before calling getImage(), one must have a reference to the Toolkit instance in use. The static method Toolkit.getDefaultToolkit() returns a reference to that Toolkit.

Related

PDFBox and chinese characters

I am using pdfbox 1.8 and I am trying to fill a pdf form with chinese character but all I got is strange characters. I got a ttc file (uming.ttc) and using font forge I exported ttf file (right now I am tryng to use only one of the exported fonts).
Loading of the fonts is done using
InputStream is = ..
PDTrueTypeFont font = PDTrueTypeFont.loadTTF(doc, is);
and I am writing the pdf field using the following code (that I found here in stackoverflow but currently I can't found it)
protected void setPDFFieldAndFont(String fieldName, String keyFontName, Object... values) {
try {
PDField pdField = pdfForm.getField(fieldName);
if (pdField == null) {
return;
}
// append fields to create a new textfield
Filler filler = new Filler();
filler.append(values);
String textFieldString = filler.toString();
String fontName = key2FontName.get(keyFontName);
COSDictionary dict = pdField.getDictionary();
COSString defaultAppearance = (COSString) dict
.getDictionaryObject(COSName.DA);
if (defaultAppearance != null)
{
dict.setString(COSName.DA, "/" + fontName + " 11 Tf");
}
if (pdField instanceof PDTextbox)
{
PDTextbox textbox = new PDTextbox(pdfForm, dict);
//PDTextbox textbox = (PDTextbox) pdField;
textbox.setValue(textFieldString);
}
} catch (IOException e) {
throw new IllegalStateException("Invalid field name: " + fieldName, e);
}
}
I have read that pdfbox2.0 supports unicode do I need to use this new version ?
Using font-forge I have seen that my ttf font has encoding ISO-10646-1.
Thanks for any help
EDITED
As asked by Tilman Hausherr I tried EmbeddedFonts.java and it works fine but I am filling the form in a different way. I created a main sample:
public static void main(String[] args) throws IOException {
String pdfform = "D:\\form.pdf";
PDDocument doc = PDDocument.load(new File(pdfform));
PDType0Font font = PDType0Font.load(doc, new File("D:\\fonts\\UMingCN.ttf"));
PDAcroForm acroForm = doc.getDocumentCatalog().getAcroForm();
PDResources res = acroForm.getDefaultResources();
if (res == null){
res = new PDResources();
}
COSName fontName = res.add(font);
acroForm.setDefaultResources(res);
PDField pdField = acroForm.getField("personalInformation_fullName");
if (pdField == null) {
return;
}
COSDictionary dict = pdField.getCOSObject();
COSString defaultAppearance = (COSString) dict.getDictionaryObject(COSName.DA);
if (defaultAppearance != null)
{
dict.setString(COSName.DA, "/" + fontName.getName() + " 11 Tf");
}
if (pdField instanceof PDTextField)
{
PDTextField textbox = new PDTextField(acroForm);
textbox.getCOSObject().addAll(dict);
textbox.setValue("保保保");
}
doc.save("example2.pdf");
doc.close();
}
but it does not fill anything. In debug the code goes to textbox.setValue but the pdfform saved does not have the value set in the pdf.
Probably I am missing something ..
Thanks again
I solved the issues with PdfBox and chinese (japanese, korean, and any other font) by turning text into image, like this
void writeLine(String text, int x, int y, int width, int height,
Font font, Color color, PDPageContentStream contentStream, PDDocument document) throws IOException {
try (
ByteArrayOutputStream baos = new ByteArrayOutputStream()
) {
int scale = 2;
BufferedImage img = new BufferedImage(width * scale, height * scale, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = img.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_SPEED);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
g2d.setFont(font);
g2d.setColor(color);
g2d.scale(scale,scale);
g2d.drawString(text, 0, g2d.getFontMetrics().getAscent());
g2d.dispose();
ImageIO.write(img, "png", baos);
baos.flush();
baos.close();
contentStream.drawImage(PDImageXObject.createFromByteArray(
document,baos.toByteArray(), ""), x, y, width, height);
}
}

Write multi line text on an image using Java

I looked at java.awt.Graphics documentation, stackoverflow, could not find a solution. I have in input two things, an image file and the multi line text (paragraph). I need to write the multi line text on the image file and then save it as a new image. Wondering if I am missing something really simple here.
I am open to using any good third party libraries as well.
final BufferedImage image = ImageIO.read(new File("c:/anil/Lenna.png"));
Graphics g = image.getGraphics();
g.setFont(g.getFont().deriveFont(30f));
g.drawString("Hello world", 100, 100);
g.dispose();
Above code writes just a single line on the image.
if you want to draw several lines you have to do it explicitly...
so first step is to 'detect' lines
String str = ... //some text with line breaks;
String [] lines = str.spilt("\n"); //breaking the lines into an array
second step is to draw all lines
Graphics g = image.getGraphics();
g.setFont(g.getFont().deriveFont(30f));
int lineHeight = g.getFontMetrics().getHeight();
//here comes the iteration over all lines
for(int lineCount = 0; lineCount < lines.length; lineCount ++){ //lines from above
int xPos = 100;
int yPos = 100 + lineCount * lineHeight;
String line = lines[lineCount];
g.drawString(line, xpos, yPos);
}
g.dispose();
JLabel accepts simple html to format text. Then you can paint it on your image:
JLabel l=new JLabel("<html>line1<br>line2");
l.setSize(l.getPrefferedSize());
g.translate(10,10); // fixed location
l.paint(g);
edit: complete example
public class OP_32110247 extends JPanel {
private final JLabel l = new JLabel();
private final BufferedImage image;
public OP_32110247(String imgfile, String txt) throws IOException {
image = ImageIO.read(new URL(imgfile));
l.setText(txt);
l.setFont(getFont().deriveFont(Font.BOLD,30f));
l.setSize(l.getPreferredSize());
l.setForeground(Color.GREEN);
Dimension d = new Dimension(image.getWidth(), image.getHeight());
setPreferredSize(d);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension d = getSize();
g.drawImage(image, 0, 0, null);
//place text in center of image
g.translate((d.width-l.getWidth())/2, (d.height-l.getHeight())/2);
l.paint(g);
}
public static void main(String[] args) throws IOException {
String txt = "<html>line1<br>line2";
String image = "http://kysoft.pl/proj/java/j+c.png";
JFrame f = new JFrame();
f.setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
f.setContentPane(new OP_32110247(image,txt));
f.pack();
f.setVisible(true);
}
}
The best solution is to extend JLabel and override paintComponent. Create the Label with the image required. After calling super.paintComponent draw your text, each line positioning below another using the font metrics. Something like below:
class ImageWithTextLabel extends JLabel {
List<String> lines = new ArrayList<>();
Point textPosition = new Point(0,0);
private Font textFont;
private ImageWithTextLabel(Icon image) {
super(image);
}
public void addText(String text) {
lines.add(text);
}
public void setTextPosition(Point textPosition) {
this.textPosition = textPosition;
}
#Override protected void paintComponent(Graphics g) {
super.paintComponent(g);
int from = textPosition.y ;
g.setFont(textFont);
for (String line : lines) {
g.drawString(line, textPosition.x, from);
from += g.getFontMetrics().getHeight();
}
}
public void setTextFont(Font font) {
textFont = font;
}
}
see Drawing Multiple Lines of Text(Oracle Java Tutorials) and complete code
use LineBreakMeasurer:
int width = 400;
int height = 500;
BufferedImage bufferedImage = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bufferedImage.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setColor(Color.MAGENTA);
Hashtable<TextAttribute,Object> map = new Hashtable<TextAttribute,Object>();
map.put(TextAttribute.FAMILY, "微软雅黑");
map.put(TextAttribute.SIZE,new Float(18.0));
AttributedString vanGogh = new AttributedString(
"Many people 中国 believe that Vincent van Gogh painted his best works " +
"during the two-year period he spent in Provence. Here is where he " +
"painted The Starry Night--which some consider to be his greatest " +
"work of all. However, as his artistic brilliance reached new " +
"heights in Provence, his physical and mental health plummeted. ",
map);
AttributedCharacterIterator paragraph = vanGogh.getIterator();
int paragraphStart = paragraph.getBeginIndex();
int paragraphEnd = paragraph.getEndIndex();
FontRenderContext frc = g2d.getFontRenderContext();
LineBreakMeasurer lineMeasurer = new LineBreakMeasurer(paragraph, frc);
float breakWidth = 250f;
float drawPosY = 20;
float drawPosx = 0f;
lineMeasurer.setPosition(paragraphStart);
while(lineMeasurer.getPosition()< paragraphEnd ){
TextLayout layout = lineMeasurer.nextLayout(breakWidth);
drawPosx = layout.isLeftToRight()?0:breakWidth-layout.getAdvance();
drawPosY += layout.getAscent();
layout.draw(g2d,drawPosx,drawPosY);
drawPosY += layout.getDescent() + layout.getLeading();
}
g2d.dispose();
File file = new File("myimage.png");
ImageIO.write(bufferedImage,"png",file);
file = new File("myimage.jpg");
ImageIO.write(bufferedImage,"jpg",file);

bad output(monocolor) with Java Advanced Imaging api

I m having a sample image(sorry for the type of image) which i m feeding into JAI code to get a compressed image.
Now the output image i m getting is in mono-color. I don't know why is the output is abnormal but other images are getting processed just fine.
The sample original and processed images are -
Original Image -
Processed Image -
The JAI code to process the image -
private static final String JAI_STREAM_ACTION = "stream";
private static final String JAI_SUBSAMPLE_AVERAGE_ACTION = "SubsampleAverage";
private static final String JAI_ENCODE_FORMAT_JPEG = "JPEG";
private static final String JAI_ENCODE_ACTION = "encode";
private static final String JPEG_CONTENT_TYPE = "image/jpeg";
private int mMaxWidth = 800;
//private int mMaxWidthThumbnail = 150;
private byte[] resizeImageAsJPG(byte[] pImageData, int pMaxWidth) throws IOException {
InputStream imageInputStream = new ByteArrayInputStream(pImageData);
SeekableStream seekableImageStream = SeekableStream.wrapInputStream(imageInputStream, true);
RenderedOp originalImage = JAI.create(JAI_STREAM_ACTION, seekableImageStream);
((OpImage) originalImage.getRendering()).setTileCache(null);
int origImageWidth = originalImage.getWidth();
double scale = 1.0;
/*
if (pMaxWidth > 0 && origImageWidth > pMaxWidth) {
scale = (double) pMaxWidth / originalImage.getWidth();
} */
ParameterBlock paramBlock = new ParameterBlock();
paramBlock.addSource(originalImage); // The source image
paramBlock.add(scale); // The xScale
paramBlock.add(scale); // The yScale
paramBlock.add(0.0); // The x translation
paramBlock.add(0.0); // The y translation
RenderingHints qualityHints = new RenderingHints(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
RenderedOp resizedImage = JAI.create(JAI_SUBSAMPLE_AVERAGE_ACTION, paramBlock, qualityHints);
BufferedImage scaledImage = null ;
ByteArrayOutputStream encoderOutputStream = new ByteArrayOutputStream();
JAI.create(JAI_ENCODE_ACTION, resizedImage, encoderOutputStream, JAI_ENCODE_FORMAT_JPEG, null);
//byte[] resizedImageByteArray = encoderOutputStream.toByteArray();
System.out.println("This is from exiting JAI");
return encoderOutputStream.toByteArray();
}
With imgScalr I m also getting the same output.
In openJDK with JAI I get the error -
javax.media.jai.util.ImagingException: All factories fail for the operation "encode"
With imgScalr in openJDK-
javax.imageio.IIOException: Invalid argument to native writeImage
Any other library i can use in java to get the desired result.
Regards
The solution is to convert the image to 3Byte_BGR -
private synchronized BufferedImage getScaledImage1(BufferedImage imageBytes)
{
BufferedImage scaledImage = null;
int type = 0;
try
{
type = imageBytes.getType();
if(type == 0 || type ==6) {
int w = imageBytes.getWidth();
int h = imageBytes.getHeight();
BufferedImage newImage =
new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
Graphics2D g = newImage.createGraphics();
g.drawImage(imageBytes, 0, 0, null);
g.dispose();
imageBytes = newImage;
}
scaledImage = Scalr.resize(imageBytes, Scalr.Method.ULTRA_QUALITY,2000,
Scalr.OP_ANTIALIAS);
} catch(Exception e) {
}
return scaledImage;
}

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.
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.
here's my code, note I am using Scalr.
private String autoResizeImage(String image, int width, int dpi, String prefix) throws IllegalArgumentException, ImagingOpException, IOException {
File file = new File(image);
BufferedImage img = ImageIO.read(file);
BufferedImage result = Scalr.resize(img, Scalr.Method.SPEED, Scalr.Mode.FIT_TO_WIDTH, width, Scalr.OP_ANTIALIAS);
File outputfile = new File(prefix);
PNGEncodeParam penc = PNGEncodeParam.getDefaultEncodeParam(result);
double meter2inchRatio = 1d / 0.0254d;
int dim = (int) (dpi * meter2inchRatio) + 1;
penc.setPhysicalDimension(dim, dim, 1);
// resize orginal image
JAI.create("filestore", result, outputfile.getAbsolutePath(), "PNG", penc);
return outputfile.getAbsolutePath();
}

java setting resolution and print size for an Image

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.
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.
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;
}
}
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?
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.
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.

Categories