def magick_raise(exc, force=False): """If the given `ExceptionInfo` pointer contains an exception, convert it to a Python one and throw it. Set `force` to True to throw a generic error even if the pointer doesn't seem to indicate an exception. This is useful in cases where a function uses both exceptions and `NULL` returns, which are sadly all too common in ImageMagick. """ if exc == ffi.NULL or exc.severity == lib.UndefinedException: if force: raise MysteryError return # TODO have more exception classes # An exception's description tends to be blank; the actual message # is in `reason` if exc.reason == ffi.NULL: message = b'' else: message = ffi.string(exc.reason) severity_name = ffi.string(ffi.cast("ExceptionType", exc.severity)) # severity_name is an enum name and thus a string, not bytes message = message + b' ' + severity_name.encode('ascii') if exc.severity < lib.ErrorException: # This is a warning, so do a warning cls = magick_exception_map.get(exc.severity, GenericMagickWarning) warnings.warn(cls(message)) else: # ERROR ERROR cls = magick_exception_map.get(exc.severity, GenericMagickError) raise cls(message)
def _get_formats(): formats = dict() num_formats = ffi.new("size_t *") # Snag the list of known supported image formats with magick_try() as exc: magick_infos = ffi.gc(lib.GetMagickInfoList(b"*", num_formats, exc.ptr), lib.RelinquishMagickMemory) # Sometimes this call can generate an exception (such as a module not # being loadable) but then succeed anyway and return a useful value, in # which case we want to ignore the exception if magick_infos != ffi.NULL: exc.clear() for i in range(num_formats[0]): name = ffi.string(magick_infos[i].name).decode("latin-1") formats[name.lower()] = ImageFormat( name=name, description=ffi.string(magick_infos[i].description).decode("latin-1"), can_read=magick_infos[i].decoder != ffi.NULL, can_write=magick_infos[i].encoder != ffi.NULL, supports_frames=magick_infos[i].adjoin != 0, ) return formats
def _get_formats(): formats = dict() formats_by_mime = dict() num_formats = ffi.new("size_t *") # Snag the list of known supported image formats with magick_try() as exc: magick_infos = ffi.gc( lib.GetMagickInfoList(b"*", num_formats, exc.ptr), lib.RelinquishMagickMemory) for i in range(num_formats[0]): imageformat = ImageFormat( name=ffi.string(magick_infos[i].name).decode('latin-1'), description=ffi.string(magick_infos[i].description).decode('latin-1'), can_read=magick_infos[i].decoder != ffi.NULL, can_write=magick_infos[i].encoder != ffi.NULL, supports_frames=magick_infos[i].adjoin != 0, mime_type=ffi.string(magick_infos[i].mime_type).decode('ascii') if magick_infos[i].mime_type else None, ) formats[imageformat.name.lower()] = imageformat formats_by_mime[imageformat.mime_type] = imageformat return formats, formats_by_mime
def raw_properties(self): # TODO may need SyncImageProfiles() somewhere? it updates EXIF res and # orientation ret = {} # This tricks IM into actually reading the EXIF properties... lib.GetImageProperty(self._stack, "exif:*") lib.ResetImagePropertyIterator(self._stack) while True: # XXX this only examines the top image uhoh. do we care? what # happens if i load a GIF; what does each frame say? what happens # if i have multiple images with different props and save as one # image? prop = lib.GetNextImageProperty(self._stack) if prop == ffi.NULL: break ret[ffi.string(prop)] = ffi.string(lib.GetImageProperty(self._stack, prop)) return ret
def raw_properties(self): # TODO may need SyncImageProfiles() somewhere? it updates EXIF res and # orientation ret = {} # This tricks IM into actually reading the EXIF properties... lib.GetImageProperty(self._stack, "exif:*") lib.ResetImagePropertyIterator(self._stack) while True: # XXX this only examines the top image uhoh. do we care? what # happens if i load a GIF; what does each frame say? what happens # if i have multiple images with different props and save as one # image? prop = lib.GetNextImageProperty(self._stack) if prop == ffi.NULL: break ret[ffi.string(prop)] = ffi.string( lib.GetImageProperty(self._stack, prop)) return ret
def _get_formats(): formats = dict() num_formats = ffi.new("size_t *") # Snag the list of known supported image formats with magick_try() as exc: magick_infos = ffi.gc( lib.GetMagickInfoList(b"*", num_formats, exc.ptr), lib.RelinquishMagickMemory) for i in range(num_formats[0]): name = ffi.string(magick_infos[i].name).decode('latin-1') formats[name.lower()] = ImageFormat( name=name, description=ffi.string( magick_infos[i].description).decode('latin-1'), can_read=magick_infos[i].decoder != ffi.NULL, can_write=magick_infos[i].encoder != ffi.NULL, supports_frames=magick_infos[i].adjoin != 0, ) return formats
def original_format(self): return ffi.string(self._stack.magick)
"""Various information about the underlying ImageMagick library and the features it supports. Deliberately not named ``features`` to emphasize that everything herein is highly specific to ImageMagick and completely out of the library's hands. """ from __future__ import absolute_import from __future__ import division from __future__ import print_function from collections import namedtuple from sanpera._api import ffi, lib from sanpera.exception import magick_try FEATURES = frozenset(ffi.string(lib.GetMagickFeatures()).decode('ascii').split(' ')) HAS_OPENMP = 'OpenMP' in FEATURES HAS_OPENCL = 'OpenCL' in FEATURES HAS_HDRI = 'HDRI' in FEATURES # Version number is given as hex; version A.B.C is 0xABC _out = ffi.new("size_t *") lib.GetMagickVersion(_out) VERSION = ( (_out[0] & 0xf00) >> 8, (_out[0] & 0x0f0) >> 4, (_out[0] & 0x00f) >> 0, ) del _out
"""Various information about the underlying ImageMagick library and the features it supports. Deliberately not named ``features`` to emphasize that everything herein is highly specific to ImageMagick and completely out of the library's hands. """ from __future__ import absolute_import from __future__ import division from __future__ import print_function from collections import namedtuple from sanpera._api import ffi, lib from sanpera.exception import magick_try FEATURES = frozenset(ffi.string(lib.GetMagickFeatures()).decode("ascii").split(" ")) HAS_OPENMP = "OpenMP" in FEATURES HAS_OPENCL = "OpenCL" in FEATURES HAS_HDRI = "HDRI" in FEATURES # Version number is given as hex; version A.B.C is 0xABC _out = ffi.new("size_t *") lib.GetMagickVersion(_out) VERSION = ((_out[0] & 0xF00) >> 8, (_out[0] & 0x0F0) >> 4, (_out[0] & 0x00F) >> 0) del _out ImageFormat = namedtuple("ImageFormat", ["name", "description", "can_read", "can_write", "supports_frames"])
features it supports. Deliberately not named ``features`` to emphasize that everything herein is highly specific to ImageMagick and completely out of the library's hands. """ from __future__ import absolute_import from __future__ import division from __future__ import print_function from collections import namedtuple from sanpera._api import ffi, lib from sanpera.exception import magick_try FEATURES = frozenset( ffi.string(lib.GetMagickFeatures()).decode('ascii').split(' ')) HAS_OPENMP = 'OpenMP' in FEATURES HAS_OPENCL = 'OpenCL' in FEATURES HAS_HDRI = 'HDRI' in FEATURES # Version number is given as hex; version A.B.C is 0xABC _out = ffi.new("size_t *") lib.GetMagickVersion(_out) VERSION = ( (_out[0] & 0xf00) >> 8, (_out[0] & 0x0f0) >> 4, (_out[0] & 0x00f) >> 0, ) del _out ImageFormat = namedtuple(