17

So I'm making an application to store shortcuts to all the user's favorite applications, acting kind of like a hub. I can have support for actual files and I have a .lnk parser for shortcuts. I thought it would be pretty good for the application to support Internet shortcuts, too. This is what I'm doing:

Suppose I'm trying to get Google's icon (http://www.google.com/favicon.ico).

  1. I start out by getting rid of the extra pages (e.g. www.google.com/anotherpage would become www.google.com.

  2. Then, I use ImageIO.read(java.net.URL) to get the Image.

The problem is that ImageIO never returns an Image when I call this method:

String trimmed = getBaseURL(page); //This removes the extra pages
Image icon = null;    
try {
    String fullURLString = trimmed + "/favicon.ico";
    URL faviconURL = new URL(fullURLString);
    icon = ImageIO.read(faviconURL);
} catch (IOException e) {
    e.printStackTrace();
}

return icon;

Now I have two questions:

  1. Does Java support the ICO format even though it is from Microsoft?
  2. Why does ImageIO fail to read from the URL?

Thank you in advance!

mattbdean
  • 2,532
  • 5
  • 26
  • 58
  • [If no registered ImageReader claims to be able to read the resulting stream, null is returned.](http://docs.oracle.com/javase/6/docs/api/javax/imageio/ImageIO.html) – Beau Grantham Jun 18 '12 at 20:29
  • @HunterMcMillen No, can you explain that a bit? – mattbdean Jun 18 '12 at 20:29
  • are you sure that 'getBaseURL()' removes the last String too? If not, you are trying to get the image from www.google.com//favicon.ico. – 11684 Jun 18 '12 at 20:30
  • @11684 Yes, The URL's path is `http://www.google.com/favicon.ico`. – mattbdean Jun 18 '12 at 20:31
  • @whowantsakookie Well if none of the registered Image readers can read that format, you will get null returned. As mentioned in the page Beau is trying to link to. link: https://docs.oracle.com/javase/6/docs/api/javax/imageio/ImageIO.html#read%28java.net.URL%29 for some reason I get a 404 on his link – Hunter McMillen Jun 18 '12 at 20:31
  • @HunterMcMillen I got a 404... – 11684 Jun 18 '12 at 20:32
  • @HunterMcMillen Me too. Chrome doesn't like that link, but Firefox does. – mattbdean Jun 18 '12 at 20:33
  • @whowantsakookie That's weird, but yes I am using Firefox – Hunter McMillen Jun 18 '12 at 20:34
  • I meant the last /, but I think you understood me already – 11684 Jun 18 '12 at 20:36
  • I noticed that the URL class does not have a constructor with a signature `URL(java.net.URL)`. How is that compiling for you? – user845279 Jun 18 '12 at 20:59
  • @user845279 Oh sorry, just a copy and past problem. That was supossed to be `new URL(fullURLString)`. I'll change that. – mattbdean Jun 18 '12 at 21:05

4 Answers4

11

Try Image4J.

As this quick Scala REPL session shows (paste-able as Java code):

> net.sf.image4j.codec.ico.ICODecoder.read(new java.net.URL("http://www.google.com/favicon.ico").openStream())

res1: java.util.List[java.awt.image.BufferedImage] = [BufferedImage@65712a80: type = 2 DirectColorModel: rmask=ff0000 gmask=ff00 bmask=ff amask=ff000000 IntegerInterleavedRaster: width = 16 height = 16 #Bands = 4 xOff = 0 yOff = 0 dataOffset[0] 0]

UPDATE

To answer your questions: Does Java support ICO? Doesn't seem like it:

> javax.imageio.ImageIO.read(new java.net.URL("http://www.google.com/favicon.ico"))

java.lang.IllegalArgumentException: Empty region!

Why does ImageIO fail to read from the URL? Well, the URL itself seems to work for me, so you may have a proxy/firewall issue, or it could be the problem above.

opyate
  • 5,388
  • 1
  • 37
  • 64
  • @opyate It's a [bug](http://bugs.sun.com/view_bug.do;jsessionid=cf757a2e4d6ffffffff9113c0c3c674747?bug_id=6633448) in Java. ImageIO class tries to use `WBMPImageReader` as an ico parser but fails. The issue is documented with a couple of other formats (.mov for example). According to the bug report, the issue is fixed as of 7(b63). The workaround was to disable `WBMPImageReader`. – user845279 Jun 18 '12 at 22:43
  • Note that the code here will not work in all situations because ICODecoder (0.7, released in 2008 but still not updated) has a critical bug with how it reads from an InputStream, not checking the return value from read() (or checking it, and doing the wrong thing.) Using BufferedInputStream *may* avoid the situation, but I can't be sure whether read() from BufferedInputStream will return the data every time either, so I think the better thing to do is to read the entire icon into a byte[] and then give ICODecoder a ByteArrayInputStream. – Hakanai Mar 12 '13 at 03:24
5

Old post, but for future reference:

I've written a plugin for ImageIO that adds support for .ICO (MS Windows Icon) and .CUR (MS Windows Cursor) formats.

You can get it from GitHub here: https://github.com/haraldk/TwelveMonkeys/

After you have installed the plugin, you should be able to read the icon, using the code in the original post without any modifications.

Harald K
  • 26,314
  • 7
  • 65
  • 111
3

You don't need ImageIO for this. Just copy the bytes, same as for any other static resource.

user207421
  • 305,947
  • 44
  • 307
  • 483
0

There is Apache Commons Imaging for reading ico files and others: https://commons.apache.org/proper/commons-imaging/index.html

Reading an ico file works like this:

List<BufferedImage> images = org.apache.commons.imaging.Imaging.getAllBufferedImages(yourIcoFile);

In your case you have to download it first, I guess.

S. Doe
  • 685
  • 1
  • 6
  • 25