mirror of
				https://github.com/janeczku/calibre-web
				synced 2025-11-01 07:43:02 +00:00 
			
		
		
		
	added Wand 4.2 to lib
This commit is contained in:
		
							
								
								
									
										6
									
								
								lib/wand/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								lib/wand/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| """:mod:`wand` --- Simple `MagickWand API`_ binding for Python | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| .. _MagickWand API: http://www.imagemagick.org/script/magick-wand.php | ||||
|  | ||||
| """ | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/wand/__init__.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/__init__.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1399
									
								
								lib/wand/api.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1399
									
								
								lib/wand/api.py
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								lib/wand/api.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/api.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										307
									
								
								lib/wand/color.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								lib/wand/color.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,307 @@ | ||||
| """:mod:`wand.color` --- Colors | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| .. versionadded:: 0.1.2 | ||||
|  | ||||
| """ | ||||
| import ctypes | ||||
|  | ||||
| from .api import MagickPixelPacket, library | ||||
| from .compat import binary, text | ||||
| from .resource import Resource | ||||
| from .version import QUANTUM_DEPTH | ||||
|  | ||||
| __all__ = 'Color', 'scale_quantum_to_int8' | ||||
|  | ||||
|  | ||||
| class Color(Resource): | ||||
|     """Color value. | ||||
|  | ||||
|     Unlike any other objects in Wand, its resource management can be | ||||
|     implicit when it used outside of :keyword:`with` block. In these case, | ||||
|     its resource are allocated for every operation which requires a resource | ||||
|     and destroyed immediately. Of course it is inefficient when the | ||||
|     operations are much, so to avoid it, you should use color objects | ||||
|     inside of :keyword:`with` block explicitly e.g.:: | ||||
|  | ||||
|         red_count = 0 | ||||
|         with Color('#f00') as red: | ||||
|             with Image(filename='image.png') as img: | ||||
|                 for row in img: | ||||
|                     for col in row: | ||||
|                         if col == red: | ||||
|                             red_count += 1 | ||||
|  | ||||
|     :param string: a color namel string e.g. ``'rgb(255, 255, 255)'``, | ||||
|                    ``'#fff'``, ``'white'``. see `ImageMagick Color Names`_ | ||||
|                    doc also | ||||
|     :type string: :class:`basestring` | ||||
|  | ||||
|     .. versionchanged:: 0.3.0 | ||||
|        :class:`Color` objects become hashable. | ||||
|  | ||||
|     .. seealso:: | ||||
|  | ||||
|        `ImageMagick Color Names`_ | ||||
|           The color can then be given as a color name (there is a limited | ||||
|           but large set of these; see below) or it can be given as a set | ||||
|           of numbers (in decimal or hexadecimal), each corresponding to | ||||
|           a channel in an RGB or RGBA color model. HSL, HSLA, HSB, HSBA, | ||||
|           CMYK, or CMYKA color models may also be specified. These topics | ||||
|           are briefly described in the sections below. | ||||
|  | ||||
|     .. _ImageMagick Color Names: http://www.imagemagick.org/script/color.php | ||||
|  | ||||
|     .. describe:: == (other) | ||||
|  | ||||
|        Equality operator. | ||||
|  | ||||
|        :param other: a color another one | ||||
|        :type color: :class:`Color` | ||||
|        :returns: ``True`` only if two images equal. | ||||
|        :rtype: :class:`bool` | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     c_is_resource = library.IsPixelWand | ||||
|     c_destroy_resource = library.DestroyPixelWand | ||||
|     c_get_exception = library.PixelGetException | ||||
|     c_clear_exception = library.PixelClearException | ||||
|  | ||||
|     __slots__ = 'raw', 'c_resource', 'allocated' | ||||
|  | ||||
|     def __init__(self, string=None, raw=None): | ||||
|         if (string is None and raw is None or | ||||
|                 string is not None and raw is not None): | ||||
|             raise TypeError('expected one argument') | ||||
|  | ||||
|         self.allocated = 0 | ||||
|         if raw is None: | ||||
|             self.raw = ctypes.create_string_buffer( | ||||
|                 ctypes.sizeof(MagickPixelPacket) | ||||
|             ) | ||||
|             with self: | ||||
|                 library.PixelSetColor(self.resource, binary(string)) | ||||
|                 library.PixelGetMagickColor(self.resource, self.raw) | ||||
|         else: | ||||
|             self.raw = raw | ||||
|  | ||||
|     def __getinitargs__(self): | ||||
|         return self.string, None | ||||
|  | ||||
|     def __enter__(self): | ||||
|         if not self.allocated: | ||||
|             with self.allocate(): | ||||
|                 self.resource = library.NewPixelWand() | ||||
|                 library.PixelSetMagickColor(self.resource, self.raw) | ||||
|         self.allocated += 1 | ||||
|         return Resource.__enter__(self) | ||||
|  | ||||
|     def __exit__(self, type, value, traceback): | ||||
|         self.allocated -= 1 | ||||
|         if not self.allocated: | ||||
|             Resource.__exit__(self, type, value, traceback) | ||||
|  | ||||
|     @property | ||||
|     def string(self): | ||||
|         """(:class:`basestring`) The string representation of the color.""" | ||||
|         with self: | ||||
|             color_string = library.PixelGetColorAsString(self.resource) | ||||
|             return text(color_string.value) | ||||
|  | ||||
|     @property | ||||
|     def normalized_string(self): | ||||
|         """(:class:`basestring`) The normalized string representation of | ||||
|         the color.  The same color is always represented to the same | ||||
|         string. | ||||
|  | ||||
|         .. versionadded:: 0.3.0 | ||||
|  | ||||
|         """ | ||||
|         with self: | ||||
|             string = library.PixelGetColorAsNormalizedString(self.resource) | ||||
|             return text(string.value) | ||||
|  | ||||
|     @staticmethod | ||||
|     def c_equals(a, b): | ||||
|         """Raw level version of equality test function for two pixels. | ||||
|  | ||||
|         :param a: a pointer to PixelWand to compare | ||||
|         :type a: :class:`ctypes.c_void_p` | ||||
|         :param b: a pointer to PixelWand to compare | ||||
|         :type b: :class:`ctypes.c_void_p` | ||||
|         :returns: ``True`` only if two pixels equal | ||||
|         :rtype: :class:`bool` | ||||
|  | ||||
|         .. note:: | ||||
|  | ||||
|            It's only for internal use. Don't use it directly. | ||||
|            Use ``==`` operator of :class:`Color` instead. | ||||
|  | ||||
|         """ | ||||
|         alpha = library.PixelGetAlpha | ||||
|         return bool(library.IsPixelWandSimilar(a, b, 0) and | ||||
|                     alpha(a) == alpha(b)) | ||||
|  | ||||
|     def __eq__(self, other): | ||||
|         if not isinstance(other, Color): | ||||
|             return False | ||||
|         with self as this: | ||||
|             with other: | ||||
|                 return self.c_equals(this.resource, other.resource) | ||||
|  | ||||
|     def __ne__(self, other): | ||||
|         return not (self == other) | ||||
|  | ||||
|     def __hash__(self): | ||||
|         if self.alpha: | ||||
|             return hash(self.normalized_string) | ||||
|         return hash(None) | ||||
|  | ||||
|     @property | ||||
|     def red(self): | ||||
|         """(:class:`numbers.Real`) Red, from 0.0 to 1.0.""" | ||||
|         with self: | ||||
|             return library.PixelGetRed(self.resource) | ||||
|  | ||||
|     @property | ||||
|     def green(self): | ||||
|         """(:class:`numbers.Real`) Green, from 0.0 to 1.0.""" | ||||
|         with self: | ||||
|             return library.PixelGetGreen(self.resource) | ||||
|  | ||||
|     @property | ||||
|     def blue(self): | ||||
|         """(:class:`numbers.Real`) Blue, from 0.0 to 1.0.""" | ||||
|         with self: | ||||
|             return library.PixelGetBlue(self.resource) | ||||
|  | ||||
|     @property | ||||
|     def alpha(self): | ||||
|         """(:class:`numbers.Real`) Alpha value, from 0.0 to 1.0.""" | ||||
|         with self: | ||||
|             return library.PixelGetAlpha(self.resource) | ||||
|  | ||||
|     @property | ||||
|     def red_quantum(self): | ||||
|         """(:class:`numbers.Integral`) Red. | ||||
|         Scale depends on :const:`~wand.version.QUANTUM_DEPTH`. | ||||
|  | ||||
|         .. versionadded:: 0.3.0 | ||||
|  | ||||
|         """ | ||||
|         with self: | ||||
|             return library.PixelGetRedQuantum(self.resource) | ||||
|  | ||||
|     @property | ||||
|     def green_quantum(self): | ||||
|         """(:class:`numbers.Integral`) Green. | ||||
|         Scale depends on :const:`~wand.version.QUANTUM_DEPTH`. | ||||
|  | ||||
|         .. versionadded:: 0.3.0 | ||||
|  | ||||
|         """ | ||||
|         with self: | ||||
|             return library.PixelGetGreenQuantum(self.resource) | ||||
|  | ||||
|     @property | ||||
|     def blue_quantum(self): | ||||
|         """(:class:`numbers.Integral`) Blue. | ||||
|         Scale depends on :const:`~wand.version.QUANTUM_DEPTH`. | ||||
|  | ||||
|         .. versionadded:: 0.3.0 | ||||
|  | ||||
|         """ | ||||
|         with self: | ||||
|             return library.PixelGetBlueQuantum(self.resource) | ||||
|  | ||||
|     @property | ||||
|     def alpha_quantum(self): | ||||
|         """(:class:`numbers.Integral`) Alpha value. | ||||
|         Scale depends on :const:`~wand.version.QUANTUM_DEPTH`. | ||||
|  | ||||
|         .. versionadded:: 0.3.0 | ||||
|  | ||||
|         """ | ||||
|         with self: | ||||
|             return library.PixelGetAlphaQuantum(self.resource) | ||||
|  | ||||
|     @property | ||||
|     def red_int8(self): | ||||
|         """(:class:`numbers.Integral`) Red as 8bit integer which is a common | ||||
|         style.  From 0 to 255. | ||||
|  | ||||
|         .. versionadded:: 0.3.0 | ||||
|  | ||||
|         """ | ||||
|         return scale_quantum_to_int8(self.red_quantum) | ||||
|  | ||||
|     @property | ||||
|     def green_int8(self): | ||||
|         """(:class:`numbers.Integral`) Green as 8bit integer which is | ||||
|         a common style.  From 0 to 255. | ||||
|  | ||||
|         .. versionadded:: 0.3.0 | ||||
|  | ||||
|         """ | ||||
|         return scale_quantum_to_int8(self.green_quantum) | ||||
|  | ||||
|     @property | ||||
|     def blue_int8(self): | ||||
|         """(:class:`numbers.Integral`) Blue as 8bit integer which is | ||||
|         a common style.  From 0 to 255. | ||||
|  | ||||
|         .. versionadded:: 0.3.0 | ||||
|  | ||||
|         """ | ||||
|         return scale_quantum_to_int8(self.blue_quantum) | ||||
|  | ||||
|     @property | ||||
|     def alpha_int8(self): | ||||
|         """(:class:`numbers.Integral`) Alpha value as 8bit integer which is | ||||
|         a common style.  From 0 to 255. | ||||
|  | ||||
|         .. versionadded:: 0.3.0 | ||||
|  | ||||
|         """ | ||||
|         return scale_quantum_to_int8(self.alpha_quantum) | ||||
|  | ||||
|     def __str__(self): | ||||
|         return self.string | ||||
|  | ||||
|     def __repr__(self): | ||||
|         c = type(self) | ||||
|         return '{0}.{1}({2!r})'.format(c.__module__, c.__name__, self.string) | ||||
|  | ||||
|     def _repr_html_(self): | ||||
|         html = """ | ||||
|         <span style="background-color:#{red:02X}{green:02X}{blue:02X}; | ||||
|                      display:inline-block; | ||||
|                      line-height:1em; | ||||
|                      width:1em;"> </span> | ||||
|         <strong>#{red:02X}{green:02X}{blue:02X}</strong> | ||||
|         """ | ||||
|         return html.format(red=self.red_int8, | ||||
|                            green=self.green_int8, | ||||
|                            blue=self.blue_int8) | ||||
|  | ||||
|  | ||||
| def scale_quantum_to_int8(quantum): | ||||
|     """Straightforward port of :c:func:`ScaleQuantumToChar()` inline | ||||
|     function. | ||||
|  | ||||
|     :param quantum: quantum value | ||||
|     :type quantum: :class:`numbers.Integral` | ||||
|     :returns: 8bit integer of the given ``quantum`` value | ||||
|     :rtype: :class:`numbers.Integral` | ||||
|  | ||||
|     .. versionadded:: 0.3.0 | ||||
|  | ||||
|     """ | ||||
|     if quantum <= 0: | ||||
|         return 0 | ||||
|     table = {8: 1, 16: 257.0, 32: 16843009.0, 64: 72340172838076673.0} | ||||
|     v = quantum / table[QUANTUM_DEPTH] | ||||
|     if v >= 255: | ||||
|         return 255 | ||||
|     return int(v + 0.5) | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/wand/color.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/color.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										119
									
								
								lib/wand/compat.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										119
									
								
								lib/wand/compat.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,119 @@ | ||||
| """:mod:`wand.compat` --- Compatibility layer | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| This module provides several subtle things to support | ||||
| multiple Python versions (2.6, 2.7, 3.2--3.5) and VM implementations | ||||
| (CPython, PyPy). | ||||
|  | ||||
| """ | ||||
| import contextlib | ||||
| import io | ||||
| import sys | ||||
| import types | ||||
|  | ||||
| __all__ = ('PY3', 'binary', 'binary_type', 'encode_filename', 'file_types', | ||||
|            'nested', 'string_type', 'text', 'text_type', 'xrange') | ||||
|  | ||||
|  | ||||
| #: (:class:`bool`) Whether it is Python 3.x or not. | ||||
| PY3 = sys.version_info >= (3,) | ||||
|  | ||||
| #: (:class:`type`) Type for representing binary data.  :class:`str` in Python 2 | ||||
| #: and :class:`bytes` in Python 3. | ||||
| binary_type = bytes if PY3 else str | ||||
|  | ||||
| #: (:class:`type`) Type for text data.  :class:`basestring` in Python 2 | ||||
| #: and :class:`str` in Python 3. | ||||
| string_type = str if PY3 else basestring  # noqa | ||||
|  | ||||
| #: (:class:`type`) Type for representing Unicode textual data. | ||||
| #: :class:`unicode` in Python 2 and :class:`str` in Python 3. | ||||
| text_type = str if PY3 else unicode  # noqa | ||||
|  | ||||
|  | ||||
| def binary(string, var=None): | ||||
|     """Makes ``string`` to :class:`str` in Python 2. | ||||
|     Makes ``string`` to :class:`bytes` in Python 3. | ||||
|  | ||||
|     :param string: a string to cast it to :data:`binary_type` | ||||
|     :type string: :class:`bytes`, :class:`str`, :class:`unicode` | ||||
|     :param var: an optional variable name to be used for error message | ||||
|     :type var: :class:`str` | ||||
|  | ||||
|     """ | ||||
|     if isinstance(string, text_type): | ||||
|         return string.encode() | ||||
|     elif isinstance(string, binary_type): | ||||
|         return string | ||||
|     if var: | ||||
|         raise TypeError('{0} must be a string, not {1!r}'.format(var, string)) | ||||
|     raise TypeError('expected a string, not ' + repr(string)) | ||||
|  | ||||
|  | ||||
| if PY3: | ||||
|     def text(string): | ||||
|         if isinstance(string, bytes): | ||||
|             return string.decode('utf-8') | ||||
|         return string | ||||
| else: | ||||
|     def text(string): | ||||
|         """Makes ``string`` to :class:`str` in Python 3. | ||||
|         Does nothing in Python 2. | ||||
|  | ||||
|         :param string: a string to cast it to :data:`text_type` | ||||
|         :type string: :class:`bytes`, :class:`str`, :class:`unicode` | ||||
|  | ||||
|         """ | ||||
|         return string | ||||
|  | ||||
|  | ||||
| #: The :func:`xrange()` function.  Alias for :func:`range()` in Python 3. | ||||
| xrange = range if PY3 else xrange  # noqa | ||||
|  | ||||
|  | ||||
| #: (:class:`type`, :class:`tuple`) Types for file objects that have | ||||
| #: ``fileno()``. | ||||
| file_types = io.RawIOBase if PY3 else (io.RawIOBase, types.FileType) | ||||
|  | ||||
|  | ||||
| def encode_filename(filename): | ||||
|     """If ``filename`` is a :data:`text_type`, encode it to | ||||
|     :data:`binary_type` according to filesystem's default encoding. | ||||
|  | ||||
|     """ | ||||
|     if isinstance(filename, text_type): | ||||
|         return filename.encode(sys.getfilesystemencoding()) | ||||
|     return filename | ||||
|  | ||||
|  | ||||
| try: | ||||
|     nested = contextlib.nested | ||||
| except AttributeError: | ||||
|     # http://hg.python.org/cpython/file/v2.7.6/Lib/contextlib.py#l88 | ||||
|     @contextlib.contextmanager | ||||
|     def nested(*managers): | ||||
|         exits = [] | ||||
|         vars = [] | ||||
|         exc = (None, None, None) | ||||
|         try: | ||||
|             for mgr in managers: | ||||
|                 exit = mgr.__exit__ | ||||
|                 enter = mgr.__enter__ | ||||
|                 vars.append(enter()) | ||||
|                 exits.append(exit) | ||||
|             yield vars | ||||
|         except: | ||||
|             exc = sys.exc_info() | ||||
|         finally: | ||||
|             while exits: | ||||
|                 exit = exits.pop() | ||||
|                 try: | ||||
|                     if exit(*exc): | ||||
|                         exc = (None, None, None) | ||||
|                 except: | ||||
|                     exc = sys.exc_info() | ||||
|             if exc != (None, None, None): | ||||
|                 # PEP 3109 | ||||
|                 e = exc[0](exc[1]) | ||||
|                 e.__traceback__ = e[2] | ||||
|                 raise e | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/wand/compat.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/compat.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										78
									
								
								lib/wand/display.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								lib/wand/display.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| """:mod:`wand.display` --- Displaying images | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| The :func:`display()` functions shows you the image.  It is useful for | ||||
