diff --git a/ChangeLog b/ChangeLog
index c2261452..8536a03f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -10,6 +10,7 @@
- added test_foreign.py, plus more test images
- rewritten tiff writer is about 3 - 4x faster at making pyramids
- jpg, magick, png, tiff readers now use only 1 fd per input image
+- python: use [] to index and slice image bands
6/2/15 started 7.42.3
- bump version for back-compat ABI change
diff --git a/TODO b/TODO
index 7fdd515f..dbab1cf4 100644
--- a/TODO
+++ b/TODO
@@ -3,6 +3,14 @@
python people are not going to want to use the glib arg parser, for example
+- need to add [] overload to Ruby bindings
+
+- overload (x, y) to be getpoint()?
+
+
+
+
+
- support orientation tag in tiff images
diff --git a/cplusplus/include/vips/VImage8.h b/cplusplus/include/vips/VImage8.h
index 7489d232..323062cf 100644
--- a/cplusplus/include/vips/VImage8.h
+++ b/cplusplus/include/vips/VImage8.h
@@ -1263,6 +1263,12 @@ public:
return( a * -1 );
}
+ friend VImage operator[]( VImage a, int index )
+ throw( VError )
+ {
+ return( a.extract_band( index ) );
+ }
+
};
VIPS_NAMESPACE_END
diff --git a/doc/using-python.xml b/doc/using-python.xml
index 376a952d..620c1c70 100644
--- a/doc/using-python.xml
+++ b/doc/using-python.xml
@@ -347,6 +347,26 @@ help(image.add)
result_image = ((image * [1, 2, 3]).abs() < 128) | 4
+
+
+ The wrapper overloads []
to be band indexing. You can write:
+
+
+result_image = image[2]
+
+
+ to extract the third band of the image. It implements the usual
+ slicing and negative indexes, so you can write:
+
+
+result_image = image[1:]
+result_image = image[:3]
+result_image = image[-2:]
+result_image = [x.avg() for x in image]
+
+
+ and so on.
+
diff --git a/python/Vips.py b/python/Vips.py
index c6bf8fc5..5ee8dc90 100644
--- a/python/Vips.py
+++ b/python/Vips.py
@@ -757,6 +757,32 @@ class Image(Vips.Image):
else:
return self.relational_const(other, Vips.OperationRelational.NOTEQ)
+ def __getitem__(self, arg):
+ if isinstance(arg, slice):
+ i = 0
+ if arg.start != None:
+ i = arg.start
+
+ n = self.bands - i
+ if arg.stop != None:
+ if arg.stop < 0:
+ n = self.bands + arg.stop - i
+ else:
+ n = arg.stop - i
+ elif isinstance(arg, int):
+ i = arg
+ n = 1
+ else:
+ raise TypeError
+
+ if i < 0:
+ i = self.bands + i
+
+ if i < 0 or i >= self.bands:
+ raise IndexError
+
+ return self.extract_band(i, n = n)
+
# the cast operators int(), long() and float() must return numeric types,
# so we can't define them for images
@@ -813,7 +839,7 @@ class Image(Vips.Image):
def bandsplit(self):
"""Split an n-band image into n separate images."""
- return [self.extract_band(i) for i in range(0, self.bands)]
+ return [x for x in self]
def bandjoin(self, other):
"""Join a set of images bandwise."""
diff --git a/python/example/try17.py b/python/example/try17.py
new file mode 100755
index 00000000..bc5eaf8f
--- /dev/null
+++ b/python/example/try17.py
@@ -0,0 +1,18 @@
+#!/usr/bin/python3
+
+import sys
+
+import logging
+#logging.basicConfig(level = logging.DEBUG)
+
+from gi.repository import Vips
+
+#Vips.cache_set_trace(True)
+
+a = Vips.Image.new_from_file(sys.argv[1])
+
+a = a[1:]
+
+a.write_to_file(sys.argv[2])
+
+
diff --git a/test/test_conversion.py b/test/test_conversion.py
index 5518c4b7..df4e03ad 100755
--- a/test/test_conversion.py
+++ b/test/test_conversion.py
@@ -80,6 +80,8 @@ rot_angle_bonds = [Vips.Angle.D0,
# the other
def zip_expand(x, y):
if isinstance(x, list) and isinstance(y, list):
+ if len(x) != len(y):
+ raise Vips.Error("zip_expand list args not equal length")
return list(zip(x, y))
elif isinstance(x, list):
return [[i, y] for i in x]
@@ -138,7 +140,7 @@ class TestConversion(unittest.TestCase):
def setUp(self):
im = Vips.Image.mask_ideal(100, 100, 0.5, reject = True, optical = True)
self.colour = im * [1, 2, 3] + [2, 3, 4]
- self.mono = self.colour.extract_band(1)
+ self.mono = self.colour[1]
self.all_images = [self.mono, self.colour]
def test_band_and(self):
@@ -295,6 +297,31 @@ class TestConversion(unittest.TestCase):
pixel = sub.getpoint(30, 30)
self.assertAlmostEqualObjects(pixel, [3, 4])
+ def test_slice(self):
+ test = self.colour
+ bands = [x.avg() for x in test]
+
+ x = test[0].avg()
+ self.assertEqual(x, bands[0])
+
+ x = test[-1].avg()
+ self.assertAlmostEqualObjects(x, bands[2])
+
+ x = [i.avg() for i in test[1:3]]
+ self.assertAlmostEqualObjects(x, bands[1:3])
+
+ x = [i.avg() for i in test[1:-1]]
+ self.assertAlmostEqualObjects(x, bands[1:-1])
+
+ x = [i.avg() for i in test[:2]]
+ self.assertAlmostEqualObjects(x, bands[:2])
+
+ x = [i.avg() for i in test[1:]]
+ self.assertAlmostEqualObjects(x, bands[1:])
+
+ x = [i.avg() for i in test[-1]]
+ self.assertAlmostEqualObjects(x, bands[-1])
+
def test_crop(self):
for fmt in all_formats:
test = self.colour.cast(fmt)