Categories
Javascript JQuery

Preloading Images with JavaScript

Sometimes in a complex javascript-application you want to display an image when it is fully loaded. Until then you want to show for example a common loading-imageAjax Loading Image. In this case the best solution is to load the image in background, and then show it to the use. For that you can use the Image-Class provided by the browsers.

This class is the used Class at img-Tags. So you have all known properties, like “src”. With the onload-Event you can then check, if the image was fully loaded or not. An example would be:

?View Code JAVASCRIPT
1
2
3
var image = new Image();
$(image).load(function () { alert("picture is fully loaded."); });
image.src="http://www.javahelp.info/wp-content/uploads/2009/11/Bild-80-300x64.png";

In the example I use JQuery for event-handling, because this is more comfortable as the normal event-method of JavaScript.

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.