Is there a way to get the icon of a running X program? When you switch between windows, you could see the icon of it, e.g through xfwm4.
4 Answers
This works for me. Might not work with all applications and all window managers. The pam format is at least supported by ImageMagick, so you can view it with display and convert it to other formats if need be with convert:
xprop -notype 32c _NET_WM_ICON |
perl -0777 -pe '@_=/\d+/g;
printf "P7\nWIDTH %d\nHEIGHT %d\nDEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n", splice@_,0,2;
$_=pack "N*", @_;
s/(.)(...)/$2$1/gs' > icon.pam
(and click on the window you want to get the icon from, see also xprop's -id option)
The idea is to use xprop to get the property as a list of 32 bit decimal integers and use perl to convert that into a graphics format (pam chosen here for simplicity though I had to reorder the bytes since _NET_WM_ICON is ARGB while pam is RGBA.
(a note about the pam format. It's a netpbm format, netpbm being a venerable Unix image manipulation toolbox. However, due to various issues, mostly licensing ones, newer netpbm versions are not packages by debian and as a result its derivatives like ubuntu as well, which means that most of the pam conversion utilities are not present there. On other systems that have newer netpbm, you can pipe the output above to pamrgbatopng to generate a png image)
- 522,931
- 91
- 1,010
- 1,501
-
-
1Nice solution. Note to others: this picks up only the first size of icon, which is typically the smallest. I was able to get the bigger size by sending the output of `xprop` to a file and editing it by hand. Each icon size begins with width and height, and is followed by the corresponding number of values (eg 16x16 has 256 values). – Neil Mayhew Jun 08 '20 at 21:14
-
1@NeilMayhew: I created a script to dump all icons instead of just the first one, no hand-editing needed: https://unix.stackexchange.com/a/609751/4919 – MestreLion Sep 16 '20 at 21:58
-
Based on @Stéphane Chazelas amazing snippet I created a script to dump not just the first but all icons of a given window to .png images:
#!/bin/bash
if [[ "$1" == '--help' ]]; then
echo "Show information or extract a window's icons to NAME-WIDTH.png"
echo "Usage: ${0##*/} [NAME]"
exit
fi
if [[ "$1" ]]; then
cmd=(convert -set 'filename:w' '%w' - "${1}-%[filename:w].png")
else
cmd=(identify -)
fi
split_icons() {
xprop -notype 32c _NET_WM_ICON |
awk -v RS=', | = ' '
NR == 1 { h = $1; i++; next }
NR == i + 1 { x = $1; printf "%s = %s", h, x; next }
NR == i + 2 { s = x * $1 } { printf ", %s", $1 }
NR == i + 2 + s { i += s + 2; printf "\n" }
'
}
to_pam() {
perl -0777 -pe '@_=/\d+/g;
printf "P7\nWIDTH %d\nHEIGHT %d\n", splice@_,0,2;
printf "DEPTH 4\nMAXVAL 255\nTUPLTYPE RGB_ALPHA\nENDHDR\n";
$_=pack "N*", @_;
s/(.)(...)/$2$1/gs'
}
while read -r data; do to_pam <<< "$data" | "${cmd[@]}"; done < <(split_icons)
Without any arguments it uses identify to display icon information, no files are created. With a given NAME it extracts the icons and use convert to save them as NAME-<width>.png.
Example usage:
$ extract-icons --help
Show information or extract a window's icons to NAME-WIDTH.png
Usage: extract-icons [NAME]
$ extract-icons # ... click on firefox ...
-=>/tmp/magick-14339JS01_CgEl3Yi PAM 64x64 64x64+0+0 8-bit TrueColor sRGB 16.5KB 0.000u 0:00.000
-=>/tmp/magick-14342I14cdBFZKQIm PAM 16x16 16x16+0+0 8-bit TrueColor sRGB 1.09KB 0.000u 0:00.000
-=>/tmp/magick-14345gjMYsrl4Jhmh PAM 128x128 128x128+0+0 8-bit TrueColor sRGB 65.6KB 0.000u 0:00.000
-=>/tmp/magick-14348Wdmu9LGUEH0j PAM 32x32 32x32+0+0 8-bit TrueColor sRGB 4.16KB 0.000u 0:00.000
-=>/tmp/magick-14351HICEECbK3LRi PAM 48x48 48x48+0+0 8-bit TrueColor sRGB 9.28KB 0.000u 0:00.000
$ extract-icons firefox
$ ls -l
total 36.864
-rw-r--r-- 1 rodrigo rodrigo 14.882 2020-09-16 18:44 firefox-128.png
-rw-r--r-- 1 rodrigo rodrigo 1.175 2020-09-16 18:44 firefox-16.png
-rw-r--r-- 1 rodrigo rodrigo 2.265 2020-09-16 18:44 firefox-32.png
-rw-r--r-- 1 rodrigo rodrigo 3.870 2020-09-16 18:44 firefox-48.png
-rw-r--r-- 1 rodrigo rodrigo 5.996 2020-09-16 18:44 firefox-64.png
You can get the full script, with a few added options, as xdg-extract-icons in my xdg-tools repository
- 1,358
- 12
- 19
-
I'm so glad someone has added this capability! I much prefer to have something that doesn't need compilation and/or library dependencies. – Neil Mayhew Sep 28 '20 at 14:58
I stumbled upon this blog post. To quote from it:
To demonstrate how this can be done in practice, I wrote a small program called xgeticon which let the user choose the window of a running X application and save the extracted icon into the file provided as argument.
- 479
- 5
- 4
-
Suppose `wmctrl -l | awk '{print $1 "|" $2}'` gives the window ids like `0x03000003`. How to use your program get icon of each window? – Ahmad Ismail Jul 11 '23 at 04:27
use linux libwnck can do it
#define WNCK_I_KNOW_THIS_IS_UNSTABLE = 1
#include <libwnck/libwnck.h>
int main(int argc,
char **argv) {
WnckScreen *screen;
gdk_init(&argc, &argv);
screen = wnck_screen_get_default();
wnck_screen_force_update(screen);
auto win = wnck_window_get(127926341); // 127926341 is window id, it can be get by linux cli xdotool or wmctrl or other many clis
GdkPixbuf *r = wnck_window_get_icon(win);
GError *err = NULL;
gdk_pixbuf_save(r, "/tmp/prpr.png", "png", &err, "quality", "100", NULL);
return 0;
}
I get it from this page
- 121
- 5