| debugging. | ||||
|  | ||||
| If you are in Mac, the image will be opened by your default image application | ||||
| (:program:`Preview.app` usually). | ||||
|  | ||||
| If you are in Windows, the image will be opened by :program:`imdisplay.exe`, | ||||
| or your default image application (:program:`Windows Photo Viewer` usually) | ||||
| if :program:`imdisplay.exe` is unavailable. | ||||
|  | ||||
| You can use it from CLI also.  Execute :mod:`wand.display` module through | ||||
| :option:`python -m` option: | ||||
|  | ||||
| .. sourcecode:: console | ||||
|  | ||||
|    $ python -m wand.display wandtests/assets/mona-lisa.jpg | ||||
|  | ||||
| .. versionadded:: 0.1.9 | ||||
|  | ||||
| """ | ||||
| import ctypes | ||||
| import os | ||||
| import platform | ||||
| import sys | ||||
| import tempfile | ||||
|  | ||||
| from .image import Image | ||||
| from .api import library | ||||
| from .exceptions import BlobError, DelegateError | ||||
|  | ||||
| __all__ = 'display', | ||||
|  | ||||
|  | ||||
| def display(image, server_name=':0'): | ||||
|     """Displays the passed ``image``. | ||||
|  | ||||
|     :param image: an image to display | ||||
|     :type image: :class:`~wand.image.Image` | ||||
|     :param server_name: X11 server name to use.  it is ignored and not used | ||||
|                         for Mac.  default is ``':0'`` | ||||
|     :type server_name: :class:`str` | ||||
|  | ||||
|     """ | ||||
|     if not isinstance(image, Image): | ||||
|         raise TypeError('image must be a wand.image.Image instance, not ' + | ||||
|                         repr(image)) | ||||
|     system = platform.system() | ||||
|     if system == 'Windows': | ||||
|         try: | ||||
|             image.save(filename='win:.') | ||||
|         except DelegateError: | ||||
|             pass | ||||
|         else: | ||||
|             return | ||||
|     if system in ('Windows', 'Darwin'): | ||||
|         ext = '.' + image.format.lower() | ||||
|         path = tempfile.mktemp(suffix=ext) | ||||
|         image.save(filename=path) | ||||
|         os.system(('start ' if system == 'Windows' else 'open ') + path) | ||||
|     else: | ||||
|         library.MagickDisplayImage.argtypes = [ctypes.c_void_p, | ||||
|                                                ctypes.c_char_p] | ||||
|         library.MagickDisplayImage(image.wand, str(server_name).encode()) | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     if len(sys.argv) < 2: | ||||
|         print>>sys.stderr, 'usage: python -m wand.display FILE' | ||||
|         raise SystemExit | ||||
|     path = sys.argv[1] | ||||
|     try: | ||||
|         with Image(filename=path) as image: | ||||
|             display(image) | ||||
|     except BlobError: | ||||
|         print>>sys.stderr, 'cannot read the file', path | ||||
							
								
								
									
										1988
									
								
								lib/wand/drawing.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1988
									
								
								lib/wand/drawing.py
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										111
									
								
								lib/wand/exceptions.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								lib/wand/exceptions.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| """:mod:`wand.exceptions` --- Errors and warnings | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| This module maps MagickWand API's errors and warnings to Python's native | ||||
