Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaFX 2.2 Image support for .ico?

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).

like image 452
Spotted Avatar asked Feb 12 '15 10:02

Spotted


3 Answers

Feature Request

See the related feature request:

  • JDK-8092240 Support for the .ico file format

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.

like image 140
jewelsea Avatar answered Nov 10 '22 21:11

jewelsea


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);
like image 37
Harald K Avatar answered Nov 10 '22 19:11

Harald K


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);
like image 35
441653683 Avatar answered Nov 10 '22 19:11

441653683