Categories
Java

Loading TTF-Fonts with Java

It is very easy to load some TrueType-Fonts (TTF) with Java.

1
java.awt.Font.createFont(Font.TRUETYPE_FONT, new File("font.ttf"));

But with some files I got the following Exception:

1
java.awt.FontFormatException: Font name not found

You can correct this with a font-editor to add the font names. For Linux I can advise the tool fontforge. It is very powerful also for convertions of fonts. For Debian you can simply install with the following command:

1
apt-get install fontforge
Categories
Java

Reading JPEGs with CMYK profile

Today I tried to read a JPEG with the ImageIO-Library, provided by the JRE. But instead of a wonderful image I only received the following exception:

1
2
3
4
5
6
7
8
java.lang.IllegalArgumentException: bandOffsets.length is wrong!
	at javax.imageio.ImageTypeSpecifier$Interleaved.< init >(ImageTypeSpecifier.java:382)
	at javax.imageio.ImageTypeSpecifier.createInterleaved(ImageTypeSpecifier.java:495)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.getImageTypes(JPEGImageReader.java:743)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.readInternal(JPEGImageReader.java:935)
	at com.sun.imageio.plugins.jpeg.JPEGImageReader.read(JPEGImageReader.java:912)
	at javax.imageio.ImageIO.read(ImageIO.java:1400)
	at javax.imageio.ImageIO.read(ImageIO.java:1322)

With an EXIF-Reader (by the way a nice website) I tried to analyze the picture and saw the picture includes an embedded color profile “(unrecognized embedded color profile ‘SWOP (Coated), 20%’)”. A little bit more research showed the currently unresolved bugs in the JRE (especially ImageIO-Library; #4799903 and #5100094). So I’m not the only person, who had the problem. There are some code snippets and bug workarounds on the net trying to convert CMYK or YCCK to RGB. For my picture the CMYK-Solution doesn’t work, because the JRE means the embedded ICC profile doesn’t match the given raster (raster contains 3 bytes per pixel, but CMYK 4 bytes). But Werner Randelshofer wrote that it is important to use the given ICC, because of unexpectable color problems. So just to use a fix conversion method is not the wanted solution.

Then I tried first not to use the ImageIO library, but to give AWT-Toolkit a try. I was very surprised, that this function can correctly read the given image. So I didn’t need to handle the embedded ICC profiles directly. I modified my code to use this method, if ImageIO fails. The resulting code looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    private BufferedImage readImage(InputStream picture) throws IOException {
        ByteArrayOutputStream buf = new ByteArrayOutputStream();
        byte[] b = new byte[10240];
        int l = 0;
        while ((l = picture.read(b)) >= 0) {
            buf.write(b, 0, l);
        }
        buf.close();
        byte[] picturedata = buf.toByteArray();
        buf = null;
        try {
            return ImageIO.read(new ByteArrayInputStream(picturedata));
        } catch (IllegalArgumentException e) {
                ImageInputStream input = ImageIO
                        .createImageInputStream(new ByteArrayInputStream(
                                picturedata));
                Iterator< ImageReader > readers = ImageIO.getImageReaders(input);
                ImageReader reader = null;
                while (readers.hasNext()) {
                    reader = (ImageReader) readers.next();
                    if (reader.canReadRaster())
                        break;
                }
 
                if (reader == null)
                    throw new IOException("no reader found");
                // Set the input.
                reader.setInput(input);
                int w = reader.getWidth(0);
                int h = reader.getHeight(0);
                BufferedImage image;
                image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
                Image intImage = Toolkit.getDefaultToolkit().createImage(
                        picturedata);
                new ImageIcon(intImage);
                Graphics2D g = image.createGraphics();
                g.drawImage(intImage, 0, 0, null);
                g.dispose();
                return image;
        }
    }

The Toolkit-Method also has no problems on servers without an X11 server.

Categories
Java

Drawing aliased lines with Java

Java provides a very flexible API for drawing images. This API also support aliased drawing of lines, text, etc. To activate it, you have to set the RenderingHints of the Graphics-Object (line 3). After that all operations results in aliased objects. To draw half pixels, you can use g.scale or g.translate with double-values.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
        BufferedImage image = new BufferedImage(200,200,BufferedImage.TYPE_INT_ARGB);
        Graphics2D g = image.createGraphics();
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g.setColor(Color.white);
        g.fillRect(0, 0, 199, 199);
        g.setColor(Color.black);
        double step = 2.5;
        g.scale(step, 1);
        for (int i = 0; i &lt; (int)(200/step); i++) {
            if (i % 2 == 1) {
                g.fillRect(0, 0, 1, 199);
            }
            g.translate(1, 0);
        }
        ImageIO.write(image, "png", new File("test.png"));