I'm trying to write a String to a BufferedImage but it is either horribly pixelated (without antialiasing) or blurry (with antialiasing).
I've tried increasing the DPI when I write the image to an OutputStream and whilst there is some improvement - it's still not great.
Here is the code to generate the image:
BufferedImage generateImage(String text) throws IOException {
Font font = new Font("Arial", Font.BOLD, 10);
int height;
int width;
BufferedImage temp = new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB);
Graphics2D tempGraphics = temp.createGraphics();
tempGraphics.setFont(font);
FontMetrics metrics = tempGraphics.getFontMetrics();
height= metrics.getHeight();
width = metrics.stringWidth(text);
final BufferedImage image = new BufferedImage(height + 1, width + 1, BufferedImage.TYPE_INT_RGB);
final Graphics2D graphics = image.createGraphics();
graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
graphics.setFont(FONT);
graphics.setColor(Color.WHITE);
graphics.fillRect(0, 0, width + 1, heigth + 1);
graphics.setColor(Color.BLACK);
graphics.drawString(text, 1, metrics.getAscent() + 1.5f);
graphics.dispose();
return image;
}
And here is the code to write the image to a byte array:
byte[] imageToOutputStream(BufferedImage image) throws IOException {
ImageWriter writer = ImageIO.getImageWritersByFormatName("jpeg").next();
ImageWriteParam writeParam = writer.getDefaultWriteParam();
ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, writeParam);
setDpi(metadata);
writeParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
writeParam.setCompressionQuality(1f);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageOutputStream ios = ImageIO.createImageOutputStream(baos);
writer.setOutput(ios);
writer.write(metadata, new IIOImage(image, null, metadata), writeParam);
baos.toByteArray();
}
And finally the code to set the DPI of the metadata used to write the image:
void setDpiJpg(IIOMetadata metadata) throws IIOInvalidTreeException {
String metadataFormat = "javax_imageio_jpeg_image_1.0";
IIOMetadataNode root = new IIOMetadataNode(metadataFormat);
IIOMetadataNode jpegVariety = new IIOMetadataNode("JPEGvariety");
IIOMetadataNode markerSequence = new IIOMetadataNode("markerSequence");
IIOMetadataNode app0JFIF = new IIOMetadataNode("app0JFIF");
app0JFIF.setAttribute("majorVersion", "1");
app0JFIF.setAttribute("minorVersion", "2");
app0JFIF.setAttribute("thumbWidth", "0");
app0JFIF.setAttribute("thumbHeight", "0");
app0JFIF.setAttribute("resUnits", "01");
app0JFIF.setAttribute("Xdensity", String.valueOf(300));
app0JFIF.setAttribute("Ydensity", String.valueOf(300));
root.appendChild(jpegVariety);
root.appendChild(markerSequence);
jpegVariety.appendChild(app0JFIF);
metadata.mergeTree(metadataFormat, root);
}
I've read here that it has something to do with the scale of the image but I must admit I'm lost.