Question

I'm currently trying to figure out how to create some code which will take the input of a file extension like '.png' and return the icon associated with that filetype on the system.

I'm using python 2.7.6 and using Windows 8. I've been looking for code for this for hours to things close to it by saving images from .exe files but not finding the file extension in the registry and saving it.

I have found some code that works and allows me to save the file as a bmp which basically works by using wxpython's icon to bitmap workings and saves the image as well. However, I would the code to simply not use wxpython since I'm using Tkinter to code the interface itself .

Here's the code that currently works (adapted slightly) from http://ginstrom.com/scribbles/2007/08/31/file-list-with-icons-on-wxpython-windows/

import wx
from win32com.shell import shell, shellcon
from win32con import FILE_ATTRIBUTE_NORMAL

def extension_to_bitmap(extension):
    """dot is mandatory in extension"""

    flags = shellcon.SHGFI_SMALLICON | \
            shellcon.SHGFI_ICON | \
            shellcon.SHGFI_USEFILEATTRIBUTES

    retval, info = shell.SHGetFileInfo(extension,
                         FILE_ATTRIBUTE_NORMAL,
                         flags)
    # non-zero on success
    assert retval

    hicon, iicon, attr, display_name, type_name = info

    # Get the bitmap
    icon = wx.EmptyIcon()
    icon.SetHandle(hicon)
    return wx.BitmapFromIcon(icon)

root = wx.App()

bitmapFile = extension_to_bitmap(".png")

bitmapFile.SaveFile('test.bmp', wx.BITMAP_TYPE_BMP)

Any help is greatly appreciated!

Was it helpful?

Solution

Inspired by IronManMark20's answer. This version returns a PIL image so it doesn't require the disc I/O of creating a temporary file. It also can get the different image sizes (see below) For more information, check this blog post.

from win32com.shell import shell, shellcon
from PIL import Image, ImageTk
import win32api
import win32con
import win32ui
import win32gui

def get_icon(PATH, size):
    SHGFI_ICON = 0x000000100
    SHGFI_ICONLOCATION = 0x000001000
    if size == "small":
        SHIL_SIZE = 0x00001
    elif size == "large":
        SHIL_SIZE = 0x00002
    else:
        raise TypeError("Invalid argument for 'size'. Must be equal to 'small' or 'large'")
        
    ret, info = shell.SHGetFileInfo(PATH, 0, SHGFI_ICONLOCATION | SHGFI_ICON | SHIL_SIZE)
    hIcon, iIcon, dwAttr, name, typeName = info
    ico_x = win32api.GetSystemMetrics(win32con.SM_CXICON)
    hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
    hbmp = win32ui.CreateBitmap()
    hbmp.CreateCompatibleBitmap(hdc, ico_x, ico_x)
    hdc = hdc.CreateCompatibleDC()
    hdc.SelectObject(hbmp)
    hdc.DrawIcon((0, 0), hIcon)
    win32gui.DestroyIcon(hIcon)

    bmpinfo = hbmp.GetInfo()
    bmpstr = hbmp.GetBitmapBits(True)
    img = Image.frombuffer(
        "RGBA",
        (bmpinfo["bmWidth"], bmpinfo["bmHeight"]),
        bmpstr, "raw", "BGRA", 0, 1
    )

    if size == "small":
        img = img.resize((16, 16), Image.ANTIALIAS)
    return img

Test Cases

OTHER TIPS

Oddly enough, Python doesn't seem to have much for creating / editing *.ico files. It sounds like your best bet is to get the Python bindings for ImageMagick:

I couldn't find any documentation specific to the bindings though. From what I have read, the Python Imaging Library (PIL) can read icon files, but not create them. However, you can probably use PIL to create bitmap files:

I recently had to do a similar task, and I used the following (requires pywin32 and PIL or Pillow). Basically, you get the handle of the icon, and make a copy. This returns a PIL image. You can open the Icontemp.bmp using something else, if you want.

def icon32(PATH):
    SHGFI_ICON = 0x000000100
    SHGFI_ICONLOCATION = 0x000001000
    SHIL_EXTRALARGE = 0x00002
    ret, info = shell.SHGetFileInfo(PATH, 0, SHGFI_ICONLOCATION | SHGFI_ICON | SHIL_EXTRALARGE)
    hIcon, iIcon, dwAttr, name, typeName = info
    tempDirectory = os.getenv("temp")
    ico_x = win32api.GetSystemMetrics(win32con.SM_CXICON)
    #creating a destination memory DC
    hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
    hbmp = win32ui.CreateBitmap()
    hbmp.CreateCompatibleBitmap(hdc, ico_x, ico_x)
    hdc = hdc.CreateCompatibleDC()
    hdc.SelectObject(hbmp)
    hdc.DrawIcon((0, 0), hIcon)
    win32gui.DestroyIcon(hIcon)
    hbmp.SaveBitmapFile(hdc, tempDirectory + "\Icontemp.bmp")
    icon = QIcon(tempDirectory + "\Icontemp.bmp")
    os.remove(tempDirectory + "\Icontemp.bmp")
    return icon
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top