JavaFX 2.2 Image support for .ico?
Asked Answered
S

3

8

I am developing an application that must have a custom icon. The provided icon is the same in all sizes (256x256, 48x48, 32x32) except in 16x16 where the icon is simplified.

I thought about the .ico format (where I can store all the differents icons and let the OS showing the best) but it doesn't seem to be supported by the javafx.scene.image (I haven't found any confirmation about that).

Here is how I set up my icon

stage.getIcons().add(new Image(getClass().getResourceAsStream("/path/to/icon.ico")));

In this case the icon is never displayed. If I convert this icon into a .png image, this works but enforces to always display the same icon (even in 16x16).

Is there a way in JavaFX 2.2 to display a .ico (even in an hacky way) or do I have to use other image formats ?

Update

I separated my .ico into multiple png (one for each size) and then loading them one by one.

stage.getIcons().add(new Image(getClass().getResourceAsStream("/path/to/icon_16x16.png")));
stage.getIcons().add(new Image(getClass().getResourceAsStream("/path/to/icon_256x256.png")));

The 256x256 and the 16x16 are two different images but the 16x16 is never showed in the top left of the application (despite this is the nearest size).

Sportsman answered 12/2, 2015 at 10:16 Comment(0)
G
9

Feature Request

See the related feature request:

The feature is currently not allocated to a release, but you can vote or comment on it if you like.

Loading ico files using third party libraries

In the meantime, you can use various utilities for creating icons in java.awt.image.BufferedImage format and then convert them to JavaFX using SwingFXUtils. haraldK provides a sample of this approach in his answer. Another example is the fav icon fetcher for the willow browser, which uses the image4j library, though haraldK's twelve monkeys library is likely the better library to use. Your other alternative is to port the source of one of the awt based icon libraries to JavaFX, making use of a WritableImage.

Advice

Your reasoning for not using png because it always displays 16x16 is a bit strange to me, because the stage.getIcons() documentation returns a list of images you can add to (you aren't limited to adding single icon). From the javadoc:

Gets the icon images to be used in the window decorations and when minimized. The images should be different sizes of the same image and the best size will be chosen, eg. 16x16, 32,32.

Additional question

What if, depending on the size, the image is not always the same

It's probably OK to provide different images. If the system interpolates provided images to create icons of sizes which are not provided, that could cause an issue - but I think that it is highly unlikely that the system would do that. "Images should be different sizes of the same image" is more of a guideline than an actual rule. If you need different images at different sizes, try supplying multiple png images for that and see what happens.

Gilbreath answered 12/2, 2015 at 12:2 Comment(4)
+1 For mentioning the fact that you can use just multiple PNGs (which is what we usually do). I already voted though, so I can't give you an extra point... ;-) PS: Why is the Kenai JIRA password protected?Beseech
@haraldK It is not just password protected. It just needs you to sign up before reading/posting anything. Though, it doesn't make sense why did they make it compulsory for read access.Granuloma
@Gilbreath With this method, all the images should be the same image (but with different sizes). What if, depending on the size, the image is not always the same ?Sportsman
@Gilbreath I tried to supply multiple images at different sizes but the behaviour is a bit strange: the choosen image seems always to be the biggest (downscaled when needed).Sportsman
B
5

I don't think JavaFX supports the ICO format directly. I'm pretty sure the list is JPEG, GIF and PNG only, but I've yet to find an official source that confirms this.

However, you could use my ICO plugin for ImageIO to read the ICO file, and convert the image to an FX Image using SwingFXUtils.toFXImage(bufferedImage, null).

Note that the reader simply returns the icons in the order they are found in the ICO file, so ImageIO.read(...) will not give you the icon you want (it will only read the first). Instead you need to read each icon, convert and add all the icons to your stage. And FX will select correct size for you. :-)

Something like:

ImageInputStream stream = ImageIO.createImageInputStream(getClass().getResourceAsStream("/path/to/icon.ico"));
ImageReader reader = ImageIO.getImageReaders(stream).next();

reader.setInput(stream);
int count = reader.getNumImages(true);

List<Image> fxImages = new ArrayList<>(count);

for (int i = 0; i < count; i++) {
    BufferedImage bufferedImage = reader.read(i, null);
    Image fxImage = SwingFXUtils.toFXImage(bufferedImage, null);
    fxImages.add(fxImage);
}

stream.close(); // Remember to close/dispose in a finally block
reader.dispose();

// ...

stage.getIcons().addAll(fxImages);
Beseech answered 12/2, 2015 at 10:26 Comment(2)
I upvoted your answer but I'll finally go with multiple png (pre-calculated) instead of doing this calculation for each execution.Sportsman
@Sportsman Makes sense to me. :-)Beseech
H
1

Use image4j:

ArrayList<Image> lImages = new ArrayList<>();
ICODecoder.read(Global.FILE_ICON).stream().forEach((lBufferedImage) -> lImages.add(SwingFXUtils.toFXImage(lBufferedImage, null)));
this.getStage().getIcons().addAll(lImages);
Hang answered 11/6, 2015 at 7:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.