| exceptions and warnings. You can catch all MagickWand errors using Python's | ||||
| natural way to catch errors. | ||||
|  | ||||
| .. seealso:: | ||||
|  | ||||
|    `ImageMagick Exceptions <http://www.imagemagick.org/script/exception.php>`_ | ||||
|  | ||||
| .. versionadded:: 0.1.1 | ||||
|  | ||||
| """ | ||||
|  | ||||
|  | ||||
| class WandException(Exception): | ||||
|     """All Wand-related exceptions are derived from this class.""" | ||||
|  | ||||
|  | ||||
| class WandWarning(WandException, Warning): | ||||
|     """Base class for Wand-related warnings.""" | ||||
|  | ||||
|  | ||||
| class WandError(WandException): | ||||
|     """Base class for Wand-related errors.""" | ||||
|  | ||||
|  | ||||
| class WandFatalError(WandException): | ||||
|     """Base class for Wand-related fatal errors.""" | ||||
|  | ||||
|  | ||||
| class WandLibraryVersionError(WandException): | ||||
|     """Base class for Wand-related ImageMagick version errors. | ||||
|  | ||||
|     .. versionadded:: 0.3.2 | ||||
|  | ||||
|     """ | ||||
|  | ||||
|  | ||||
| #: (:class:`list`) A list of error/warning domains, these descriptions and | ||||
| #: codes. The form of elements is like: (domain name, description, codes). | ||||
| DOMAIN_MAP = [ | ||||
|     ('ResourceLimit', | ||||
|      'A program resource is exhausted e.g. not enough memory.', | ||||
|      (MemoryError,), | ||||
|      [300, 400, 700]), | ||||
|     ('Type', 'A font is unavailable; a substitution may have occurred.', (), | ||||
|      [305, 405, 705]), | ||||
|     ('Option', 'A command-line option was malformed.', (), [310, 410, 710]), | ||||
|     ('Delegate', 'An ImageMagick delegate failed to complete.', (), | ||||
|      [315, 415, 715]), | ||||
|     ('MissingDelegate', | ||||
|      'The image type can not be read or written because the appropriate; ' | ||||
|      'delegate is missing.', | ||||
|      (ImportError,), | ||||
|      [320, 420, 720]), | ||||
|     ('CorruptImage', 'The image file may be corrupt.', | ||||
|      (ValueError,), [325, 425, 725]), | ||||
|     ('FileOpen', 'The image file could not be opened for reading or writing.', | ||||
|      (IOError,), [330, 430, 730]), | ||||
|     ('Blob', 'A binary large object could not be allocated, read, or written.', | ||||
|      (IOError,), [335, 435, 735]), | ||||
|     ('Stream', 'There was a problem reading or writing from a stream.', | ||||
|      (IOError,), [340, 440, 740]), | ||||
|     ('Cache', 'Pixels could not be read or written to the pixel cache.', | ||||
|      (), [345, 445, 745]), | ||||
|     ('Coder', 'There was a problem with an image coder.', (), [350, 450, 750]), | ||||
|     ('Module', 'There was a problem with an image module.', (), | ||||
|      [355, 455, 755]), | ||||
|     ('Draw', 'A drawing operation failed.', (), [360, 460, 760]), | ||||
|     ('Image', 'The operation could not complete due to an incompatible image.', | ||||
|      (), [365, 465, 765]), | ||||
|     ('Wand', 'There was a problem specific to the MagickWand API.', (), | ||||
|      [370, 470, 770]), | ||||
|     ('Random', 'There is a problem generating a true or pseudo-random number.', | ||||
|      (), [375, 475, 775]), | ||||
|     ('XServer', 'An X resource is unavailable.', (), [380, 480, 780]), | ||||
|     ('Monitor', 'There was a problem activating the progress monitor.', (), | ||||
|      [385, 485, 785]), | ||||
|     ('Registry', 'There was a problem getting or setting the registry.', (), | ||||
|      [390, 490, 790]), | ||||
|     ('Configure', 'There was a problem getting a configuration file.', (), | ||||
|      [395, 495, 795]), | ||||
|     ('Policy', | ||||
|      'A policy denies access to a delegate, coder, filter, path, or resource.', | ||||
|      (), [399, 499, 799]) | ||||
| ] | ||||
|  | ||||
|  | ||||
| #: (:class:`list`) The list of (base_class, suffix) pairs (for each code). | ||||
| #: It would be zipped with :const:`DOMAIN_MAP` pairs' last element. | ||||
| CODE_MAP = [ | ||||
|     (WandWarning, 'Warning'), | ||||
|     (WandError, 'Error'), | ||||
|     (WandFatalError, 'FatalError') | ||||
| ] | ||||
|  | ||||
|  | ||||
| #: (:class:`dict`) The dictionary of (code, exc_type). | ||||
| TYPE_MAP = {} | ||||
|  | ||||
|  | ||||
| for domain, description, bases, codes in DOMAIN_MAP: | ||||
|     for code, (base, suffix) in zip(codes, CODE_MAP): | ||||
|         name = domain + suffix | ||||
|         locals()[name] = TYPE_MAP[code] = type(name, (base,) + bases, { | ||||
|             '__doc__': description, | ||||
|             'wand_error_code': code | ||||
|         }) | ||||
| del name, base, suffix | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/wand/exceptions.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/exceptions.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										103
									
								
								lib/wand/font.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								lib/wand/font.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | ||||
| """:mod:`wand.font` --- Fonts | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| .. versionadded:: 0.3.0 | ||||
|  | ||||
| :class:`Font` is an object which takes the :attr:`~Font.path` of font file, | ||||
| :attr:`~Font.size`, :attr:`~Font.color`, and whether to use | ||||
| :attr:`~Font.antialias`\ ing.  If you want to use font by its name rather | ||||
| than the file path, use TTFQuery_ package.  The font path resolution by its | ||||
| name is a very complicated problem to achieve. | ||||
|  | ||||
| .. seealso:: | ||||
|  | ||||
|    TTFQuery_ --- Find and Extract Information from TTF Files | ||||
|       TTFQuery builds on the `FontTools-TTX`_ package to allow the Python | ||||
|       programmer to accomplish a number of tasks: | ||||
|  | ||||
|       - query the system to find installed fonts | ||||
|  | ||||
|       - retrieve metadata about any TTF font file | ||||
|  | ||||
|         - this includes the glyph outlines (shape) of individual code-points, | ||||
|           which allows for rendering the glyphs in 3D (such as is done in | ||||
|           OpenGLContext) | ||||
|  | ||||
|       - lookup/find fonts by: | ||||
|  | ||||
|         - abstract family type | ||||
|         - proper font name | ||||
|  | ||||
|       - build simple metadata registries for run-time font matching | ||||
|  | ||||
| .. _TTFQuery: http://ttfquery.sourceforge.net/ | ||||
| .. _FontTools-TTX: http://sourceforge.net/projects/fonttools/ | ||||
|  | ||||
| """ | ||||
| import numbers | ||||
|  | ||||
| from .color import Color | ||||
| from .compat import string_type, text | ||||
|  | ||||
| __all__ = 'Font', | ||||
|  | ||||
|  | ||||
| class Font(tuple): | ||||
|     """Font struct which is a subtype of :class:`tuple`. | ||||
|  | ||||
|     :param path: the path of the font file | ||||
|     :type path: :class:`str`, :class:`basestring` | ||||
|     :param size: the size of typeface.  0 by default which means *autosized* | ||||
|     :type size: :class:`numbers.Real` | ||||
|     :param color: the color of typeface.  black by default | ||||
|     :type color: :class:`~wand.color.Color` | ||||
|     :param antialias: whether to use antialiasing.  :const:`True` by default | ||||
|     :type antialias: :class:`bool` | ||||
|  | ||||
|     .. versionchanged:: 0.3.9 | ||||
|        The ``size`` parameter becomes optional.  Its default value is | ||||
|        0, which means *autosized*. | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     def __new__(cls, path, size=0, color=None, antialias=True): | ||||
|         if not isinstance(path, string_type): | ||||
|             raise TypeError('path must be a string, not ' + repr(path)) | ||||
|         if not isinstance(size, numbers.Real): | ||||
|             raise TypeError('size must be a real number, not ' + repr(size)) | ||||
|         if color is None: | ||||
|             color = Color('black') | ||||
|         elif not isinstance(color, Color): | ||||
|             raise TypeError('color must be an instance of wand.color.Color, ' | ||||
|                             'not ' + repr(color)) | ||||
|         path = text(path) | ||||
|         return tuple.__new__(cls, (path, size, color, bool(antialias))) | ||||
|  | ||||
|     @property | ||||
|     def path(self): | ||||
|         """(:class:`basestring`) The path of font file.""" | ||||
|         return self[0] | ||||
|  | ||||
|     @property | ||||
|     def size(self): | ||||
|         """(:class:`numbers.Real`) The font size in pixels.""" | ||||
|         return self[1] | ||||
|  | ||||
|     @property | ||||
|     def color(self): | ||||
|         """(:class:`wand.color.Color`) The font color.""" | ||||
|         return self[2] | ||||
|  | ||||
|     @property | ||||
|     def antialias(self): | ||||
|         """(:class:`bool`) Whether to apply antialiasing (``True``) | ||||
|         or not (``False``). | ||||
|  | ||||
|         """ | ||||
|         return self[3] | ||||
|  | ||||
|     def __repr__(self): | ||||
|         return '{0.__module__}.{0.__name__}({1})'.format( | ||||
|             type(self), | ||||
|             tuple.__repr__(self) | ||||
|         ) | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/wand/font.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/font.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										3498
									
								
								lib/wand/image.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3498
									
								
								lib/wand/image.py
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								lib/wand/image.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/image.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										244
									
								
								lib/wand/resource.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								lib/wand/resource.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,244 @@ | ||||
