1# wrap VipsImage
2
3from __future__ import division
4
5import numbers
6
7import pyvips
8from pyvips import ffi, glib_lib, vips_lib, Error, _to_bytes, \
9    _to_string, _to_string_copy, GValue, at_least_libvips
10
11
12# either a single number, or a table of numbers
13def _is_pixel(value):
14    return (isinstance(value, numbers.Number) or
15            (isinstance(value, list) and not
16            isinstance(value, pyvips.Image)))
17
18
19# test for rectangular array of something
20def _is_2D(array):
21    if not isinstance(array, list):
22        return False
23
24    for x in array:
25        if not isinstance(x, list):
26            return False
27        if len(x) != len(array[0]):
28            return False
29
30    return True
31
32
33# apply a function to a thing, or map over a list
34# we often need to do something like (1.0 / other) and need to work for lists
35# as well as scalars
36def _smap(func, x):
37    if isinstance(x, list):
38        return list(map(func, x))
39    else:
40        return func(x)
41
42
43def _call_enum(image, other, base, operation):
44    if _is_pixel(other):
45        return pyvips.Operation.call(base + '_const', image, operation, other)
46    else:
47        return pyvips.Operation.call(base, image, other, operation)
48
49
50def _run_cmplx(fn, image):
51    """Run a complex function on a non-complex image.
52
53    The image needs to be complex, or have an even number of bands. The input
54    can be int, the output is always float or double.
55    """
56    original_format = image.format
57
58    if image.format != 'complex' and image.format != 'dpcomplex':
59        if image.bands % 2 != 0:
60            raise Error('not an even number of bands')
61
62        if image.format != 'float' and image.format != 'double':
63            image = image.cast('float')
64
65        if image.format == 'double':
66            new_format = 'dpcomplex'
67        else:
68            new_format = 'complex'
69
70        image = image.copy(format=new_format, bands=image.bands / 2)
71
72    image = fn(image)
73
74    if original_format != 'complex' and original_format != 'dpcomplex':
75        if image.format == 'dpcomplex':
76            new_format = 'double'
77        else:
78            new_format = 'float'
79
80        image = image.copy(format=new_format, bands=image.bands * 2)
81
82    return image
83
84
85# https://stackoverflow.com/a/22409540/1480019
86# https://github.com/benjaminp/six/blob/33b584b2c551548021adb92a028ceaf892deb5be/six.py#L846-L861
87def _with_metaclass(metaclass):
88    """Class decorator for creating a class with a metaclass."""
89    def wrapper(cls):
90        orig_vars = cls.__dict__.copy()
91        slots = orig_vars.get('__slots__')
92        if slots is not None:
93            if isinstance(slots, str):
94                slots = [slots]
95            for slots_var in slots:
96                orig_vars.pop(slots_var)
97        orig_vars.pop('__dict__', None)
98        orig_vars.pop('__weakref__', None)
99        if hasattr(cls, '__qualname__'):
100            orig_vars['__qualname__'] = cls.__qualname__
101        return metaclass(cls.__name__, cls.__bases__, orig_vars)
102    return wrapper
103
104
105# decorator to set docstring
106def _add_doc(name):
107    try:
108        docstring = pyvips.Operation.generate_docstring(name)
109    except Error:
110        docstring = None
111
112    def _doc(func):
113        func.__doc__ = docstring
114        return func
115
116    return _doc
117
118
119# decorator to set deprecated
120def _deprecated(note):
121    def _dep(func):
122        func.__deprecated__ = note
123        return func
124
125    return _dep
126
127
128# metaclass for Image ... getattr on this implements the class methods
129class ImageType(type):
130    def __getattr__(cls, name):
131        # logger.debug('ImageType.__getattr__ %s', name)
132
133        @_add_doc(name)
134        def call_function(*args, **kwargs):
135            return pyvips.Operation.call(name, *args, **kwargs)
136
137        return call_function
138
139
140@_with_metaclass(ImageType)
141class Image(pyvips.VipsObject):
142    """Wrap a VipsImage object.
143
144    """
145    __slots__ = ('_references',)
146
147    # private static
148
149    @staticmethod
150    def _imageize(self, value):
151        # careful! self can be None if value is a 2D array
152        if isinstance(value, Image):
153            return value
154        elif _is_2D(value):
155            return Image.new_from_array(value)
156        else:
157            return self.new_from_image(value)
158
159    def __init__(self, pointer):
160        # a list of other objects which this object depends on and which need
161        # to be kept alive
162        # we can't use a set because set elements are unique under "==", and
163        # Python checks memoryview equality with hash functions, not pointer
164        # equality
165        self._references = []
166        # logger.debug('Image.__init__: pointer = %s', pointer)
167        super(Image, self).__init__(pointer)
168
169    # constructors
170
171    @staticmethod
172    def new_from_file(vips_filename, **kwargs):
173        """Load an image from a file.
174
175        This method can load images in any format supported by vips. The
176        filename can include load options, for example::
177
178            image = pyvips.Image.new_from_file('fred.jpg[shrink=2]')
179
180        You can also supply options as keyword arguments, for example::
181
182            image = pyvips.Image.new_from_file('fred.jpg', shrink=2)
183
184        The full set of options available depend upon the load operation that
185        will be executed. Try something like::
186
187            $ vips jpegload
188
189        at the command-line to see a summary of the available options for the
190        JPEG loader.
191
192        Loading is fast: only enough of the image is loaded to be able to fill
193        out the header. Pixels will only be decompressed when they are needed.
194
195        Args:
196            vips_filename (str): The disc file to load the image from, with
197                optional appended arguments.
198
199        All loaders support at least the following options:
200
201        Keyword args:
202            memory (bool): If set True, load the image via memory rather than
203                via a temporary disc file. See :meth:`.new_temp_file` for
204                notes on where temporary files are created. Small images are
205                loaded via memory by default, use ``VIPS_DISC_THRESHOLD`` to
206                set the definition of small.
207            access (Access): Hint the expected access pattern for the image.
208            fail (bool): If set True, the loader will fail with an error on
209                the first serious error in the file. By default, libvips
210                will attempt to read everything it can from a damaged image.
211
212        Returns:
213            A new :class:`.Image`.
214
215        Raises:
216            :class:`.Error`
217
218        """
219        vips_filename = _to_bytes(vips_filename)
220        pointer = vips_lib.vips_filename_get_filename(vips_filename)
221        filename = _to_string_copy(pointer)
222
223        pointer = vips_lib.vips_filename_get_options(vips_filename)
224        options = _to_string_copy(pointer)
225
226        pointer = vips_lib.vips_foreign_find_load(vips_filename)
227        if pointer == ffi.NULL:
228            raise Error('unable to load from file {0}'.format(vips_filename))
229        name = _to_string(pointer)
230
231        return pyvips.Operation.call(name, filename,
232                                     string_options=options, **kwargs)
233
234    @staticmethod
235    def new_from_buffer(data, options, **kwargs):
236        """Load a formatted image from memory.
237
238        This behaves exactly as :meth:`new_from_file`, but the image is
239        loaded from the memory object rather than from a file. The memory
240        object can be anything that supports the Python buffer protocol.
241
242        Args:
243            data (array, bytearray, bytes, buffer): The memory object to
244                load the image from.
245            options (str): Load options as a string. Use ``""`` for no options.
246
247        All loaders support at least the following options:
248
249        Keyword args:
250            access (Access): Hint the expected access pattern for the image.
251            fail (bool): If set True, the loader will fail with an error on the
252                first serious error in the image. By default, libvips will
253                attempt to read everything it can from a damaged image.
254
255        Returns:
256            A new :class:`Image`.
257
258        Raises:
259            :class:`.Error`
260
261        """
262        pointer = vips_lib.vips_foreign_find_load_buffer(data, len(data))
263        if pointer == ffi.NULL:
264            raise Error('unable to load from buffer')
265        name = _to_string(pointer)
266
267        return pyvips.Operation.call(name, data,
268                                     string_options=options, **kwargs)
269
270    @staticmethod
271    def new_from_array(array, scale=1.0, offset=0.0):
272        """Create an image from a 1D or 2D array.
273
274        A new one-band image with :class:`BandFormat` ``'double'`` pixels is
275        created from the array. These image are useful with the libvips
276        convolution operator :meth:`Image.conv`.
277
278        Args:
279            array (list[list[float]]): Create the image from these values.
280                1D arrays become a single row of pixels.
281            scale (float): Default to 1.0. What to divide each pixel by after
282                convolution.  Useful for integer convolution masks.
283            offset (float): Default to 0.0. What to subtract from each pixel
284                after convolution.  Useful for integer convolution masks.
285
286        Returns:
287            A new :class:`Image`.
288
289        Raises:
290            :class:`.Error`
291
292        """
293        if not _is_2D(array):
294            array = [array]
295
296        height = len(array)
297        width = len(array[0])
298
299        n = width * height
300        a = ffi.new('double[]', n)
301        for y in range(0, height):
302            for x in range(0, width):
303                a[x + y * width] = array[y][x]
304
305        vi = vips_lib.vips_image_new_matrix_from_array(width, height, a, n)
306        if vi == ffi.NULL:
307            raise Error('unable to make image from matrix')
308        image = pyvips.Image(vi)
309
310        image.set_type(GValue.gdouble_type, 'scale', scale)
311        image.set_type(GValue.gdouble_type, 'offset', offset)
312
313        return image
314
315    @staticmethod
316    def new_from_memory(data, width, height, bands, format):
317        """Wrap an image around a memory array.
318
319        Wraps an Image around an area of memory containing a C-style array. For
320        example, if the ``data`` memory array contains four bytes with the
321        values 1, 2, 3, 4, you can make a one-band, 2x2 uchar image from
322        it like this::
323
324            image = Image.new_from_memory(data, 2, 2, 1, 'uchar')
325
326        A reference is kept to the data object, so it will not be
327        garbage-collected until the returned image is garbage-collected.
328
329        This method is useful for efficiently transferring images from PIL or
330        NumPy into libvips.
331
332        See :meth:`.write_to_memory` for the opposite operation.
333
334        Use :meth:`.copy` to set other image attributes.
335
336        Args:
337            data (bytes): A memoryview or buffer object.
338            width (int): Image width in pixels.
339            height (int): Image height in pixels.
340            bands (int): Number of bands.
341            format (BandFormat): Band format.
342
343        Returns:
344            A new :class:`Image`.
345
346        Raises:
347            :class:`.Error`
348
349        """
350
351        format_value = GValue.to_enum(GValue.format_type, format)
352        pointer = ffi.from_buffer(data)
353        # py3:
354        #   - memoryview has .nbytes for number of bytes in object
355        #   - len() returns number of elements in top array
356        # py2:
357        #   - buffer has no nbytes member
358        #   - but len() gives number of bytes in object
359        nbytes = data.nbytes if hasattr(data, 'nbytes') else len(data)
360        vi = vips_lib.vips_image_new_from_memory(pointer,
361                                                 nbytes,
362                                                 width, height, bands,
363                                                 format_value)
364        if vi == ffi.NULL:
365            raise Error('unable to make image from memory')
366
367        image = pyvips.Image(vi)
368
369        # keep a secret ref to the underlying object .. this reference will be
370        # inherited by things that in turn depend on us, so the memory we are
371        # using will not be freed
372        image._references.append(data)
373
374        return image
375
376    @staticmethod
377    def new_from_source(source, options, **kwargs):
378        """Load a formatted image from a source.
379
380        This behaves exactly as :meth:`new_from_file`, but the image is
381        loaded from the source rather than from a file.
382
383        Args:
384            source (Source): The source to load the image from.
385            options (str): Load options as a string. Use ``""`` for no options.
386
387        All loaders support at least the following options:
388
389        Keyword args:
390            access (Access): Hint the expected access pattern for the image.
391            fail (bool): If set True, the loader will fail with an error on the
392                first serious error in the image. By default, libvips will
393                attempt to read everything it can from a damaged image.
394
395        Returns:
396            A new :class:`Image`.
397
398        Raises:
399            :class:`.Error`
400
401        """
402        pointer = vips_lib.vips_foreign_find_load_source(source.pointer)
403        if pointer == ffi.NULL:
404            raise Error('unable to load from source')
405        name = _to_string(pointer)
406
407        return pyvips.Operation.call(name, source,
408                                     string_options=options, **kwargs)
409
410    @staticmethod
411    def new_temp_file(format):
412        """Make a new temporary image.
413
414        Returns an image backed by a temporary file. When written to with
415        :func:`Image.write`, a temporary file will be created on disc in the
416        specified format. When the image is closed, the file will be deleted
417        automatically.
418
419        The file is created in the temporary directory. This is set with
420        the environment variable ``TMPDIR``. If this is not set, then on
421        Unix systems, vips will default to ``/tmp``. On Windows, vips uses
422        ``GetTempPath()`` to find the temporary directory.
423
424        vips uses ``g_mkstemp()`` to make the temporary filename. They
425        generally look something like ``"vips-12-EJKJFGH.v"``.
426
427        Args:
428            format (str): The format for the temp file, for example
429                ``"%s.v"`` for a vips format file. The ``%s`` is
430                substituted by the file path.
431
432        Returns:
433            A new :class:`Image`.
434
435        Raises:
436            :class:`.Error`
437
438        """
439
440        vi = vips_lib.vips_image_new_temp_file(_to_bytes(format))
441        if vi == ffi.NULL:
442            raise Error('unable to make temp file')
443
444        return pyvips.Image(vi)
445
446    def new_from_image(self, value):
447        """Make a new image from an existing one.
448
449        A new image is created which has the same size, format, interpretation
450        and resolution as ``self``, but with every pixel set to ``value``.
451
452        Args:
453            value (float, list[float]): The value for the pixels. Use a
454                single number to make a one-band image; use an array constant
455                to make a many-band image.
456
457        Returns:
458            A new :class:`Image`.
459
460        Raises:
461            :class:`.Error`
462
463        """
464
465        pixel = (Image.black(1, 1) + value).cast(self.format)
466        image = pixel.embed(0, 0, self.width, self.height,
467                            extend='copy')
468        image = image.copy(interpretation=self.interpretation,
469                           xres=self.xres,
470                           yres=self.yres,
471                           xoffset=self.xoffset,
472                           yoffset=self.yoffset)
473
474        return image
475
476    def copy_memory(self):
477        """Copy an image to memory.
478
479        A large area of memory is allocated, the image is rendered to that
480        memory area, and a new image is returned which wraps that large memory
481        area.
482
483        Returns:
484            A new :class:`Image`.
485
486        Raises:
487            :class:`.Error`
488
489        """
490        vi = vips_lib.vips_image_copy_memory(self.pointer)
491        if vi == ffi.NULL:
492            raise Error('unable to copy to memory')
493
494        return pyvips.Image(vi)
495
496    # writers
497
498    def write_to_file(self, vips_filename, **kwargs):
499        """Write an image to a file on disc.
500
501        This method can save images in any format supported by vips. The format
502        is selected from the filename suffix. The filename can include embedded
503        save options, see :func:`Image.new_from_file`.
504
505        For example::
506
507            image.write_to_file('fred.jpg[Q=95]')
508
509        You can also supply options as keyword arguments, for example::
510
511            image.write_to_file('fred.jpg', Q=95)
512
513        The full set of options available depend upon the load operation that
514        will be executed. Try something like::
515
516            $ vips jpegsave
517
518        at the command-line to see a summary of the available options for the
519        JPEG saver.
520
521        Args:
522            vips_filename (str): The disc file to save the image to, with
523                optional appended arguments.
524
525        Other arguments depend upon the save operation.
526
527        Returns:
528            None
529
530        Raises:
531            :class:`.Error`
532
533        """
534        vips_filename = _to_bytes(vips_filename)
535        pointer = vips_lib.vips_filename_get_filename(vips_filename)
536        filename = _to_string_copy(pointer)
537
538        pointer = vips_lib.vips_filename_get_options(vips_filename)
539        options = _to_string_copy(pointer)
540
541        pointer = vips_lib.vips_foreign_find_save(vips_filename)
542        if pointer == ffi.NULL:
543            raise Error('unable to write to file {0}'.format(vips_filename))
544        name = _to_string(pointer)
545
546        return pyvips.Operation.call(name, self, filename,
547                                     string_options=options, **kwargs)
548
549    def write_to_buffer(self, format_string, **kwargs):
550        """Write an image to memory.
551
552        This method can save images in any format supported by vips. The format
553        is selected from the suffix in the format string. This can include
554        embedded save options, see :func:`Image.write_to_file`.
555
556        For example::
557
558            data = image.write_to_buffer('.jpg[Q=95]')
559
560        You can also supply options as keyword arguments, for example::
561
562            data = image.write_to_buffer('.jpg', Q=95)
563
564        The full set of options available depend upon the load operation that
565        will be executed. Try something like::
566
567            $ vips jpegsave_buffer
568
569        at the command-line to see a summary of the available options for the
570        JPEG saver.
571
572        Args:
573            format_string (str): The suffix, plus any string-form arguments.
574
575        Other arguments depend upon the save operation.
576
577        Returns:
578            A byte string.
579
580        Raises:
581            :class:`.Error`
582
583        """
584        format_string = _to_bytes(format_string)
585
586        filename = vips_lib.vips_filename_get_filename(format_string)
587
588        pointer = vips_lib.vips_filename_get_options(format_string)
589        options = _to_string_copy(pointer)
590
591        pointer = ffi.NULL
592        if at_least_libvips(8, 9):
593            vips_lib.vips_error_freeze()
594            pointer = vips_lib.vips_foreign_find_save_target(filename)
595            vips_lib.vips_error_thaw()
596
597        if pointer != ffi.NULL:
598            name = _to_string(pointer)
599            target = pyvips.Target.new_to_memory()
600            pyvips.Operation.call(name, self, target,
601                                  string_options=options, **kwargs)
602            buffer = target.get("blob")
603        else:
604            pointer = vips_lib.vips_foreign_find_save_buffer(filename)
605            if pointer == ffi.NULL:
606                raise Error('unable to write to buffer')
607
608            name = _to_string(pointer)
609            buffer = pyvips.Operation.call(name, self,
610                                           string_options=options, **kwargs)
611
612        return buffer
613
614    def write_to_target(self, target, format_string, **kwargs):
615        """Write an image to a target.
616
617        This method will write the image to the target in the format
618        specified in the suffix in the format string. This can include
619        embedded save options, see :func:`Image.write_to_file`.
620
621        For example::
622
623            image.write_to_target(target, '.jpg[Q=95]')
624
625        You can also supply options as keyword arguments, for example::
626
627            image.write_to_target(target, '.jpg', Q=95)
628
629        The full set of options available depend upon the save operation that
630        will be executed. Try something like::
631
632            $ vips jpegsave_target
633
634        at the command-line to see a summary of the available options for the
635        JPEG saver.
636
637        Args:
638            target (Target): The target to write the image to
639            format_string (str): The suffix, plus any string-form arguments.
640
641        Other arguments depend upon the save operation.
642
643        Returns:
644            None
645
646        Raises:
647            :class:`.Error`
648
649        """
650        format_string = _to_bytes(format_string)
651
652        pointer = vips_lib.vips_filename_get_options(format_string)
653        options = _to_string_copy(pointer)
654
655        pointer = vips_lib.vips_foreign_find_save_target(format_string)
656        if pointer == ffi.NULL:
657            raise Error('unable to write to target')
658        name = _to_string(pointer)
659
660        return pyvips.Operation.call(name, self, target,
661                                     string_options=options, **kwargs)
662
663    def write_to_memory(self):
664        """Write the image to a large memory array.
665
666        A large area of memory is allocated, the image is rendered to that
667        memory array, and the array is returned as a buffer.
668
669        For example, if you have a 2x2 uchar image containing the bytes 1, 2,
670        3, 4, read left-to-right, top-to-bottom, then::
671
672            buf = image.write_to_memory()
673
674        will return a four byte buffer containing the values 1, 2, 3, 4.
675
676        Returns:
677            buffer
678
679        Raises:
680            :class:`.Error`
681
682        """
683
684        psize = ffi.new('size_t *')
685        pointer = vips_lib.vips_image_write_to_memory(self.pointer, psize)
686        if pointer == ffi.NULL:
687            raise Error('unable to write to memory')
688        pointer = ffi.gc(pointer, glib_lib.g_free)
689
690        return ffi.buffer(pointer, psize[0])
691
692    def write(self, other):
693        """Write an image to another image.
694
695        This function writes ``self`` to another image. Use something like
696        :func:`Image.new_temp_file` to make an image that can be written to.
697
698        Args:
699            other (Image): The :class:`Image` to write to,
700
701        Returns:
702            None
703
704        Raises:
705            :class:`.Error`
706
707        """
708        result = vips_lib.vips_image_write(self.pointer, other.pointer)
709        if result != 0:
710            raise Error('unable to write to image')
711
712    def set_progress(self, progress):
713        """Enable progress reporting on an image.
714
715        When progress reporting is enabled, evaluation of the most downstream
716        image from this image will report progress using the ::preeval, ::eval,
717        and ::posteval signals.
718
719        """
720        vips_lib.vips_image_set_progress(self.pointer, progress)
721
722    def set_kill(self, kill):
723        """Kill processing of an image.
724
725        Use this to kill evaluation of an image. You can call it from one of
726        the progress signals, for example. See :meth:`.set_progress`.
727
728        """
729        vips_lib.vips_image_set_kill(self.pointer, kill)
730
731    # get/set metadata
732
733    def get_typeof(self, name):
734        """Get the GType of an item of metadata.
735
736        Fetch the GType of a piece of metadata, or 0 if the named item does not
737        exist. See :class:`GValue`.
738
739        Args:
740            name (str): The name of the piece of metadata to get the type of.
741
742        Returns:
743            The ``GType``, or 0.
744
745        Raises:
746            None
747
748        """
749
750        # on libvips before 8.5, property types must be fetched separately,
751        # since built-in enums were reported as ints
752        if not at_least_libvips(8, 5):
753            gtype = super(Image, self).get_typeof(name)
754            if gtype != 0:
755                return gtype
756
757        return vips_lib.vips_image_get_typeof(self.pointer, _to_bytes(name))
758
759    def get(self, name):
760        """Get an item of metadata.
761
762        Fetches an item of metadata as a Python value. For example::
763
764            orientation = image.get('orientation')
765
766        would fetch the image orientation.
767
768        Args:
769            name (str): The name of the piece of metadata to get.
770
771        Returns:
772            The metadata item as a Python value.
773
774        Raises:
775            :class:`.Error`
776
777        """
778
779        # with old libvips, we must fetch properties (as opposed to
780        # metadata) via VipsObject
781        if not at_least_libvips(8, 5):
782            gtype = super(Image, self).get_typeof(name)
783            if gtype != 0:
784                return super(Image, self).get(name)
785
786        gv = GValue()
787        result = vips_lib.vips_image_get(self.pointer, _to_bytes(name),
788                                         gv.pointer)
789        if result != 0:
790            raise Error('unable to get {0}'.format(name))
791
792        return gv.get()
793
794    def get_fields(self):
795        """Get a list of all the metadata fields on an image.
796
797        Returns:
798            [string]
799
800        """
801
802        names = []
803
804        if at_least_libvips(8, 5):
805            array = vips_lib.vips_image_get_fields(self.pointer)
806            i = 0
807            while array[i] != ffi.NULL:
808                name = _to_string(array[i])
809                names.append(name)
810                glib_lib.g_free(array[i])
811                i += 1
812            glib_lib.g_free(array)
813
814        return names
815
816    def set_type(self, gtype, name, value):
817        """Set the type and value of an item of metadata.
818
819        Sets the type and value of an item of metadata. Any old item of the
820        same name is removed. See :class:`GValue` for types.
821
822        Args:
823            gtype (int): The GType of the metadata item to create.
824            name (str): The name of the piece of metadata to create.
825            value (mixed): The value to set as a Python value. It is
826                converted to the ``gtype``, if possible.
827
828        Returns:
829            None
830
831        Raises:
832            None
833
834        """
835
836        gv = GValue()
837        gv.set_type(gtype)
838        gv.set(value)
839        vips_lib.vips_image_set(self.pointer, _to_bytes(name), gv.pointer)
840
841    def set(self, name, value):
842        """Set the value of an item of metadata.
843
844        Sets the value of an item of metadata. The metadata item must already
845        exist.
846
847        Args:
848            name (str): The name of the piece of metadata to set the value of.
849            value (mixed): The value to set as a Python value. It is
850                converted to the type of the metadata item, if possible.
851
852        Returns:
853            None
854
855        Raises:
856            :class:`.Error`
857
858        """
859        gtype = self.get_typeof(name)
860        if gtype == 0:
861            raise Error('metadata item {0} does not exist - '
862                        'use set_type() to create and set'.format(name))
863        self.set_type(gtype, name, value)
864
865    def remove(self, name):
866        """Remove an item of metadata.
867
868        The named metadata item is removed.
869
870        Args:
871            name (str): The name of the piece of metadata to remove.
872
873        Returns:
874            None
875
876        Raises:
877            None
878
879        """
880
881        return vips_lib.vips_image_remove(self.pointer, _to_bytes(name)) != 0
882
883    def __repr__(self):
884        return ('<pyvips.Image {0}x{1} {2}, {3} bands, {4}>'.
885                format(self.width, self.height, self.format, self.bands,
886                       self.interpretation))
887
888    def __getattr__(self, name):
889        """Divert unknown names to libvips.
890
891        Unknown attributes are first looked up in the image properties as
892        accessors, for example::
893
894            width = image.width
895
896        and then in the libvips operation table, where they become method
897        calls, for example::
898
899            new_image = image.invert()
900
901        Use :func:`get` to fetch image metadata.
902
903        A ``__getattr__`` on the metatype lets you call static members in the
904        same way.
905
906        Args:
907            name (str): The name of the piece of metadata to get.
908
909        Returns:
910            Mixed.
911
912        Raises:
913            :class:`.Error`
914
915        """
916
917        # logger.debug('Image.__getattr__ %s', name)
918
919        # scale and offset have default values
920        if name == 'scale':
921            if self.get_typeof('scale') != 0:
922                return self.get('scale')
923            else:
924                return 1.0
925
926        if name == 'offset':
927            if self.get_typeof('offset') != 0:
928                return self.get('offset')
929            else:
930                return 0.0
931
932        # look up in props first (but not metadata)
933        if super(Image, self).get_typeof(name) != 0:
934            return super(Image, self).get(name)
935
936        @_add_doc(name)
937        def call_function(*args, **kwargs):
938            return pyvips.Operation.call(name, self, *args, **kwargs)
939
940        return call_function
941
942    # compatibility methods
943
944    @_deprecated('use Image.get() instead')
945    def get_value(self, name):
946        return self.get(name)
947
948    @_deprecated('use Image.set() instead')
949    def set_value(self, name, value):
950        self.set(name, value)
951
952    @_deprecated('use Image.scale instead')
953    def get_scale(self):
954        return self.scale
955
956    @_deprecated('use Image.offset instead')
957    def get_offset(self):
958        return self.offset
959
960    # support with in the most trivial way
961
962    def __enter__(self):
963        return self
964
965    def __exit__(self, type, value, traceback):
966        pass
967
968    def __getitem__(self, arg):
969        """Overload []
970
971        Use [] to pull out band elements from an image. You can use all the
972        usual slicing syntax, for example::
973
974            green = rgb_image[1]
975
976        Will make a new one-band image from band 1 (the middle band). You can
977        also write::
978
979            last_two = rgb_image[1:]
980            last_band = rgb_image[-1]
981            middle_few = multiband[1:-2]
982
983        """
984
985        if isinstance(arg, slice):
986            i = 0
987            if arg.start is not None:
988                i = arg.start
989
990            n = self.bands - i
991            if arg.stop is not None:
992                if arg.stop < 0:
993                    n = self.bands + arg.stop - i
994                else:
995                    n = arg.stop - i
996        elif isinstance(arg, int):
997            i = arg
998            n = 1
999        else:
1000            raise TypeError
1001
1002        if i < 0:
1003            i = self.bands + i
1004
1005        if i < 0 or i >= self.bands:
1006            raise IndexError
1007
1008        return self.extract_band(i, n=n)
1009
1010    # overload () to mean fetch pixel
1011    def __call__(self, x, y):
1012        """Fetch a pixel value.
1013
1014        Args:
1015            x (int): The x coordinate to fetch.
1016            y (int): The y coordinate to fetch.
1017
1018        Returns:
1019            Pixel as an array of floating point numbers.
1020
1021        Raises:
1022            :class:`.Error`
1023
1024        """
1025
1026        return self.getpoint(x, y)
1027
1028    # operator overloads
1029
1030    def __add__(self, other):
1031        if isinstance(other, pyvips.Image):
1032            return self.add(other)
1033        else:
1034            return self.linear(1, other)
1035
1036    def __radd__(self, other):
1037        return self.__add__(other)
1038
1039    def __sub__(self, other):
1040        if isinstance(other, pyvips.Image):
1041            return self.subtract(other)
1042        else:
1043            return self.linear(1, _smap(lambda x: -1 * x, other))
1044
1045    def __rsub__(self, other):
1046        return self.linear(-1, other)
1047
1048    def __mul__(self, other):
1049        if isinstance(other, Image):
1050            return self.multiply(other)
1051        else:
1052            return self.linear(other, 0)
1053
1054    def __rmul__(self, other):
1055        return self.__mul__(other)
1056
1057    # a / const has always been a float in vips, so div and truediv are the
1058    # same
1059    def __div__(self, other):
1060        if isinstance(other, pyvips.Image):
1061            return self.divide(other)
1062        else:
1063            return self.linear(_smap(lambda x: 1.0 / x, other), 0)
1064
1065    def __rdiv__(self, other):
1066        return (self ** -1) * other
1067
1068    def __truediv__(self, other):
1069        return self.__div__(other)
1070
1071    def __rtruediv__(self, other):
1072        return self.__rdiv__(other)
1073
1074    def __floordiv__(self, other):
1075        if isinstance(other, pyvips.Image):
1076            return self.divide(other).floor()
1077        else:
1078            return self.linear(_smap(lambda x: 1.0 / x, other), 0).floor()
1079
1080    def __rfloordiv__(self, other):
1081        return ((self ** -1) * other).floor()
1082
1083    def __mod__(self, other):
1084        if isinstance(other, pyvips.Image):
1085            return self.remainder(other)
1086        else:
1087            return self.remainder_const(other)
1088
1089    def __pow__(self, other):
1090        return _call_enum(self, other, 'math2', 'pow')
1091
1092    def __rpow__(self, other):
1093        return _call_enum(self, other, 'math2', 'wop')
1094
1095    def __abs__(self):
1096        return self.abs()
1097
1098    def __lshift__(self, other):
1099        return _call_enum(self, other, 'boolean', 'lshift')
1100
1101    def __rshift__(self, other):
1102        return _call_enum(self, other, 'boolean', 'rshift')
1103
1104    def __and__(self, other):
1105        return _call_enum(self, other, 'boolean', 'and')
1106
1107    def __rand__(self, other):
1108        return self.__and__(other)
1109
1110    def __or__(self, other):
1111        return _call_enum(self, other, 'boolean', 'or')
1112
1113    def __ror__(self, other):
1114        return self.__or__(other)
1115
1116    def __xor__(self, other):
1117        return _call_enum(self, other, 'boolean', 'eor')
1118
1119    def __rxor__(self, other):
1120        return self.__xor__(other)
1121
1122    def __neg__(self):
1123        return -1 * self
1124
1125    def __pos__(self):
1126        return self
1127
1128    def __invert__(self):
1129        return self ^ -1
1130
1131    def __gt__(self, other):
1132        return _call_enum(self, other, 'relational', 'more')
1133
1134    def __ge__(self, other):
1135        return _call_enum(self, other, 'relational', 'moreeq')
1136
1137    def __lt__(self, other):
1138        return _call_enum(self, other, 'relational', 'less')
1139
1140    def __le__(self, other):
1141        return _call_enum(self, other, 'relational', 'lesseq')
1142
1143    def __eq__(self, other):
1144        # _eq version allows comparison to None
1145        if other is None:
1146            return False
1147
1148        return _call_enum(self, other, 'relational', 'equal')
1149
1150    def __ne__(self, other):
1151        # _eq version allows comparison to None
1152        if other is None:
1153            return True
1154
1155        return _call_enum(self, other, 'relational', 'noteq')
1156
1157    def floor(self):
1158        """Return the largest integral value not greater than the argument."""
1159        return self.round('floor')
1160
1161    def ceil(self):
1162        """Return the smallest integral value not less than the argument."""
1163        return self.round('ceil')
1164
1165    def rint(self):
1166        """Return the nearest integral value."""
1167        return self.round('rint')
1168
1169    def bandand(self):
1170        """AND image bands together."""
1171        return self.bandbool('and')
1172
1173    def bandor(self):
1174        """OR image bands together."""
1175        return self.bandbool('or')
1176
1177    def bandeor(self):
1178        """EOR image bands together."""
1179        return self.bandbool('eor')
1180
1181    def bandsplit(self):
1182        """Split an n-band image into n separate images."""
1183        return [x for x in self]
1184
1185    def bandjoin(self, other):
1186        """Append a set of images or constants bandwise."""
1187        if not isinstance(other, list):
1188            other = [other]
1189
1190        # if [other] is all numbers, we can use bandjoin_const
1191        non_number = next((x for x in other
1192                           if not isinstance(x, numbers.Number)),
1193                          None)
1194
1195        if non_number is None:
1196            return self.bandjoin_const(other)
1197        else:
1198            return pyvips.Operation.call('bandjoin', [self] + other)
1199
1200    def atan2(self, other):
1201        return _call_enum(self, other, 'math2', 'atan2')
1202
1203    def get_n_pages(self):
1204        """Get the number of pages in an image file, or 1.
1205
1206        This is the number of pages in the file the image was loaded from, not
1207        the number of pages in the image.
1208
1209        To get the number of pages in an image, divide the image height by
1210        the page height.
1211        """
1212        if at_least_libvips(8, 8):
1213            return vips_lib.vips_image_get_n_pages(self.pointer)
1214        else:
1215            return self.get("n-pages") \
1216                if self.get_typeof("n-pages") != 0 else 1
1217
1218    def get_page_height(self):
1219        """Get the page height in a many-page image, or height.
1220        """
1221        if at_least_libvips(8, 8):
1222            return vips_lib.vips_image_get_page_height(self.pointer)
1223        else:
1224            if self.get_typeof("page-height") != 0:
1225                page_height = self.get("page-height")
1226            else:
1227                page_height = self.height
1228
1229            if page_height > 0 and \
1230                page_height <= self.height and \
1231                    self.height % page_height == 0:
1232                return page_height
1233            else:
1234                return self.height
1235
1236    def pagesplit(self):
1237        """Split an N-page image into a list of N separate images.
1238        """
1239        page_height = self.get_page_height()
1240        return [self.crop(0, y, self.width, page_height)
1241                for y in range(0, self.height, page_height)]
1242
1243    def pagejoin(self, other):
1244        """Join a set of pages vertically to make a multipage image.
1245
1246        Also sets the page-height property on the result.
1247        """
1248        if not isinstance(other, list):
1249            other = [other]
1250
1251        n_pages = 1 + len(other)
1252
1253        image = Image.arrayjoin([self] + other, across=1)
1254        image = image.copy()
1255        image.set_type(GValue.gint_type, 'page-height', image.height / n_pages)
1256
1257        return image
1258
1259    def composite(self, other, mode, **kwargs):
1260        """Composite a set of images with a set of modes."""
1261        if not isinstance(other, list):
1262            other = [other]
1263        if not isinstance(mode, list):
1264            mode = [mode]
1265
1266        # modes are VipsBlendMode enums, but we have to pass as array of int --
1267        # we need to map str->int by hand
1268        mode = [GValue.to_enum(GValue.blend_mode_type, x) for x in mode]
1269
1270        return pyvips.Operation.call('composite', [self] + other, mode,
1271                                     **kwargs)
1272
1273    def bandrank(self, other, **kwargs):
1274        """Band-wise rank filter a set of images."""
1275        if not isinstance(other, list):
1276            other = [other]
1277
1278        return pyvips.Operation.call('bandrank', [self] + other, **kwargs)
1279
1280    def maxpos(self):
1281        """Return the coordinates of the image maximum."""
1282        v, opts = self.max(x=True, y=True)
1283        x = opts['x']
1284        y = opts['y']
1285        return v, x, y
1286
1287    def minpos(self):
1288        """Return the coordinates of the image minimum."""
1289        v, opts = self.min(x=True, y=True)
1290        x = opts['x']
1291        y = opts['y']
1292        return v, x, y
1293
1294    def real(self):
1295        """Return the real part of a complex image."""
1296        return self.complexget('real')
1297
1298    def imag(self):
1299        """Return the imaginary part of a complex image."""
1300        return self.complexget('imag')
1301
1302    def polar(self):
1303        """Return an image converted to polar coordinates."""
1304        return _run_cmplx(lambda x: x.complex('polar'), self)
1305
1306    def rect(self):
1307        """Return an image converted to rectangular coordinates."""
1308        return _run_cmplx(lambda x: x.complex('rect'), self)
1309
1310    def conj(self):
1311        """Return the complex conjugate of an image."""
1312        return self.complex('conj')
1313
1314    def sin(self):
1315        """Return the sine of an image in degrees."""
1316        return self.math('sin')
1317
1318    def cos(self):
1319        """Return the cosine of an image in degrees."""
1320        return self.math('cos')
1321
1322    def tan(self):
1323        """Return the tangent of an image in degrees."""
1324        return self.math('tan')
1325
1326    def asin(self):
1327        """Return the inverse sine of an image in degrees."""
1328        return self.math('asin')
1329
1330    def acos(self):
1331        """Return the inverse cosine of an image in degrees."""
1332        return self.math('acos')
1333
1334    def atan(self):
1335        """Return the inverse tangent of an image in degrees."""
1336        return self.math('atan')
1337
1338    def sinh(self):
1339        """Return the hyperbolic sine of an image in radians."""
1340        return self.math('sinh')
1341
1342    def cosh(self):
1343        """Return the hyperbolic cosine of an image in radians."""
1344        return self.math('cosh')
1345
1346    def tanh(self):
1347        """Return the hyperbolic tangent of an image in radians."""
1348        return self.math('tanh')
1349
1350    def asinh(self):
1351        """Return the inverse hyperbolic sine of an image in radians."""
1352        return self.math('asinh')
1353
1354    def acosh(self):
1355        """Return the inverse hyperbolic cosine of an image in radians."""
1356        return self.math('acosh')
1357
1358    def atanh(self):
1359        """Return the inverse hyperbolic tangent of an image in radians."""
1360        return self.math('atanh')
1361
1362    def log(self):
1363        """Return the natural log of an image."""
1364        return self.math('log')
1365
1366    def log10(self):
1367        """Return the log base 10 of an image."""
1368        return self.math('log10')
1369
1370    def exp(self):
1371        """Return e ** pixel."""
1372        return self.math('exp')
1373
1374    def exp10(self):
1375        """Return 10 ** pixel."""
1376        return self.math('exp10')
1377
1378    def erode(self, mask):
1379        """Erode with a structuring element."""
1380        return self.morph(mask, 'erode')
1381
1382    def dilate(self, mask):
1383        """Dilate with a structuring element."""
1384        return self.morph(mask, 'dilate')
1385
1386    def median(self, size):
1387        """size x size median filter."""
1388        return self.rank(size, size, (size * size) / 2)
1389
1390    def fliphor(self):
1391        """Flip horizontally."""
1392        return self.flip('horizontal')
1393
1394    def flipver(self):
1395        """Flip vertically."""
1396        return self.flip('vertical')
1397
1398    def rot90(self):
1399        """Rotate 90 degrees clockwise."""
1400        return self.rot('d90')
1401
1402    def rot180(self):
1403        """Rotate 180 degrees."""
1404        return self.rot('d180')
1405
1406    def rot270(self):
1407        """Rotate 270 degrees clockwise."""
1408        return self.rot('d270')
1409
1410    def hasalpha(self):
1411        """True if the image has an alpha channel."""
1412        return vips_lib.vips_image_hasalpha(self.pointer)
1413
1414    def addalpha(self):
1415        """Add an alpha channel."""
1416        if self.interpretation == 'grey16' or self.interpretation == 'rgb16':
1417            max_alpha = 65535
1418        else:
1419            max_alpha = 255
1420        return self.bandjoin(max_alpha)
1421
1422    # we need different _imageize rules for this operator ... we need to
1423    # _imageize in1 and in2 to match each other first
1424    @_add_doc('ifthenelse')
1425    def ifthenelse(self, in1, in2, **kwargs):
1426        for match_image in [in1, in2, self]:
1427            if isinstance(match_image, pyvips.Image):
1428                break
1429
1430        if not isinstance(in1, pyvips.Image):
1431            in1 = Image._imageize(match_image, in1)
1432        if not isinstance(in2, pyvips.Image):
1433            in2 = Image._imageize(match_image, in2)
1434
1435        return pyvips.Operation.call('ifthenelse', self, in1, in2, **kwargs)
1436
1437    def scaleimage(self, **kwargs):
1438        """Scale an image to 0 - 255.
1439
1440        This is the libvips ``scale`` operation, renamed to avoid a clash with
1441        the ``scale`` for convolution masks.
1442
1443        Keyword args:
1444            exp (float): Exponent for log scale.
1445            log (bool): Switch to turn on log scaling.
1446
1447        Returns:
1448            A new :class:`Image`.
1449
1450        Raises:
1451            :class:`.Error`
1452
1453        """
1454
1455        return pyvips.Operation.call('scale', self, **kwargs)
1456
1457
1458__all__ = ['Image']
1459