wxWidgets / Phoenix

wxPython's Project Phoenix. A new implementation of wxPython, better, stronger, faster than he was before.
http://wxpython.org/
2.31k stars 519 forks source link

missing BITMAP_TYPE_BMP_RESOURCE constant #1439

Open kdschlosser opened 4 years ago

kdschlosser commented 4 years ago

Operating system: Windows 7 x64 SP1 wxPython version & source: 4.0.7.post1 msw (phoenix) wxWidgets 3.0.5 Pypi Python version & source: 3.7.5 Stackless 3.7 (tags/v3.7.5-slp:f7925f2a02, Oct 20 2019, 15:28:53) [MSC v.1916 64 bit (AMD64)]

Description of the problem: missing constant BITMAP_TYPE_BMP_RESOURCE

import wx

print(wx.BITMAP_TYPE_BMP_RESOURCE )

I also wanted to mention that the constant is also listed in the documentation here https://docs.wxpython.org/bitmap_overview.html

But it is is not listed here https://wxpython.org/Phoenix/docs/html/wx.BitmapType.enumeration.html

I can confirm that this constant does not exist in 4.0.X and also 3.0.x It is however in the documentation for both. It is also in the documentation for 2.8.9 I am unsure if it was in that version of the library tho.

I have several questions regarding loading a bitmap resource.

wx.Bitmap(r'c:\windows\system32\imageres.dll,1911', wx.BITMAP_TYPE_BMP_RESOURCE )

is this the correct call to make for loading a resource of that constant existed?? I was not able to locate any information on how the path should be formatted when passed to the wxBitmap constructor. I did see a single reference and it had a , and the resource number.

when loading a resource how explicit is the actual constant. is it to be taken literally? as in it will only load a .bmp resource? or will it also load a .png resource as well? The resource I am trying to load is the one you see in the example above. It is a png resource.

kdschlosser commented 4 years ago

I wanted tho also report this.. when I use the BITMAP_TYPE_PNG i get this for an error.

   wxError1: can't open file 'C:\Windows\system32\imageres.dll,1911' (error 0: the operation completed successfully.)
   wxError1: Failed to load image from file "C:\Windows\system32\imageres.dll,1911".

wx is saying it cannot open the image but the actual error message states that the operation completed successfully.

kdschlosser commented 4 years ago

also as it turns out there is a whole plethora of missing wxBITMAP_TYPE enumerations

enum wxBitmapType {
    wxBITMAP_TYPE_INVALID,
    wxBITMAP_TYPE_BMP,
    wxBITMAP_TYPE_BMP_RESOURCE,
    wxBITMAP_TYPE_RESOURCE = wxBITMAP_TYPE_BMP_RESOURCE,
    wxBITMAP_TYPE_ICO,
    wxBITMAP_TYPE_ICO_RESOURCE,
    wxBITMAP_TYPE_CUR,
    wxBITMAP_TYPE_CUR_RESOURCE,
    wxBITMAP_TYPE_XBM,
    wxBITMAP_TYPE_XBM_DATA,
    wxBITMAP_TYPE_XPM,
    wxBITMAP_TYPE_XPM_DATA, 
    wxBITMAP_TYPE_TIFF,
    wxBITMAP_TYPE_TIF = wxBITMAP_TYPE_TIFF,
    wxBITMAP_TYPE_TIFF_RESOURCE,
    wxBITMAP_TYPE_TIF_RESOURCE = wxBITMAP_TYPE_TIFF_RESOURCE,
    wxBITMAP_TYPE_GIF,
    wxBITMAP_TYPE_GIF_RESOURCE,
    wxBITMAP_TYPE_PNG,
    wxBITMAP_TYPE_PNG_RESOURCE,
    wxBITMAP_TYPE_JPEG,
    wxBITMAP_TYPE_JPEG_RESOURCE,
    wxBITMAP_TYPE_PNM,
    wxBITMAP_TYPE_PNM_RESOURCE,
    wxBITMAP_TYPE_PCX, 
    wxBITMAP_TYPE_PCX_RESOURCE,
    wxBITMAP_TYPE_PICT,
    wxBITMAP_TYPE_PICT_RESOURCE,
    wxBITMAP_TYPE_ICON,
    wxBITMAP_TYPE_ICON_RESOURCE,
    wxBITMAP_TYPE_ANI,
    wxBITMAP_TYPE_IFF,
    wxBITMAP_TYPE_TGA,
    wxBITMAP_TYPE_MACCURSOR,
    wxBITMAP_TYPE_MACCURSOR_RESOURCE,
    wxBITMAP_TYPE_ANY = 50
}
kdschlosser commented 4 years ago