| """:mod:`wand.resource` --- Global resource management | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| There is the global resource to manage in MagickWand API. This module | ||||
| implements automatic global resource management through reference counting. | ||||
|  | ||||
| """ | ||||
| import contextlib | ||||
| import ctypes | ||||
| import warnings | ||||
|  | ||||
| from .api import library | ||||
| from .compat import string_type | ||||
| from .exceptions import TYPE_MAP, WandException | ||||
|  | ||||
|  | ||||
| __all__ = ('genesis', 'terminus', 'increment_refcount', 'decrement_refcount', | ||||
|            'Resource', 'DestroyedResourceError') | ||||
|  | ||||
|  | ||||
| def genesis(): | ||||
|     """Instantiates the MagickWand API. | ||||
|  | ||||
|     .. warning:: | ||||
|  | ||||
|        Don't call this function directly. Use :func:`increment_refcount()` and | ||||
|        :func:`decrement_refcount()` functions instead. | ||||
|  | ||||
|     """ | ||||
|     library.MagickWandGenesis() | ||||
|  | ||||
|  | ||||
| def terminus(): | ||||
|     """Cleans up the MagickWand API. | ||||
|  | ||||
|     .. warning:: | ||||
|  | ||||
|        Don't call this function directly. Use :func:`increment_refcount()` and | ||||
|        :func:`decrement_refcount()` functions instead. | ||||
|  | ||||
|     """ | ||||
|     library.MagickWandTerminus() | ||||
|  | ||||
|  | ||||
| #: (:class:`numbers.Integral`) The internal integer value that maintains | ||||
| #: the number of referenced objects. | ||||
| #: | ||||
| #: .. warning:: | ||||
| #: | ||||
| #:    Don't touch this global variable. Use :func:`increment_refcount()` and | ||||
| #:    :func:`decrement_refcount()` functions instead. | ||||
| #: | ||||
| reference_count = 0 | ||||
|  | ||||
|  | ||||
| def increment_refcount(): | ||||
|     """Increments the :data:`reference_count` and instantiates the MagickWand | ||||
|     API if it is the first use. | ||||
|  | ||||
|     """ | ||||
|     global reference_count | ||||
|     if reference_count: | ||||
|         reference_count += 1 | ||||
|     else: | ||||
|         genesis() | ||||
|         reference_count = 1 | ||||
|  | ||||
|  | ||||
| def decrement_refcount(): | ||||
|     """Decrements the :data:`reference_count` and cleans up the MagickWand | ||||
|     API if it will be no more used. | ||||
|  | ||||
|     """ | ||||
|     global reference_count | ||||
|     if not reference_count: | ||||
|         raise RuntimeError('wand.resource.reference_count is already zero') | ||||
|     reference_count -= 1 | ||||
|     if not reference_count: | ||||
|         terminus() | ||||
|  | ||||
|  | ||||
| class Resource(object): | ||||
|     """Abstract base class for MagickWand object that requires resource | ||||
|     management. Its all subclasses manage the resource semiautomatically | ||||
|     and support :keyword:`with` statement as well:: | ||||
|  | ||||
|         with Resource() as resource: | ||||
|             # use the resource... | ||||
|             pass | ||||
|  | ||||
|     It doesn't implement constructor by itself, so subclasses should | ||||
|     implement it. Every constructor should assign the pointer of its | ||||
|     resource data into :attr:`resource` attribute inside of :keyword:`with` | ||||
|     :meth:`allocate()` context.  For example:: | ||||
|  | ||||
|         class Pizza(Resource): | ||||
|             '''My pizza yummy.''' | ||||
|  | ||||
|             def __init__(self): | ||||
|                 with self.allocate(): | ||||
|                     self.resource = library.NewPizza() | ||||
|  | ||||
|     .. versionadded:: 0.1.2 | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     #: (:class:`ctypes.CFUNCTYPE`) The :mod:`ctypes` predicate function | ||||
|     #: that returns whether the given pointer (that contains a resource data | ||||
|     #: usuaully) is a valid resource. | ||||
|     #: | ||||
|     #: .. note:: | ||||
|     #: | ||||
|     #:    It is an abstract attribute that has to be implemented | ||||
|     #:    in the subclass. | ||||
|     c_is_resource = NotImplemented | ||||
|  | ||||
|     #: (:class:`ctypes.CFUNCTYPE`) The :mod:`ctypes` function that destroys | ||||
|     #: the :attr:`resource`. | ||||
|     #: | ||||
|     #: .. note:: | ||||
|     #: | ||||
|     #:    It is an abstract attribute that has to be implemented | ||||
|     #:    in the subclass. | ||||
|     c_destroy_resource = NotImplemented | ||||
|  | ||||
|     #: (:class:`ctypes.CFUNCTYPE`) The :mod:`ctypes` function that gets | ||||
|     #: an exception from the :attr:`resource`. | ||||
|     #: | ||||
|     #: .. note:: | ||||
|     #: | ||||
|     #:    It is an abstract attribute that has to be implemented | ||||
|     #:    in the subclass. | ||||
|     c_get_exception = NotImplemented | ||||
|  | ||||
|     #: (:class:`ctypes.CFUNCTYPE`) The :mod:`ctypes` function that clears | ||||
|     #: an exception of the :attr:`resource`. | ||||
|     #: | ||||
|     #: .. note:: | ||||
|     #: | ||||
|     #:    It is an abstract attribute that has to be implemented | ||||
|     #:    in the subclass. | ||||
|     c_clear_exception = NotImplemented | ||||
|  | ||||
|     @property | ||||
|     def resource(self): | ||||
|         """Internal pointer to the resource instance. It may raise | ||||
|         :exc:`DestroyedResourceError` when the resource has destroyed already. | ||||
|  | ||||
|         """ | ||||
|         if getattr(self, 'c_resource', None) is None: | ||||
|             raise DestroyedResourceError(repr(self) + ' is destroyed already') | ||||
|         return self.c_resource | ||||
|  | ||||
|     @resource.setter | ||||
|     def resource(self, resource): | ||||
|         # Delete the existing resource if there is one | ||||
|         if getattr(self, 'c_resource', None): | ||||
|             self.destroy() | ||||
|  | ||||
|         if self.c_is_resource(resource): | ||||
|             self.c_resource = resource | ||||
|         else: | ||||
|             raise TypeError(repr(resource) + ' is an invalid resource') | ||||
|         increment_refcount() | ||||
|  | ||||
|     @resource.deleter | ||||
|     def resource(self): | ||||
|         self.c_destroy_resource(self.resource) | ||||
|         self.c_resource = None | ||||
|  | ||||
|     @contextlib.contextmanager | ||||
|     def allocate(self): | ||||
|         """Allocates the memory for the resource explicitly. Its subclasses | ||||
|         should assign the created resource into :attr:`resource` attribute | ||||
|         inside of this context. For example:: | ||||
|  | ||||
|             with resource.allocate(): | ||||
|                 resource.resource = library.NewResource() | ||||
|  | ||||
|         """ | ||||
|         increment_refcount() | ||||
|         try: | ||||
|             yield self | ||||
|         except: | ||||
|             decrement_refcount() | ||||
|             raise | ||||
|  | ||||
|     def destroy(self): | ||||
|         """Cleans up the resource explicitly. If you use the resource in | ||||
|         :keyword:`with` statement, it was called implicitly so have not to | ||||
|         call it. | ||||
|  | ||||
|         """ | ||||
|         del self.resource | ||||
|         decrement_refcount() | ||||
|  | ||||
|     def get_exception(self): | ||||
|         """Gets a current exception instance. | ||||
|  | ||||
|         :returns: a current exception. it can be ``None`` as well if any | ||||
|                   errors aren't occurred | ||||
|         :rtype: :class:`wand.exceptions.WandException` | ||||
|  | ||||
|         """ | ||||
|         severity = ctypes.c_int() | ||||
|         desc = self.c_get_exception(self.resource, ctypes.byref(severity)) | ||||
|         if severity.value == 0: | ||||
|             return | ||||
|         self.c_clear_exception(self.wand) | ||||
|         exc_cls = TYPE_MAP[severity.value] | ||||
|         message = desc.value | ||||
|         if not isinstance(message, string_type): | ||||
|             message = message.decode(errors='replace') | ||||
|         return exc_cls(message) | ||||
|  | ||||
|     def raise_exception(self, stacklevel=1): | ||||
|         """Raises an exception or warning if it has occurred.""" | ||||
|         e = self.get_exception() | ||||
|         if isinstance(e, Warning): | ||||
|             warnings.warn(e, stacklevel=stacklevel + 1) | ||||
|         elif isinstance(e, Exception): | ||||
|             raise e | ||||
|  | ||||
|     def __enter__(self): | ||||
|         return self | ||||
|  | ||||
|     def __exit__(self, type, value, traceback): | ||||
|         self.destroy() | ||||
|  | ||||
|     def __del__(self): | ||||
|         try: | ||||
|             self.destroy() | ||||
|         except DestroyedResourceError: | ||||
|             pass | ||||
|  | ||||
|  | ||||
| class DestroyedResourceError(WandException, ReferenceError, AttributeError): | ||||
|     """An error that rises when some code tries access to an already | ||||
|     destroyed resource. | ||||
|  | ||||
|     .. versionchanged:: 0.3.0 | ||||
|        It becomes a subtype of :exc:`wand.exceptions.WandException`. | ||||
|  | ||||
|     """ | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/wand/resource.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/resource.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										345
									
								
								lib/wand/sequence.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										345
									
								
								lib/wand/sequence.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,345 @@ | ||||
| """:mod:`wand.sequence` --- Sequences | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| .. versionadded:: 0.3.0 | ||||
|  | ||||
| """ | ||||
| import collections | ||||
| import contextlib | ||||
| import ctypes | ||||
| import numbers | ||||
|  | ||||
| from .api import libmagick, library | ||||
| from .compat import binary, xrange | ||||
| from .image import BaseImage, ImageProperty | ||||
| from .version import MAGICK_VERSION_INFO | ||||
|  | ||||
| __all__ = 'Sequence', 'SingleImage' | ||||
|  | ||||
|  | ||||
| class Sequence(ImageProperty, collections.MutableSequence): | ||||
|     """The list-like object that contains every :class:`SingleImage` | ||||
|     in the :class:`~wand.image.Image` container.  It implements | ||||
|     :class:`collections.Sequence` prototocol. | ||||
|  | ||||
|     .. versionadded:: 0.3.0 | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, image): | ||||
|         super(Sequence, self).__init__(image) | ||||
|         self.instances = [] | ||||
|  | ||||
|     def __del__(self): | ||||
|         for instance in self.instances: | ||||
|             if instance is not None: | ||||
|                 instance.c_resource = None | ||||
|  | ||||
|     @property | ||||
|     def current_index(self): | ||||
|         """(:class:`numbers.Integral`) The current index of | ||||
|         its internal iterator. | ||||
|  | ||||
|         .. note:: | ||||
|  | ||||
|            It's only for internal use. | ||||
|  | ||||
|         """ | ||||
|         return library.MagickGetIteratorIndex(self.image.wand) | ||||
|  | ||||
|     @current_index.setter | ||||
|     def current_index(self, index): | ||||
|         library.MagickSetIteratorIndex(self.image.wand, index) | ||||
|  | ||||
|     @contextlib.contextmanager | ||||
|     def index_context(self, index): | ||||
|         """Scoped setter of :attr:`current_index`.  Should be | ||||
|         used for :keyword:`with` statement e.g.:: | ||||
|  | ||||
|             with image.sequence.index_context(3): | ||||
|                 print(image.size) | ||||
|  | ||||
|         .. note:: | ||||
|  | ||||
|            It's only for internal use. | ||||
|  | ||||
|         """ | ||||
|         index = self.validate_position(index) | ||||
|         tmp_idx = self.current_index | ||||
|         self.current_index = index | ||||
|         yield index | ||||
|         self.current_index = tmp_idx | ||||
|  | ||||
|     def __len__(self): | ||||
|         return library.MagickGetNumberImages(self.image.wand) | ||||
|  | ||||
|     def validate_position(self, index): | ||||
|         if not isinstance(index, numbers.Integral): | ||||
|             raise TypeError('index must be integer, not ' + repr(index)) | ||||
|         length = len(self) | ||||
|         if index >= length or index < -length: | ||||
|             raise IndexError( | ||||
|                 'out of index: {0} (total: {1})'.format(index, length) | ||||
|             ) | ||||
|         if index < 0: | ||||
|             index += length | ||||
|         return index | ||||
|  | ||||
|     def validate_slice(self, slice_, as_range=False): | ||||
|         if not (slice_.step is None or slice_.step == 1): | ||||
|             raise ValueError('slicing with step is unsupported') | ||||
|         length = len(self) | ||||
|         if slice_.start is None: | ||||
|             start = 0 | ||||
|         elif slice_.start < 0: | ||||
|             start = length + slice_.start | ||||
|         else: | ||||
|             start = slice_.start | ||||
|         start = min(length, start) | ||||
|         if slice_.stop is None: | ||||
|             stop = 0 | ||||
|         elif slice_.stop < 0: | ||||
|             stop = length + slice_.stop | ||||
|         else: | ||||
|             stop = slice_.stop | ||||
|         stop = min(length, stop or length) | ||||
|         return xrange(start, stop) if as_range else slice(start, stop, None) | ||||
|  | ||||
|     def __getitem__(self, index): | ||||
|         if isinstance(index, slice): | ||||
|             slice_ = self.validate_slice(index) | ||||
|             return [self[i] for i in xrange(slice_.start, slice_.stop)] | ||||
|         index = self.validate_position(index) | ||||
|         instances = self.instances | ||||
|         instances_length = len(instances) | ||||
|         if index < instances_length: | ||||
|             instance = instances[index] | ||||
|             if (instance is not None and | ||||
|                     getattr(instance, 'c_resource', None) is not None): | ||||
|                 return instance | ||||
|         else: | ||||
|             number_to_extend = index - instances_length + 1 | ||||
|             instances.extend(None for _ in xrange(number_to_extend)) | ||||
|         wand = self.image.wand | ||||
|         tmp_idx = library.MagickGetIteratorIndex(wand) | ||||
|         library.MagickSetIteratorIndex(wand, index) | ||||
|         image = library.GetImageFromMagickWand(wand) | ||||
|         exc = libmagick.AcquireExceptionInfo() | ||||
|         single_image = libmagick.CloneImages(image, binary(str(index)), exc) | ||||
|         libmagick.DestroyExceptionInfo(exc) | ||||
|         single_wand = library.NewMagickWandFromImage(single_image) | ||||
|         single_image = libmagick.DestroyImage(single_image) | ||||
|         library.MagickSetIteratorIndex(wand, tmp_idx) | ||||
|         instance = SingleImage(single_wand, self.image, image) | ||||
|         self.instances[index] = instance | ||||
|         return instance | ||||
|  | ||||
|     def __setitem__(self, index, image): | ||||
|         if isinstance(index, slice): | ||||
|             tmp_idx = self.current_index | ||||
|             slice_ = self.validate_slice(index) | ||||
|             del self[slice_] | ||||
|             self.extend(image, offset=slice_.start) | ||||
|             self.current_index = tmp_idx | ||||
|         else: | ||||
|             if not isinstance(image, BaseImage): | ||||
|                 raise TypeError('image must be an instance of wand.image.' | ||||
|                                 'BaseImage, not ' + repr(image)) | ||||
|             with self.index_context(index) as index: | ||||
|                 library.MagickRemoveImage(self.image.wand) | ||||
|                 library.MagickAddImage(self.image.wand, image.wand) | ||||
|  | ||||
|     def __delitem__(self, index): | ||||
|         if isinstance(index, slice): | ||||
|             range_ = self.validate_slice(index, as_range=True) | ||||
|             for i in reversed(range_): | ||||
|                 del self[i] | ||||
|         else: | ||||
|             with self.index_context(index) as index: | ||||
|                 library.MagickRemoveImage(self.image.wand) | ||||
|                 if index < len(self.instances): | ||||
|                     del self.instances[index] | ||||
|  | ||||
|     def insert(self, index, image): | ||||
|         try: | ||||
|             index = self.validate_position(index) | ||||
|         except IndexError: | ||||
|             index = len(self) | ||||
|         if not isinstance(image, BaseImage): | ||||
|             raise TypeError('image must be an instance of wand.image.' | ||||
|                             'BaseImage, not ' + repr(image)) | ||||
|         if not self: | ||||
|             library.MagickAddImage(self.image.wand, image.wand) | ||||
|         elif index == 0: | ||||
|             tmp_idx = self.current_index | ||||
|             self_wand = self.image.wand | ||||
|             wand = image.sequence[0].wand | ||||
|             try: | ||||
|                 # Prepending image into the list using MagickSetFirstIterator() | ||||
|                 # and MagickAddImage() had not worked properly, but was fixed | ||||
|                 # since 6.7.6-0 (rev7106). | ||||
|                 if MAGICK_VERSION_INFO >= (6, 7, 6, 0): | ||||
|                     library.MagickSetFirstIterator(self_wand) | ||||
|                     library.MagickAddImage(self_wand, wand) | ||||
|                 else: | ||||
|                     self.current_index = 0 | ||||
|                     library.MagickAddImage(self_wand, | ||||
|                                            self.image.sequence[0].wand) | ||||
|                     self.current_index = 0 | ||||
|                     library.MagickAddImage(self_wand, wand) | ||||
|                     self.current_index = 0 | ||||
|                     library.MagickRemoveImage(self_wand) | ||||
|             finally: | ||||
|                 self.current_index = tmp_idx | ||||
|         else: | ||||
|             with self.index_context(index - 1): | ||||
|                 library.MagickAddImage(self.image.wand, image.sequence[0].wand) | ||||
|         self.instances.insert(index, None) | ||||
|  | ||||
|     def append(self, image): | ||||
|         if not isinstance(image, BaseImage): | ||||
|             raise TypeError('image must be an instance of wand.image.' | ||||
|                             'BaseImage, not ' + repr(image)) | ||||
|         wand = self.image.wand | ||||
|         tmp_idx = self.current_index | ||||
|         try: | ||||
|             library.MagickSetLastIterator(wand) | ||||
|             library.MagickAddImage(wand, image.sequence[0].wand) | ||||
|         finally: | ||||
|             self.current_index = tmp_idx | ||||
|         self.instances.append(None) | ||||
|  | ||||
|     def extend(self, images, offset=None): | ||||
|         tmp_idx = self.current_index | ||||
|         wand = self.image.wand | ||||
|         length = 0 | ||||
|         try: | ||||
|             if offset is None: | ||||
|                 library.MagickSetLastIterator(self.image.wand) | ||||
|             else: | ||||
|                 if offset == 0: | ||||
|                     images = iter(images) | ||||
|                     self.insert(0, next(images)) | ||||
|                     offset += 1 | ||||
|                 self.current_index = offset - 1 | ||||
|             if isinstance(images, type(self)): | ||||
|                 library.MagickAddImage(wand, images.image.wand) | ||||
|                 length = len(images) | ||||
|             else: | ||||
|                 delta = 1 if MAGICK_VERSION_INFO >= (6, 7, 6, 0) else 2 | ||||
|                 for image in images: | ||||
|                     if not isinstance(image, BaseImage): | ||||
|                         raise TypeError( | ||||
|                             'images must consist of only instances of ' | ||||
|                             'wand.image.BaseImage, not ' + repr(image) | ||||
|                         ) | ||||
|                     else: | ||||
|                         library.MagickAddImage(wand, image.sequence[0].wand) | ||||
|                         self.instances = [] | ||||
|                         if offset is None: | ||||
|                             library.MagickSetLastIterator(self.image.wand) | ||||
|                         else: | ||||
|                             self.current_index += delta | ||||
|                         length += 1 | ||||
|         finally: | ||||
|             self.current_index = tmp_idx | ||||
|         null_list = [None] * length | ||||
|         if offset is None: | ||||
|             self.instances[offset:] = null_list | ||||
|         else: | ||||
|             self.instances[offset:offset] = null_list | ||||
|  | ||||
|     def _repr_png_(self): | ||||
|         library.MagickResetIterator(self.image.wand) | ||||
|         repr_wand = library.MagickAppendImages(self.image.wand, 1) | ||||
|         length = ctypes.c_size_t() | ||||
|         blob_p = library.MagickGetImagesBlob(repr_wand, | ||||
|                                              ctypes.byref(length)) | ||||
|         if blob_p and length.value: | ||||
|             blob = ctypes.string_at(blob_p, length.value) | ||||
|             library.MagickRelinquishMemory(blob_p) | ||||
|             return blob | ||||
|         else: | ||||
|             return None | ||||
|  | ||||
|  | ||||
| class SingleImage(BaseImage): | ||||
|     """Each single image in :class:`~wand.image.Image` container. | ||||
|     For example, it can be a frame of GIF animation. | ||||
|  | ||||
|     Note that all changes on single images are invisible to their | ||||
|     containers until they are :meth:`~wand.image.BaseImage.close`\ d | ||||
|     (:meth:`~wand.resource.Resource.destroy`\ ed). | ||||
|  | ||||
|     .. versionadded:: 0.3.0 | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     #: (:class:`wand.image.Image`) The container image. | ||||
|     container = None | ||||
|  | ||||
|     def __init__(self, wand, container, c_original_resource): | ||||
|         super(SingleImage, self).__init__(wand) | ||||
|         self.container = container | ||||
|         self.c_original_resource = c_original_resource | ||||
|         self._delay = None | ||||
|  | ||||
|     @property | ||||
|     def sequence(self): | ||||
|         return self, | ||||
|  | ||||
|     @property | ||||
|     def index(self): | ||||
|         """(:class:`numbers.Integral`) The index of the single image in | ||||
|         the :attr:`container` image. | ||||
|  | ||||
|         """ | ||||
|         wand = self.container.wand | ||||
|         library.MagickResetIterator(wand) | ||||
|         image = library.GetImageFromMagickWand(wand) | ||||
|         i = 0 | ||||
|         while self.c_original_resource != image and image: | ||||
|             image = libmagick.GetNextImageInList(image) | ||||
|             i += 1 | ||||
|         assert image | ||||
|         assert self.c_original_resource == image | ||||
|         return i | ||||
|  | ||||
|     @property | ||||
|     def delay(self): | ||||
|         """(:class:`numbers.Integral`) The delay to pause before display | ||||
|         the next image (in the :attr:`~wand.image.BaseImage.sequence` of | ||||
|         its :attr:`container`).  It's hundredths of a second. | ||||
|  | ||||
|         """ | ||||
|         if self._delay is None: | ||||
|             container = self.container | ||||
|             with container.sequence.index_context(self.index): | ||||
|                 self._delay = library.MagickGetImageDelay(container.wand) | ||||
|         return self._delay | ||||
|  | ||||
|     @delay.setter | ||||
|     def delay(self, delay): | ||||
|         if not isinstance(delay, numbers.Integral): | ||||
|             raise TypeError('delay must be an integer, not ' + repr(delay)) | ||||
|         elif delay < 0: | ||||
|             raise ValueError('delay cannot be less than zero') | ||||
|         self._delay = delay | ||||
|  | ||||
|     def destroy(self): | ||||
|         if self.dirty: | ||||
|             self.container.sequence[self.index] = self | ||||
|         if self._delay is not None: | ||||
|             container = self.container | ||||
|             with container.sequence.index_context(self.index): | ||||
|                 library.MagickSetImageDelay(container.wand, self._delay) | ||||
|         super(SingleImage, self).destroy() | ||||
|  | ||||
|     def __repr__(self): | ||||
|         cls = type(self) | ||||
|         if getattr(self, 'c_resource', None) is None: | ||||
|             return '<{0}.{1}: (closed)>'.format(cls.__module__, cls.__name__) | ||||
|         return '<{0}.{1}: {2} ({3}x{4})>'.format( | ||||
|             cls.__module__, cls.__name__, | ||||
|             self.signature[:7], self.width, self.height | ||||
|         ) | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/wand/sequence.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/sequence.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										251
									
								
								lib/wand/version.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										251
									
								
								lib/wand/version.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,251 @@ | ||||
| """:mod:`wand.version` --- Version data | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| You can find the current version in the command line interface: | ||||
|  | ||||
| .. sourcecode:: console | ||||
|  | ||||
|    $ python -m wand.version | ||||
|    0.0.0 | ||||
|    $ python -m wand.version --verbose | ||||
|    Wand 0.0.0 | ||||
|    ImageMagick 6.7.7-6 2012-06-03 Q16 http://www.imagemagick.org | ||||
|    $ python -m wand.version --config | grep CC | cut -d : -f 2 | ||||
|    gcc -std=gnu99 -std=gnu99 | ||||
|    $ python -m wand.version --fonts | grep Helvetica | ||||
|    Helvetica | ||||
|    Helvetica-Bold | ||||
|    Helvetica-Light | ||||
|    Helvetica-Narrow | ||||
|    Helvetica-Oblique | ||||
|    $ python -m wand.version --formats | grep CMYK | ||||
|    CMYK | ||||
|    CMYKA | ||||
|  | ||||
| .. versionadded:: 0.2.0 | ||||
|    The command line interface. | ||||
|  | ||||
| .. versionadded:: 0.2.2 | ||||
|    The ``--verbose``/``-v`` option which also prints ImageMagick library | ||||
|    version for CLI. | ||||
|  | ||||
| .. versionadded:: 0.4.1 | ||||
|    The ``--fonts``, ``--formats``, & ``--config`` option allows printing | ||||
|    additional information about ImageMagick library. | ||||
|  | ||||
| """ | ||||
| from __future__ import print_function | ||||
|  | ||||
| import ctypes | ||||
| import datetime | ||||
| import re | ||||
| import sys | ||||
|  | ||||
| try: | ||||
|     from .api import libmagick, library | ||||
| except ImportError: | ||||
|     libmagick = None | ||||
| from .compat import binary, string_type, text | ||||
|  | ||||
|  | ||||
| __all__ = ('VERSION', 'VERSION_INFO', 'MAGICK_VERSION', | ||||
|            'MAGICK_VERSION_INFO', 'MAGICK_VERSION_NUMBER', | ||||
|            'MAGICK_RELEASE_DATE', 'MAGICK_RELEASE_DATE_STRING', | ||||
|            'QUANTUM_DEPTH', 'configure_options', 'fonts', 'formats') | ||||
|  | ||||
| #: (:class:`tuple`) The version tuple e.g. ``(0, 1, 2)``. | ||||
| #: | ||||
| #: .. versionchanged:: 0.1.9 | ||||
| #:    Becomes :class:`tuple`.  (It was string before.) | ||||
| VERSION_INFO = (0, 4, 2) | ||||
|  | ||||
| #: (:class:`basestring`) The version string e.g. ``'0.1.2'``. | ||||
| #: | ||||
| #: .. versionchanged:: 0.1.9 | ||||
| #:    Becomes string.  (It was :class:`tuple` before.) | ||||
| VERSION = '{0}.{1}.{2}'.format(*VERSION_INFO) | ||||
|  | ||||
| if libmagick: | ||||
|     c_magick_version = ctypes.c_size_t() | ||||
|     #: (:class:`basestring`) The version string of the linked ImageMagick | ||||
|     #: library.  The exactly same string to the result of | ||||
|     #: :c:func:`GetMagickVersion` function. | ||||
|     #: | ||||
|     #: Example:: | ||||
|     #: | ||||
|     #:    'ImageMagick 6.7.7-6 2012-06-03 Q16 http://www.imagemagick.org' | ||||
|     #: | ||||
|     #: .. versionadded:: 0.2.1 | ||||
|     MAGICK_VERSION = text( | ||||
|         libmagick.GetMagickVersion(ctypes.byref(c_magick_version)) | ||||
|     ) | ||||
|  | ||||
|     #: (:class:`numbers.Integral`) The version number of the linked | ||||
|     #: ImageMagick library. | ||||
|     #: | ||||
|     #: .. versionadded:: 0.2.1 | ||||
|     MAGICK_VERSION_NUMBER = c_magick_version.value | ||||
|  | ||||
|     _match = re.match(r'^ImageMagick\s+(\d+)\.(\d+)\.(\d+)(?:-(\d+))?', | ||||
|                       MAGICK_VERSION) | ||||
|     #: (:class:`tuple`) The version tuple e.g. ``(6, 7, 7, 6)`` of | ||||
|     #: :const:`MAGICK_VERSION`. | ||||
|     #: | ||||
|     #: .. versionadded:: 0.2.1 | ||||
|     MAGICK_VERSION_INFO = tuple(int(v or 0) for v in _match.groups()) | ||||
|  | ||||
|     #: (:class:`datetime.date`) The release date of the linked ImageMagick | ||||
|     #: library.  The same to the result of :c:func:`GetMagickReleaseDate` | ||||
|     #: function. | ||||
|     #: | ||||
|     #: .. versionadded:: 0.2.1 | ||||
|     MAGICK_RELEASE_DATE_STRING = text(libmagick.GetMagickReleaseDate()) | ||||
|  | ||||
|     #: (:class:`basestring`) The date string e.g. ``'2012-06-03'`` of | ||||
|     #: :const:`MAGICK_RELEASE_DATE_STRING`.  This value is the exactly same | ||||
|     #: string to the result of :c:func:`GetMagickReleaseDate` function. | ||||
|     #: | ||||
|     #: .. versionadded:: 0.2.1 | ||||
|     MAGICK_RELEASE_DATE = datetime.date( | ||||
|         *map(int, MAGICK_RELEASE_DATE_STRING.split('-'))) | ||||
|  | ||||
|     c_quantum_depth = ctypes.c_size_t() | ||||
|     libmagick.GetMagickQuantumDepth(ctypes.byref(c_quantum_depth)) | ||||
|     #: (:class:`numbers.Integral`) The quantum depth configuration of | ||||
|     #: the linked ImageMagick library.  One of 8, 16, 32, or 64. | ||||
|     #: | ||||
|     #: .. versionadded:: 0.3.0 | ||||
|     QUANTUM_DEPTH = c_quantum_depth.value | ||||
|  | ||||
|     del c_magick_version, _match, c_quantum_depth | ||||
|  | ||||
|  | ||||
| def configure_options(pattern='*'): | ||||
|     """ | ||||
|     Queries ImageMagick library for configurations options given at | ||||
|     compile-time. | ||||
|  | ||||
|     Example: Find where the ImageMagick documents are installed:: | ||||
|  | ||||
|         >>> from wand.version import configure_options | ||||
|         >>> configure_options('DOC*') | ||||
|         {'DOCUMENTATION_PATH': '/usr/local/share/doc/ImageMagick-6'} | ||||
|  | ||||
|     :param pattern: A term to filter queries against. Supports wildcard '*' | ||||
|                     characters. Default patterns '*' for all options. | ||||
|     :type pattern: :class:`basestring` | ||||
|     :returns: Directory of configuration options matching given pattern | ||||
|     :rtype: :class:`collections.defaultdict` | ||||
|     """ | ||||
|     if not isinstance(pattern, string_type): | ||||
|         raise TypeError('pattern must be a string, not ' + repr(pattern)) | ||||
|     pattern_p = ctypes.create_string_buffer(binary(pattern)) | ||||
|     config_count = ctypes.c_size_t(0) | ||||
|     configs = {} | ||||
|     configs_p = library.MagickQueryConfigureOptions(pattern_p, | ||||
|                                                     ctypes.byref(config_count)) | ||||
|     cursor = 0 | ||||
|     while cursor < config_count.value: | ||||
|         config = configs_p[cursor].value | ||||
|         value = library.MagickQueryConfigureOption(config) | ||||
|         configs[text(config)] = text(value.value) | ||||
|         cursor += 1 | ||||
|     return configs | ||||
|  | ||||
|  | ||||
| def fonts(pattern='*'): | ||||
|     """ | ||||
|     Queries ImageMagick library for available fonts. | ||||
|  | ||||
|     Available fonts can be configured by defining `types.xml`, | ||||
|     `type-ghostscript.xml`, or `type-windows.xml`. | ||||
|     Use :func:`wand.version.configure_options` to locate system search path, | ||||
|     and `resources <http://www.imagemagick.org/script/resources.php>`_ | ||||
|     article for defining xml file. | ||||
|  | ||||
|     Example: List all bold Helvetica fonts:: | ||||
|  | ||||
|         >>> from wand.version import fonts | ||||
|         >>> fonts('*Helvetica*Bold*') | ||||
|         ['Helvetica-Bold', 'Helvetica-Bold-Oblique', 'Helvetica-BoldOblique', | ||||
|          'Helvetica-Narrow-Bold', 'Helvetica-Narrow-BoldOblique'] | ||||
|  | ||||
|  | ||||
|     :param pattern: A term to filter queries against. Supports wildcard '*' | ||||
|                     characters. Default patterns '*' for all options. | ||||
|     :type pattern: :class:`basestring` | ||||
|     :returns: Sequence of matching fonts | ||||
|     :rtype: :class:`collections.Sequence` | ||||
|     """ | ||||
|     if not isinstance(pattern, string_type): | ||||
|         raise TypeError('pattern must be a string, not ' + repr(pattern)) | ||||
|     pattern_p = ctypes.create_string_buffer(binary(pattern)) | ||||
|     number_fonts = ctypes.c_size_t(0) | ||||
|     fonts = [] | ||||
|     fonts_p = library.MagickQueryFonts(pattern_p, | ||||
|                                        ctypes.byref(number_fonts)) | ||||
|     cursor = 0 | ||||
|     while cursor < number_fonts.value: | ||||
|         font = fonts_p[cursor].value | ||||
|         fonts.append(text(font)) | ||||
|         cursor += 1 | ||||
|     return fonts | ||||
|  | ||||
|  | ||||
| def formats(pattern='*'): | ||||
|     """ | ||||
|     Queries ImageMagick library for supported formats. | ||||
|  | ||||
|     Example: List supported PNG formats:: | ||||
|  | ||||
|         >>> from wand.version import formats | ||||
|         >>> formats('PNG*') | ||||
|         ['PNG', 'PNG00', 'PNG8', 'PNG24', 'PNG32', 'PNG48', 'PNG64'] | ||||
|  | ||||
|  | ||||
|     :param pattern: A term to filter formats against. Supports wildcards '*' | ||||
|                     characters. Default pattern '*' for all formats. | ||||
|     :type pattern: :class:`basestring` | ||||
|     :returns: Sequence of matching formats | ||||
|     :rtype: :class:`collections.Sequence` | ||||
|     """ | ||||
|     if not isinstance(pattern, string_type): | ||||
|         raise TypeError('pattern must be a string, not ' + repr(pattern)) | ||||
|     pattern_p = ctypes.create_string_buffer(binary(pattern)) | ||||
|     number_formats = ctypes.c_size_t(0) | ||||
|     formats = [] | ||||
|     formats_p = library.MagickQueryFormats(pattern_p, | ||||
|                                            ctypes.byref(number_formats)) | ||||
|     cursor = 0 | ||||
|     while cursor < number_formats.value: | ||||
|         value = formats_p[cursor].value | ||||
|         formats.append(text(value)) | ||||
|         cursor += 1 | ||||
|     return formats | ||||
|  | ||||
| if __doc__ is not None: | ||||
|     __doc__ = __doc__.replace('0.0.0', VERSION) | ||||
|  | ||||
| del libmagick | ||||
|  | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|     options = frozenset(sys.argv[1:]) | ||||
|     if '-v' in options or '--verbose' in options: | ||||
|         print('Wand', VERSION) | ||||
|         try: | ||||
|             print(MAGICK_VERSION) | ||||
|         except NameError: | ||||
|             pass | ||||
|     elif '--fonts' in options: | ||||
|         for font in fonts(): | ||||
|             print(font) | ||||
|     elif '--formats' in options: | ||||
|         for supported_format in formats(): | ||||
|             print(supported_format) | ||||
|     elif '--config' in options: | ||||
|         config_options = configure_options() | ||||
|         for key in config_options: | ||||
|             print('{:24s}: {}'.format(key, config_options[key])) | ||||
|     else: | ||||
|         print(VERSION) | ||||
							
								
								
									
										
											BIN
										
									
								
								lib/wand/version.pyc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								lib/wand/version.pyc
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user
	 Cervinko Cera
					Cervinko Cera