1

I am using JLabel to create an image file from a string.

I have to specify an image dimensions (label.setSize(width, height)), otherwise I get an exception:

java.lang.IllegalArgumentException: Width (0) and height (0) cannot be <= 0
    at java.awt.image.DirectColorModel.createCompatibleWritableRaster(DirectColorModel.java:1016)
    at java.awt.image.BufferedImage.<init>(BufferedImage.java:338)
    at com.shopsnips.portal.services.ImageCreator.createFromText(ImageCreator.java:31)
    at com.shopsnips.portal.services.ImageCreator.main(ImageCreator.java:18)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:601)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

I can control the font size using

label.setFont(new Font("Serif", Font.BOLD, 26));

When I use a font or text that is too large to fit the fixed dimentions, the label is truncated and "..." is included instead. Is there a way to identify the optimal/maximal font size that still fits in the dimensions I set?

Or alternatively, how can I find out whether the current settings (font size + dimensions) will cause the text to be truncated?

Here is some source:

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class ImageCreator {
    private ImageCreator(){}

    private final static String FONT = "Freestyle Script";

    public static void main(String[] args) {
        Path outputFile = Paths.get("c:\\tmp\\img\\test.png");

        createFromText("Hello World - this is a long text", outputFile, 150, 50);
    }

    /**
* <p>Create an image from text. <p/>
* <p/>
* https://stackoverflow.com/a/4437998/11236
*/
    public static void createFromText(String text, Path outputFile, int width, int height) {
        JLabel label = new JLabel(text, SwingConstants.CENTER);
        label.setSize(width, height);
        label.setFont(new Font(FONT, Font.BOLD, 24));

        BufferedImage image = new BufferedImage(
                label.getWidth(), label.getHeight(),
                BufferedImage.TYPE_INT_ARGB);

        Graphics g = null;
        try {
            // paint the html to an image
            g = image.getGraphics();
            g.setColor(Color.BLACK);
            label.paint(g);
        } finally {
            if (g != null) {
                g.dispose();
            }
        }

        // get the byte array of the image (as jpeg)
        try {
            ImageIO.write(image, "png", outputFile.toFile());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

Please log in to comment.

Community
  • 1
  • 1
ripper234
  • 222,824
  • 274
  • 634
  • 905

3 Answers3

2

1) put BuferedImage as Icon to the JLabel,

2) don't setSize let this job for LayoutManager

3) answer by @Jeffrey was too close to the correct answer, BuferedImage if exist can return both dimensions

4) for better help sooner please post a SSCCE, because I/we can't see code on your monitor, nor exceptions generated from your Java classes

mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I'm using the post I linked to ... it's pretty much a SSCCE. I can post my own code, it's very very very close to that. Just omit setting the dimensions. – ripper234 Jan 23 '12 at 20:02
  • And ... here's your SSCCE. I'll try out your answer tomorrow at work. https://gist.github.com/1665287 – ripper234 Jan 23 '12 at 20:08
  • 1) Something either 'is an SSCCE' or 'is **not** an SSCCE', there are no prizes for being 'close'. 2) People won't usually follow links to external sites like github. It is better to embed the source into the question as an edit. I have done that. – Andrew Thompson Jan 24 '12 at 02:01
  • @ripper234 all updates to the Swing GUI must be done on EDT, then you have to wrap output from background task to the invokeLater / invokeAndWait (sometimes depents) more http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html – mKorbel Jan 24 '12 at 06:01
  • Some answers/comments here disagree with you: http://stackoverflow.com/questions/8975533/is-creating-an-image-with-swing-thread-safe – ripper234 Jan 24 '12 at 08:01
  • ??? sorry I understood that you have problem with concurency `if(isEventDispatchThread)`, both threads talking about same issue, in some cases doesn't depends if method is declared as Thread-Safe, I see there code veriations where Thread-Safe methods setText(), must be wrapped into invokeLater / invokeAndWait http://stackoverflow.com/a/7208530/714968, you issue is hidded here http://stackoverflow.com/a/8084657/714968 with `myIcon.getImage().flush();` – mKorbel Jan 24 '12 at 08:26
2

label.setFont(new Font("Serif", Font.BOLD, 26)); ..Is there a way to identify the optimal/maximal font size that still fits in the dimensions I set?

For getting the size of text, look to FontMetrics or a GlyphVector.

A 'quick and dirty' way to get the size of text is to drop it into a label & interrogate the label for the preferred size.

Taking these figures, the font size can be adjusted accordingly.

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
0

I don't like any of the answers given (or there are not detailed enough for me to make use of right now).

Instead, I just used this heuristic to choose a font size:

private static int chooseFontSize(String text) {
    int largeFont = 28;
    int mediumFont = 22;
    int tinyFont = 16;
    if (text.length() > 25) {
        return tinyFont;
    }
    if (text.length() > 15) {
        return mediumFont;
    }
    return largeFont;
}
ripper234
  • 222,824
  • 274
  • 634
  • 905