I wanted to follow up on this and provide some more details on this. I have not been able to use any of the resource type constants and get a resource to properly load. The path to the resource is being gotten from Windows. and I was passing that path directly to wx.Bitmap.

I ended up writing a ctypes binder to the portion of the Windows API that handles the resources. and I happened across a couple of issues.

*As it turns out the icon (.ico, .cur) resources are not standard. they do not include a header. The header has to be created manually and added to the data stream and then I can get wx Bitmap to open the image without having specifying the resource enumeration.

*The resource id I was specifically dealing with was not an icon or a png icon. It was a group icon id. Which points to a container holding multiple sizes of the same icon. Maybe a mechanism should be added that would be able to present the user with the different sizes/bits so they would then be able to choose which one to use.

*The resource identifier as part of a path I have not been able to wrap my head fully around. some of them will be a negative number while others will not. the negative if changed to a positive seems to make no difference in the loading of the resource so I am not entirely sure of the purpose for the negative.

The binder I wrote will handle BMP, TIFF (little edian), TIFF (big edian), JPEG, JPEG (JFIF), GIF, WMF, PNG, ICO, CUR, WAV and AVI files, It also handles string resources which could be useful. It works with the pre defined RT_* constants as well as custom resource group names. A large portion of the API to windows for handling resources is not documented and there are structures needed that are not included in any header file in the SDK. so as you can imagine it was a challenge to get it to work properly. I did manage to collect the information needed and also copy the data out of the resource in order to create a wx Bitmap properly (width, height, color depth, etc...) and It does correct the missing header for the ICO and CUR. I have not yet tinkered about with animated icons and cursors These would be more involved and need to have a section added to the header for each frame in the animation.

I am going to write a library that a user can install that will extend the functionality of wx Bitmap to handle resources and resource groups without the need to use a resource specific constant. I will share the link to it when I am finished. If you want to add it to wxPython then by all means please do.

RobinD42 commented 4 years ago

wxPython has always excluded the wx.BITMAP_TYPE_*_RESOURCE enum values because, at least in the early days, it was only possible to pull the resource items from the binaries of the currently running application. For us, that would be python.exe and wx/_core.pyd and it makes no sense for wxPython application developers to expect to pull bitmaps from Python or wxPython binaries. It might make sense to be able to do it from a frozen application, but IMO there are much easier ways to embed and use resources when distributing wxPython applications, and those techniques are not Windows-specific.

kdschlosser commented 4 years ago

well pulling binaries from a library can be done for any library file not just the running applications. You can see this being done if you check out resource hacker.

whole dialogs can also get stored as a resource as well and when you have a tool like resource hacker that provides the ability to design a dialog layout easily and save it to an executable it would be a pretty handy thing to be able to load that dialog from the resource using wxPython. It is something that would be nice to be able to do instead of having to write code for. and the same goes with the icons. instead of having to store the icons as files having them bundled together is kind of nice. The other thing is have the same icon in varying sizes and color depths grouped together. The API to access the resources is not all that complex really, the hard part was figuring the API out because a large portion of it is not documented and not in any of the SDK h files. The header information being missing from the icons and cursors took me a bit to figure out, it's not that hard to generate the header using the API to collect the width, height and color depth. The ico's and cur's are the only image types that need to have this done. the png's and bmp's are complete and need no modification.

In my use case I was writing an endpoint control program where you can carry out operations when something changes with the audio. here is an example, say you plugged in your headphones and you want to have your media player launch whn you do that and have the volume adjusted for headphone listening. I have a user that uses this kind of ability to know if he has docked his laptop. I wanted to be able to display the icons that are used by Windows for these items. The icons used may not be apart of windows and could be included with the audio driver. The paths and resource numbers are provided by the audio API..

I did want to mention.. I figured out why some of the resources are identified as a negative. these are the group identifiers and not specific icon identifiers. the group has to get enumerated in order to get the specific icon id's and that id is going to depend on what size/type/bit depth is wanted.

yamahubuki commented 3 years ago

I understand why this constant was removed. However, I wasted a lot of time finding this issue. Please also correct the following pages. https://docs.wxpython.org/bitmap_overview.html