export_pixels(storage='long') crashes on Windows
roelandschoukens opened this issue · comments
Calling export_pixels(storage='long')
on a wand Image will crash the Python interpreter.
It seems MagickExportImagePixels
expects a buffer with 8-bit integers if you use the corresponding enum value. In the list of storage types, you can use explicitly sized integer types ctypes.c_uint32
and ctypes.c_uint64
instead of c_uint
and ctypes.c_ulong
:
c_storage_types = [
None,
ctypes.c_uint8,
ctypes.c_double,
ctypes.c_float,
ctypes.c_uint32,
ctypes.c_uint64,
ctypes.c_double, # FIXME: Might be c_longdouble?
ctypes.c_uint16
]
(n.b. long
is only 4 bytes on Windows)
Thanks for opening this issue & good find. For the most part, both ImageMagick & Python are standardized to the same C types. That is to say (python)ctypes.sizeof(ctypes.c_ushort)
must match (c)sizeof(unsigned short)
. However, as you pointed out, this is not true for the "long"
storage type. Looking into the source code, and I see "long"
maps to LongLongPixel
type that alias MagickSizeType
. Where MagickSizeType
is defined as:
#if !defined(MAGICKCORE_WINDOWS_SUPPORT)
#if (MAGICKCORE_SIZEOF_UNSIGNED_LONG_LONG == 8)
typedef long long MagickOffsetType;
typedef unsigned long long MagickSizeType;
#define MagickOffsetFormat "lld"
#define MagickSizeFormat "llu"
#else
typedef ssize_t MagickOffsetType;
typedef size_t MagickSizeType;
#define MagickOffsetFormat "ld"
#define MagickSizeFormat "lu"
#endif
#else
typedef __int64 MagickOffsetType;
typedef unsigned __int64 MagickSizeType;
#define MagickOffsetFormat "I64i"
#define MagickSizeFormat "I64u"
#endif
.... which is a fancy way of saying "always uint64 for long". I'll need to dig into this a little bit more, but yes, this is a bug.
Incidentally, the Quantum type (second from the bottom) is an alias for one of the other ones, depending on your build setting. MAGICKCORE_QUANTUM_DEPTH determines the size, and MAGICKCORE_HDRI_SUPPORT determines if it is int or float (in the latter case, float32 is also used for depth 8 and 16). See MagickCore/magick-type.h
in the ImageMagick library.
Correct. A bit tricky to identify as Python's ctypes doesn't have access to the preprocessor values and/or configure settings. However I believe this was addressed elsewhere in Wand by IBM folks.
Feel free to test out adfa655 commit. Pending some CI / regression testing on different architectures, this should be fixed.