Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loading icons from a DLL file? #7191

Open
DevilXD opened this issue May 28, 2023 · 10 comments
Open

Loading icons from a DLL file? #7191

DevilXD opened this issue May 28, 2023 · 10 comments

Comments

@DevilXD
Copy link

DevilXD commented May 28, 2023

Windows defines some native icons bundled in DLL files. I'm talking about these specifically: https://www.digitalcitizen.life/where-find-most-windows-10s-native-icons/

Is there a way in Pillow to open/load a selected icon from one of these files? I can't find anything specific to it being possible, and obviously loading the DLL file directly doesn't work (PIL.UnidentifiedImageError). If not, it'd be cool to add some support for it.

@nulano
Copy link
Contributor

nulano commented May 28, 2023

The icons embedded in a PE file (exe or dll) are stored in a format readable by Pillow, but you have to use some other library to extract their data.

@radarhere radarhere changed the title Is there a way to load an icon from a DLL file? Loading icons from a DLL file? May 28, 2023
@radarhere
Copy link
Member

Could you upload an example file? If you're requesting support, ideally one that could be added to our test suite and released under the Pillow license.

@pubpub-zz
Copy link

you should find such a file in windows default installation:
c:\Windows\System32\moricons.dll

@nulano
Copy link
Contributor

nulano commented May 30, 2023

you should find such a file in windows default installation: c:\Windows\System32\moricons.dll

That is a part of Windows, so it cannot be distributed under the Pillow license.

EXE and DLL files have the same format, so python.exe seems like a good example: python.zip

@DevilXD
Copy link
Author

DevilXD commented May 30, 2023

That is a part of Windows, so it cannot be distributed under the Pillow license.

The point is that, because the icon files are part of Windows, they're always there, so you don't need to distribute it, just read it from the disk. This assumes the tests will be done on Windows, of course. Otherwise, the only possible way I can think of testing this, would be to create a custom DLL file with some icons inside, and then distribute and test on that. I currently don't have such a file, I intend on using the existing icons that Windows already provides.

@nulano
Copy link
Contributor

nulano commented May 30, 2023

This assumes the tests will be done on Windows, of course.

That's exactly the problem, the majority of Pillow contributors are on Linux or macOS.

Otherwise, the only possible way I can think of testing this, would be to create a custom DLL file with some icons inside, and then distribute and test on that.

Exactly. EXE files have the same structure as a DLL, and python.exe was the first file I could think of with a compatible license. Of course, a custom DLL would be smaller, but I don't have the time to make one right now.

@radarhere
Copy link
Member

I found https://github.com/robomotic/pemeta, and with that, I was able to run python3 main.py --pefile python.exe -i -s and save 7 ICO files.

Under the hood, it uses https://github.com/erocarrera/pefile

@radarhere
Copy link
Member

@DevilXD would you still like support for this file type added to Pillow, or could you simply use Pillow and another Python library to achieve your goal?

@DevilXD
Copy link
Author

DevilXD commented Jun 5, 2023

@radarhere Well, honestly, I've created this issue as a pilot one - just exploring my options. Since Pillow currently does not support this option easily, instead of using some other lib for extraction, I'll probably just pre-extract things I need, and have something like a folder of ICO/PNG files with whatever icons I might end up using. It's not ideal, but should get the job done. I don't want to overcomplicate something as simple as loading a bunch of icons. I wanted to just have a single DLL file with all the icons I'd need, to avoid clutter, but a folder of icons should do as well for my case.

That being said, it'd be really cool to have this as an option for Pillow, for anyone who might stumble upon a usage like this in the future. Alternatively, if supporting this would be a huge burden, a short "tutorial note" of sorts added somewhere in the documentation would be cool, basically the 2nd comment of this issue, but maybe in a slightly more in-detail format. Maybe some links to the 3rd party libraries mentioned here. A short paragraph about "how to do it" would be enough.

@yinkaisheng
Copy link

yinkaisheng commented Apr 7, 2024

I have also previously researched how to read ICO images embedded in exe and dll files, and ultimately, I used the ctypes and PyQt5 for this purpose.

#!/usr/bin/env python3
import os
import sys
import ctypes
import numpy as np
import cv2
from matplotlib import pyplot as plt
from PyQt5 import QtWidgets
from PyQt5 import QtWinExtras
ctypes.windll.shell32.ExtractIconW.restype = ctypes.c_size_t

def displayIcon(path: str, index=0):
    hicon = ctypes.windll.shell32.ExtractIconW(0, path, index)
    qpixmap = QtWinExtras.QtWin.fromHICON(hicon)
    ctypes.windll.user32.DestroyIcon(ctypes.c_void_p(hicon))
    name = f'{os.path.basename(path)}_{index}.ico'
    qpixmap.save(name, 'ICO')
    qimg = qpixmap.toImage()
    width, height = qimg.width(), qimg.height()
    ptr = qimg.bits()  # qimg.constBits(), # bgra
    ptr.setsize(qimg.byteCount())
    img = np.array(ptr).reshape(height, width, 4)
    img = cv2.cvtColor(img, cv2.COLOR_BGRA2RGBA)
    plt.imshow(img)
    plt.title(name)
    plt.show()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    displayIcon(sys.executable)
    displayIcon(r'C:\Windows\System32\shell32.dll', 14)
    displayIcon(r'C:\Windows\System32\shell32.dll', 15)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants