I want to make the graphics (icons, logo etc.) of an existing Java Swing application look better on HiDPI displays with a scale factor larger than 1.0, e.g. my notebook with 14" display and Windows 10 (scale factor 1.5). At the moment, the application uses PNG images, with one resolution per image, e.g. 16x16 pixels for icons. On JButtons etc. these icons look horrible when they are scaled up by Java.
My current idea (A) to solve that problem (see [1] and [2] for credits):
- Replace PNGs with SVGs.
- Include Apache Batik in the Swing desktop application (~ 4 megabytes of new JAR dependencies just for that, ughh).
- Use Batik to rasterize the SVGs at runtime to multiple
BufferedImage
s, one for each scale factor (1.0, 1.25, 1.5, ...) to be supported. - Put the
BufferedImage
s (e.g. 16x16, 20x20, 24x24, ...) into a standardBaseMultiResolutionImage
.
A slightly different idea (B) might be:
- and 4.: Instead: Extend
AbstractMultiResolutionImage
and overwritegetResolutionVariant
to rasterize just the requesteddestImageWidth
/destImageHeight
pixel size using Batik (and cache the result with width/height as cache key). This way, any requesteddestImageWidth
/destImageHeight
could be provided exactly. This might be useful, as there seem to be some rounding effects causing dest width or height to differ by 1 or 2 pixels from what I'd expect.
Both approaches above require Batik (and its transitive dependencies) as a runtime dependency / to be included in my client distribution. And I'm like: Do I really want that just because of some simple icons?! (= just eye candy)
Therefore, idea C: On my dev system, I might use rsvg-convert
or Inkscape to "precompile" different resolution PNGs from a source SVG (e.g. 16x16, 20x20, 24x24, ...). Then I include the PNGs (not the source SVG) in my application and build a BaseMultiResolutionImage
just from the precompiled PNGs. This approach offers the huge advantage of not needing Batik. But it's more manual work and not as flexible.
Question: Is there maybe a best practice approach or a pure Java solution (maybe in Java 17..20...?) for this as supporting HiDPI seems to be a very common thing? Or what is your solution for this problem?