【问题标题】:HICON/HBITMAP to QIcon/QPixmap/QImage/Anything with a Q in itHICON/HBITMAP 到 QIcon/QPixmap/QImage/任何带有 Q 的东西
【发布时间】:2013-02-24 18:10:24
【问题描述】:

我正在尝试从 Windows 中的文件中获取 48x48 或 256x256 图标,但遇到了看似死胡同的问题。目前我在 python 中有一个 HICON 句柄(因为 PySides QFileIconProvider 只返回 32x32 图标),我想在 pyside 窗口中显示它,但是像 QPixmap.fromHICON/HBITMAP 这样的函数没有实现,而且似乎已经从源代码中删除了从 Qt 4.8(?)开始。另外,我试图避免将图标保存到文件中。

那么,有什么方法可以将 HICON 或任何其他您可以将其转换为任何类型的 PySide 对象的东西?

编辑: 我一直在尝试简单地重写 python 中的 WinHBITMAP 函数中的旧函数,但效果并不好。我不确定如何将 src 行转换为 python,我也不知道如何更改 QImage.scanLine() 返回的内存缓冲区的值

for (int y=0; y<h; ++y) {
            QRgb *dest = (QRgb *) image.scanLine(y);
            const QRgb *src = (const QRgb *) (data + y * bytes_per_line);
            for (int x=0; x<w; ++x) {
                dest[x] = src[x] | mask;
            }
        }

目前,我使用 win32api 从 HICON 创建 PyCBITMAP 并检索位列表。

for y in range(0, hIcon.height):
    dest = i.scanLine(y)
    src = bitmapbits[y*hIcon.widthBytes:(y*hIcon.widthBytes)+hIcon.widthBytes]

    for x in range(0, hIcon.width):
        dest[x] = bytes(ctypes.c_uint32(src[x] | 0))

这会导致“ValueError: cannot modify size of memoryview object”

函数的来源可以在这里找到:http://www.qtcentre.org/threads/19188-Converting-from-HBitmap-to-a-QPixmap?p=94747#post94747

【问题讨论】:

    标签: python pyside


    【解决方案1】:

    修好了!

    def iconToQImage(hIcon):
        hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
        hbmp = win32ui.CreateBitmap()
        hbmp.CreateCompatibleBitmap(hdc, hIcon.width, hIcon.height)
        hdc = hdc.CreateCompatibleDC()
        hdc.SelectObject(hbmp)
    
        win32gui.DrawIconEx(hdc.GetHandleOutput(), 0, 0, hIcon.hIcon, hIcon.width, hIcon.height, 0, None, 0x0003)
    
        bitmapbits = hbmp.GetBitmapBits(True)
        image = QtGui.QImage(bitmapbits, hIcon.width, hIcon.height, QtGui.QImage.Format_ARGB32_Premultiplied)
        return image
    

    【讨论】:

    • 首先如何获得 hIcon 句柄?
    • 如果我没记错的话,使用 windows 和 shellapi 头文件在 c++ 中制作了一个 python 模块。虽然我猜在 python 中可以用 ctypes.windll 做同样的事情。 pogopixels.com/blog/…
    • 我只是想知道,因为您具有 hIcon 的属性,例如宽度和高度,但自定义包装器会有意义。
    【解决方案2】:

    进行这种设置有点困难,但我阅读了 Python Imaging Library (PIL) 支持bitmap and ICO files 并具有downloads for Windows。假设你可以得到一个图标的文件名,你可以用 PIL 加载它,然后传输raw data to a QImage

    from PIL import Image
    from PySide.QtGui import QImage, QImageReader, QLabel, QPixmap, QApplication
    
    im = Image.open("my_image.png")
    data = im.tostring('raw', 'RGBA')
    
    app = QApplication([])
    
    image = QImage(data, im.size[0], im.size[1], QImage.Format_ARGB32)
    pix = QPixmap.fromImage(image)
    lbl = QLabel()
    lbl.setPixmap(pix)
    lbl.show()
    
    app.exec_()
    

    然后使用您需要从那里执行的任何QImage 操作。

    【讨论】:

    • 如果你能得到图标的文件名,你可以打电话给image = QImage(); image.load(filename)
    【解决方案3】:

    虽然@egs0 的回答是准确的,但尝试显示输出可能会导致问题,因为QLabel 不能很好地处理位图。要解决这些问题,请将结果转换为另一种图像格式。

    import win32ui
    import win32gui
    # Doesn't matter which library. Qt5 should work just as well.
    from PySide6 import QtGui, QtCore
    
    def iconToQImage(hIcon, width, height, im_format="PNG"):
        hdc = win32ui.CreateDCFromHandle(win32gui.GetDC(0))
        hbmp = win32ui.CreateBitmap()
        hbmp.CreateCompatibleBitmap(hdc, width, height)
        hdc = hdc.CreateCompatibleDC()
        hdc.SelectObject(hbmp)
    
        win32gui.DrawIconEx(hdc.GetHandleOutput(), 0, 0, hIcon, width, height, 0, None, 0x0003)
    
        bitmapbits = hbmp.GetBitmapBits(True)
        image = QtGui.QImage(bitmapbits, width, height, QtGui.QImage.Format_ARGB32_Premultiplied)
        
        # Write to and then load from a buffer to convert to PNG.
        buffer = QtCore.QBuffer()
        buffer.setOpenMode(QtCore.QIODevice.ReadWrite)
        image.save(buffer, im_format)
        image.loadFromData(buffer.data(), im_format)
        
        # Use QtGui.Pixmap.fromImage() to get a pixmap instead.
        return image
    

    也可以使用以下函数获取图标的大小,改编自here

    def getIconSize(HIcon):
        info = win32gui.GetIconInfo(HIcon)
        
        if info[4]:  # Icon has color plane.
            bmp = win32gui.GetObject(info[4])
    
            width = bmp.bmWidth
            height = bmp.bmHeight
        else: # Icon has no colour plane, image data stored in mask.
            bmp = win32gui.GetObject(info[3])
    
            width = bmp.width 
            height = bmp.height // 2  # A monochrome icon contains image and XOR mask in the hbmMask.
    
        info[3].close()
        info[4].close()
    
        return width, height
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-29
      • 1970-01-01
      • 2016-07-05
      相关资源
      最近更新 更多