1

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.

blurry text

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.

0 Answers0