How to get favicon.ico from a website using Java?
Asked Answered
B

4

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!

Boogeyman answered 18/6, 2012 at 20:25 Comment(11)
If no registered ImageReader claims to be able to read the resulting stream, null is returned.Impropriate
@HunterMcMillen No, can you explain that a bit?Boogeyman
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.Stenographer
@Stenographer Yes, The URL's path is http://www.google.com/favicon.ico.Boogeyman
@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: docs.oracle.com/javase/6/docs/api/javax/imageio/… for some reason I get a 404 on his linkTeheran
@HunterMcMillen I got a 404...Stenographer
@HunterMcMillen Me too. Chrome doesn't like that link, but Firefox does.Boogeyman
@whowantsakookie That's weird, but yes I am using FirefoxTeheran
I meant the last /, but I think you understood me alreadyStenographer
I noticed that the URL class does not have a constructor with a signature URL(java.net.URL). How is that compiling for you?Kristiankristiansand
@Kristiankristiansand Oh sorry, just a copy and past problem. That was supossed to be new URL(fullURLString). I'll change that.Boogeyman
B
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.

Brittney answered 18/6, 2012 at 21:53 Comment(2)
@Brittney It's a bug 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.Kristiankristiansand
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.Riven
M
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.

Mneme answered 23/12, 2013 at 15:22 Comment(0)
W
3

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

Wheelwright answered 2/12, 2013 at 2:20 Comment(0)
L
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.

Lamellibranch answered 22/9, 2020 at 6:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.