9

I'm doing a piece of code in java and I need to get different sizes of system icons of files. I know that for getting file system icons, i should use this:

File file = new File("Whatever.txt");
FileSystemView view = FileSystemView.getFileSystemView();
Icon icon = view.getSystemIcon(file);

but this code returns the smallest size of icon. What sholud I do for getting other sizes?

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
mehrmoudi
  • 1,096
  • 1
  • 11
  • 22
  • 1
    To the best of my knowledge, the other icons are not supported in Java. If you want them, raise an RFE with Oracle to add a method that provides the `Icon[]`. – Andrew Thompson Feb 06 '12 at 23:11
  • @AndrewThompson can you explain it a bit more please? – mehrmoudi Feb 07 '12 at 18:01
  • Can you be more specific? What do you not understand? – Andrew Thompson Feb 07 '12 at 18:18
  • @AndrewThompson Yeah, sure. I just need to get all different sizes and image of icons of a single file, as it is shown in the OS default file browser or explorer, etc. With the code I mentioned above, only smallest icon is returned; you said for solving the problem, I can raise an RFE with Oracle to add a method that provides the Icon[]. You sure it will give me what I want? If so, I don't know what's RFE and almost the whole stuff you said! – mehrmoudi Feb 08 '12 at 08:40
  • 2
    *"You sure it will give me what I want?"* If you specify it well, and Oracle can & does implement it. RFE - 'Request For Enhancement' - you raise one via the [bug database](http://bugs.sun.com/). Follow the link then follow the instructions (described at the end of the link). BTW - note that even if Oracle did implement it, it would not be available until at least Java 8. ;) – Andrew Thompson Feb 08 '12 at 08:48

4 Answers4

1

For 32x32 Icon you can use ShellFolder.

sun.awt.shell.ShellFolder.getShellFolder( file ).getIcon( true ) 

Or use a JNI Api . Both "solutions" already discuted here

Community
  • 1
  • 1
fhofmann
  • 847
  • 7
  • 15
0

I encountered the same issue of needing high-resolution icons. After an hour of digging, I think the answer is quite clear, albeit quite unfortunate.

  1. There is currently no native library support.
  2. Native support is expected on Java version 12.
  3. There is no reliable third-party library anywhere that I can find, even after extensive searching.

A ticket of this issue has already been submitted here on JDK bug system, but it seems pretty low on their priority list.


However, there does seem to be workarounds:

I am assuming you are using Windows. Finding the icon file on Linux is trivial because the icon is stored separately and linked in the desktop entry.

  1. Extract the icon using a third-party command line exe tool, like this one or this one, to a temporary directory. You can use Runtime.exec().
  2. Use a .ico reader library like the ones suggested here to read all the image files it contains into BufferedImage in a List.
  3. Iterate through the list to find the image with highest resolution.
  4. Delete temporary files.

Update

Just implemented my workaround and it worked. Here's the code snippet. I used iconsext.exe and image4j in my implementation.

    // Extract icons and wait for completion.
    File iconDir = new File("tempIcons");
    String[] iconsextCmd = { "iconsext.exe", "/save", exeFile.getPath(), iconDir.getPath(), "-icons" };
    Process iconsextProc = Runtime.getRuntime().exec(iconsextCmd);
    iconsextProc.waitFor();

    // Get all icons, sort by ascending name, and pick first one.
    File[] icons = iconDir.listFiles();
    Arrays.sort(icons, (f1, f2) -> f1.getName().compareTo(f2.getName()));
    File defaultIcon = icons[0];

    // Read images from icon.
    List<ICOImage> iconImgs = ICODecoder.readExt(defaultIcon);

    // Sort images by descending size and color depth, and pick first one.
    iconImgs.sort((i1, i2) -> (i2.getWidth() * i2.getHeight() * 33 + i2.getColourDepth())
            - (i1.getWidth() * i1.getHeight() * 33 + i1.getColourDepth()));
    BufferedImage awtImg = iconImgs.get(0).getImage();

    // Delete temporary icons.
    for (File i : icons)
    {
        i.delete();
    }
    iconDir.delete();

Throw in some JavaFX code:

Nice and big icons

Nice and big icons!


The workaround is messy and complicated, I know. And it does negate Java's cross-platform benefits, but to be honest it is the best I can think of. Hope it helps.

cyqsimon
  • 2,752
  • 2
  • 17
  • 38
  • doesn't this only extract the system-default icons? what if i needed the steam icon? on the iconsextract page it says it has an option to [Copy a single icon to the clipboard], that might be handy here but unfortunately the page itself is rather archaik – clockw0rk Sep 13 '20 at 01:28
0

I have created a library called JIconExtractReloaded which can extract all icons sizes not only 32x32. Here is the link https://github.com/MrMarnic/JIconExtractReloaded.

Just write:

BufferedImage image = JIconExtract.getIconForFile(128,128,"C:\\Windows\\explorer.exe");

And you have the icon.

MrMarnic
  • 23
  • 6
0

If you're looking for how to do this on a Mac, you can use a third-party library Quaqua

import java.awt.image.BufferedImage;
import java.io.File;

public class SystemIconMac {
    public static BufferedImage getIconImage(File file, int size) {
        return  ch.randelshofer.quaqua.osx.OSXFile.getIconImage(file, size);
    }
}
Charlie
  • 8,530
  • 2
  • 55
  • 53