Is there out any Java library that allows converting text content to image files? I only know of ImageMagick (JMagick in this case) but I wouldn't like to install any external binaries (my app will be deployed as a .war file in a Tomcat server so I don't want any other dependencies more than Java).
For example, from the string "Hello", I would like to generate this simple image:
From the Format Shape pane >>>Select text options at the top >>>Then select the underlined letter A >>> select “tile picture as texture” it will scale the photo to fit the text.
The Graphics 2D API should be capable of achieving what you need. It has some complex text handling capabilities as well.
import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics2D; import java.awt.RenderingHints; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; public class TextToGraphics { public static void main(String[] args) { String text = "Hello"; /* Because font metrics is based on a graphics context, we need to create a small, temporary image so we can ascertain the width and height of the final image */ BufferedImage img = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = img.createGraphics(); Font font = new Font("Arial", Font.PLAIN, 48); g2d.setFont(font); FontMetrics fm = g2d.getFontMetrics(); int width = fm.stringWidth(text); int height = fm.getHeight(); g2d.dispose(); img = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 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_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_QUALITY); g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE); g2d.setFont(font); fm = g2d.getFontMetrics(); g2d.setColor(Color.BLACK); g2d.drawString(text, 0, fm.getAscent()); g2d.dispose(); try { ImageIO.write(img, "png", new File("Text.png")); } catch (IOException ex) { ex.printStackTrace(); } } }
Also check out Writing/Saving and Image
WARNING I used this to generate 90k PNG images only to find that they can be viewed in IE but not in Chrome Version 70.0.3538.77
The above code works just fine for me (I changed the text color to WHITE
so I could see it in chrome)
I was using Chrome 70.0.3538.77 on Mac OS Mojave 10.14 using Java 10.0.2. The resulting image was 4778x2411 pixels ...
On IE that is black on white but on Chrome that is black on black. Yet I set background to white.
So what you're telling me is, a transparent PNG is been displayed differently on different browsers, because the browsers use different default backgrounds ... why are you surprised by this?
The original solution, deliberately, used a transparent based image. This is evident by the use of BufferedImage.TYPE_INT_ARGB
when creating the image, which is applying a Alpha (A
) based RGB
color model.
This is unexpected as there is g2d.setBackground(Color.white).
No, actually, it is entirely expected, if only you understood what setBackground
actually does and how it should be used
From the JavaDocs
Sets the background color for the Graphics2D context. The background color is used for clearing a region. When a Graphics2D is constructed for a Component, the background color is inherited from the Component. Setting the background color in the Graphics2D context only affects the subsequent clearRect calls and not the background color of the Component. To change the background of the Component, use appropriate methods of the Component.
From the "sounds" of things, you want a non-transparent image, with a filled background color. So, once again, it's off to the JavaDocs and a little bit of reading would have lead you to BufferedImage.TYPE_INT_RGB
, which removes the Alpha channel, but you'd still have to fill the background of the image.
For this, I'd use Graphics2D#setColor
and Graphics2D#fillRect
, only because it works.
So, you'd end up with a modified version of the above which might look something like...
img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); g2d = img.createGraphics(); //... g2d.setColor(Color.WHITE); g2d.fillRect(0, 0, img.getWidth(), img.getHeight()); g2d.setColor(Color.BLACK); g2d.drawString(text, 0, fm.getAscent()); g2d.dispose(); try { ImageIO.write(img, "png", new File("Text.png")); } catch (IOException ex) { ex.printStackTrace(); }
If I change to "jpg" then I get orange/pink text on black background on both IE and Chrome
Well, this is related to a well known, and sadly, common issue/bug in ImageIO
, which attempts to apply the alpha channel of transparent color models to the JPG, which doesn't support alpha channels.
See Issue using ImageIO.write jpg file: pink background for more details.
But the basic solution is to either use PNG, which supports alpha channels, or to use a non-transparent image.
So, the long and short of all this is. The problem is NOT with the original answer, nor is it with ImageIO
, BufferedImage
, Graphics
, the AWT library, Chrome or IE, but with your lack of understanding of how these APIs (and the example) works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With