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