Java 9 hdpi display support - multi-resolution images - name convention and loading in Windows
Asked Answered
C

1

36

According to these articles:

http://news.kynosarges.org/2015/06/29/javafx-dpi-scaling-fixed
https://twitter.com/michaelsamarin/status/729234779292483584

Java 9 should support high DPI displays (automatic DPI scaling) in Swing. I have tested it on the last version of Java 9 Early Access + on Zulu 9 and it works and looks really great.

I was unable to solve only one thing - high resolution/retina image loading.

According to articles (links) above and below it should use an Apple name convention (@2x):

image.png, [email protected], [email protected], etc.

I tested these loading methods:

Toolkit.getDefaultToolkit().getImage(getClass().getClassLoader().getResource("something/image.png"));

and

ImageIO.read(getClass().getResource("/something/image.png"));

But none of these works (the only base image was loaded and blurred).

According to this:

https://netbeans.org/bugzilla/show_bug.cgi?id=239745

The first method should be promising.

Has anyone any experiences with this (using Swing or even JavaFX)? I'm not sure if I'm doing something wrong or this feature is not implemented to the current pre-release version of Java 9 sofar.


Update:

It should be possible:

http://openjdk.java.net/jeps/263

I've also tried following naming conventions (described here):

Windows : image.scale-<dpi-value>.png (image.scale-140.png)
Linux : image.java-scale2x.png
Mac : [email protected] and image.java-scale2x.png

However, I cannot find any working solution or official information. I don't get it - hdpi displays are common today and Java applications look like s... on them.

Crossland answered 6/8, 2016 at 9:49 Comment(15)
@2x probably meant to work when referenced by url from JavaFX style, not when using programmatic API to load the image in generic way.Nostril
Based on the articles referencing JavaFX, I'd say that the support is based on JavaFX only, you'll probably need to define your own methods, perhaps taking a path, name and extensionGabriella
@Gabriella The article is about Java version 8u60, the first version with fully automatic DPI scaling for JavaFX - there is no support for this for Swing in this version. But there is in Java 9 and I would doubt they will make two name conventions (one for JavaFX and another for Swing). Moreover the third article (NetBeans) is about Swing (about a multi resolution image loading) and conventions are the same (it's for Mac, but JavaFX took it to Windows obviously) - look at this: netbeans.org/bugzilla/show_bug.cgi?id=239745#c5Crossland
Based on everything I've read, I'm not sure ImageIO will support this directly and all of this relates to Apple's retina displays, you don't highlight if that's the hardware you're usingGabriella
You might also want to provide a runnable example, an example of the images and the structure of your project for people to play with ;)Gabriella
Base upon MultiResolutionImage, it provides access to the images, i've not seen an examples, so I'm unsure if implementations of MultiResolutionImage are required (or expeceted) to use the "best fit" image automaticallyGabriella
Have you tried using BaseMultiResolutionImage?Tax
@Tax Emigh BaseMultiResolutionImage with a manual (in code) filling by images works. But I would like to have the application compatible with older Java versions (ok - It would be manageable using some reflection mess, but I would like to leave this as the last resort).Crossland
@Crossland I'm confused. You want the DPI support that Java 9 added to be accessible in an older version? Like, a work-around?Tax
Also, in regards to "I don't get it - hdpi displays are common today and Java applications look like s... on them." - Java does support GUI, but that doesn't mean the support is up to standards/expectation. I generally only use Java for back-end, long/continuously-running applications like servers. You may want to consider using a different toolkit or language for your presentation layer.Tax
@Tax Emigh Yes, I want to use new feature that Java 9 offers (for users whose have it), but I don't want to disable users with older versions. The hdpi naming convention should serve exactly this purpose - you do not change a code, but only add new resources (like in Android or iOS).Crossland
@Gabriella AbstractMultiResolutionImage lists an example in the javadocChenee
@MarkJeronimus I think the problem is they want a “backwards compatible” based solution, one where they don’t need to change existing code to make it workGabriella
Good luck with that. Java 9 and up completely broke HiDPI backwards compatibility with no possible workarounds*. (even if code compiled with 8 is run on JVM 9) You either make your HiDPI code work on JVM 8 or JVM 9+ but can't for both. (*there still are open bug reports regarding this)Chenee
@Mark Jeronimus Yes, the only working solution for Java 8 and 9 (as far as I know) is reflection and BaseMultiResolutionImage.Crossland
A
9

As part of HiDPI support, Java 9 introduced multi-resolution support via the java.awt.MultiResolutionImage interface and the java.awt.image.AbstractMultiResolutionImage et al classes. Although they're supported in Swing, there have been bugs and misunderstandings in this area.

Those don't exist in earlier Java versions, so if you want your users to be able to continue to run with earlier runtimes, you're going to have to write code to use regular Image classes when running on earlier JREs.

To use those, you do something like:

  • Start with a set of images are different resolutions:

enter image description here

  • Then create and load the MultiResolutionImage:

    List<Image> imgList = new ArrayList<Image>();
    imgList.add(ImageIO.read(new File("320px-Eagle.jpg"));
    imgList.add(ImageIO.read(new File("800px-Eagle.jpg"));
    imgList.add(ImageIO.read(new File("1024px-Eagle.jpg"));
    imgList.add(ImageIO.read(new File("1280px-Eagle.jpg"));
    imgList.add(ImageIO.read(new File("Eagle.jpg"));
    MultiResolutionImage mrImage = new BaseMultiResolutionImage(imgList.toArray(new Image[0]));
    
  • The use the mrImage object just like any other image.

There's nothing automatic about the naming convention: The image resolution is taken from the image file contents.

Animalism answered 28/6, 2018 at 17:27 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.