rename python bandjoin as ibandjoin

oh argh class and instance methods are in the same namespace, so we have
to rename the instance one as ibandjoin

also, start adding a test for arrayjoin
This commit is contained in:
John Cupitt 2015-12-12 12:29:20 +00:00
parent 6e9834e623
commit 5916e25c31
7 changed files with 62 additions and 14 deletions

View File

@ -17,6 +17,7 @@
- dzsave removes tile metadata by default, thanks Benjamin - dzsave removes tile metadata by default, thanks Benjamin
- added vips_image_new_from_memory_copy() - added vips_image_new_from_memory_copy()
- added vips_arrayjoin() - added vips_arrayjoin()
- Python x.bandjoin(y) is now x.ibandjoin(y), sorry
7/5/15 started 8.1.1 7/5/15 started 8.1.1
- oop, vips-8.0 wrapper script should be vips-8.1, thanks Danilo - oop, vips-8.0 wrapper script should be vips-8.1, thanks Danilo

7
TODO
View File

@ -1,3 +1,10 @@
- add tests for vips_arrayjoin()
and valgrind it too
could crop before we pad, perhaps? we could nest two embeds, that might be
simpler
- get some brightly coloured spots with nohalo / vsqbs on wobble.ws ... very - get some brightly coloured spots with nohalo / vsqbs on wobble.ws ... very
odd, the interpolation shouldn't change between bands odd, the interpolation shouldn't change between bands

View File

@ -318,6 +318,11 @@
<entry>join a pair of images</entry> <entry>join a pair of images</entry>
<entry>vips_join()</entry> <entry>vips_join()</entry>
</row> </row>
<row>
<entry>arrayjoin</entry>
<entry>join an array of images</entry>
<entry>vips_arrayjoin()</entry>
</row>
<row> <row>
<entry>extract_area</entry> <entry>extract_area</entry>
<entry>extract an area from an image</entry> <entry>extract an area from an image</entry>
@ -335,7 +340,7 @@
</row> </row>
<row> <row>
<entry>bandjoin_const</entry> <entry>bandjoin_const</entry>
<entry>appendd a set of constants to an image</entry> <entry>append a constant band to an image</entry>
<entry>vips_bandjoin_const(), vips_bandjoin_const1()</entry> <entry>vips_bandjoin_const(), vips_bandjoin_const1()</entry>
</row> </row>
<row> <row>
@ -777,9 +782,9 @@
<entry>vips_shrink()</entry> <entry>vips_shrink()</entry>
</row> </row>
<row> <row>
<entry>quadratic</entry> <entry>mapim</entry>
<entry>resample an image with a quadratic transform</entry> <entry>resample an image with an arbitrary warp</entry>
<entry>vips_quadratic()</entry> <entry>vips_mapim()</entry>
</row> </row>
<row> <row>
<entry>affine</entry> <entry>affine</entry>

View File

@ -461,21 +461,41 @@ result_image = condition_image.ifthenelse([0, 255, 0], [255, 0, 0])
two or more images up bandwise. You can write: two or more images up bandwise. You can write:
<programlisting language="Python"> <programlisting language="Python">
rgba = rgb.bandjoin(255) rgba = rgb.ibandjoin(255)
</programlisting> </programlisting>
to add a constant 255 band to an image, perhaps to add an alpha to add a constant 255 band to an image, perhaps to add an alpha
channel. Of course you can also write: channel. Of course you can also write:
<programlisting language="Python"> <programlisting language="Python">
result_image = image1.bandjoin(image2) result_image = image1.ibandjoin(image2)
result_image = image1.bandjoin([image2, image3]) result_image = image1.ibandjoin([image2, image3])
result_image = Vips.Image.bandjoin([image1, image2, image3]) result_image = Vips.Image.bandjoin([image1, image2, image3])
result_image = image1.bandjoin([image2, 255]) result_image = image1.ibandjoin([image2, 255])
</programlisting> </programlisting>
and so on. and so on.
</para> </para>
<para>
There's one annoying wrinkle in <code>.bandjoin()</code>. The vips
operation <code>vips_bandjoin()</code> takes an array of images to join,
so you can't use it as an instance member, it appears in the API as
<programlisting language="Python">
result_image = Vips.Image.bandjoin([image1, image2, image3])
</programlisting>
For convenience, the wrapper has an extra instance function called
<code>.ibandjoin()</code> which puts the <code>self</code> at the head
of the image array. This means the previous line is the same as:
<programlisting language="Python">
result_image = image1.ibandjoin([image2, image3])
</programlisting>
</para>
</refsect3> </refsect3>
<refsect3 id="python-exceptions"> <refsect3 id="python-exceptions">

View File

@ -906,7 +906,9 @@ class Image(Vips.Image):
"""Split an n-band image into n separate images.""" """Split an n-band image into n separate images."""
return [x for x in self] return [x for x in self]
def bandjoin(self, other): # bandjoin as an instance method ... it needs a different name,
# unfortunately
def ibandjoin(self, other):
"""Append a set of images or constants bandwise.""" """Append a set of images or constants bandwise."""
if not isinstance(other, list): if not isinstance(other, list):
other = [other] other = [other]

View File

@ -173,7 +173,7 @@ class TestConversion(unittest.TestCase):
def test_bandjoin(self): def test_bandjoin(self):
def bandjoin(x, y): def bandjoin(x, y):
if isinstance(x, Vips.Image) and isinstance(y, Vips.Image): if isinstance(x, Vips.Image) and isinstance(y, Vips.Image):
return x.bandjoin(y) return x.ibandjoin(y)
else: else:
return x + y return x + y
@ -382,7 +382,7 @@ class TestConversion(unittest.TestCase):
mx = 255 mx = 255
alpha = mx / 2.0 alpha = mx / 2.0
nalpha = mx - alpha nalpha = mx - alpha
test = self.colour.bandjoin(alpha).cast(fmt) test = self.colour.ibandjoin(alpha).cast(fmt)
pixel = test(30, 30) pixel = test(30, 30)
predict = [int(x) * alpha / mx for x in pixel[:-1]] predict = [int(x) * alpha / mx for x in pixel[:-1]]
@ -413,7 +413,7 @@ class TestConversion(unittest.TestCase):
mx = 255 mx = 255
alpha = mx / 2.0 alpha = mx / 2.0
nalpha = mx - alpha nalpha = mx - alpha
test = self.colour.bandjoin(alpha).cast(fmt) test = self.colour.ibandjoin(alpha).cast(fmt)
pixel = test(30, 30) pixel = test(30, 30)
predict = [int(x) * alpha / mx for x in pixel[:-1]] + [alpha] predict = [int(x) * alpha / mx for x in pixel[:-1]] + [alpha]
@ -433,7 +433,7 @@ class TestConversion(unittest.TestCase):
mx = 255 mx = 255
alpha = mx / 2.0 alpha = mx / 2.0
nalpha = mx - alpha nalpha = mx - alpha
test = self.colour.bandjoin(alpha).cast(fmt) test = self.colour.ibandjoin(alpha).cast(fmt)
pixel = test(30, 30) pixel = test(30, 30)
predict = [int(x) / (alpha / mx) for x in pixel[:-1]] + [alpha] predict = [int(x) / (alpha / mx) for x in pixel[:-1]] + [alpha]
@ -627,6 +627,19 @@ class TestConversion(unittest.TestCase):
a = r(r.width - 5, 5) a = r(r.width - 5, 5)
self.assertAlmostEqualObjects(a, [100, 100, 100]) self.assertAlmostEqualObjects(a, [100, 100, 100])
def test_arrayjoin(self):
max_width = 0
max_height = 0
for image in self.all_images:
if image.width > max_width:
max_width = image.width
if image.height > max_height:
max_height = image.height
im = Vips.Image.arrayjoin(self.all_images)
self.assertEqual(im.width, max_width * len(self.all_images))
self.assertEqual(im.height, max_height)
def test_msb(self): def test_msb(self):
for fmt in unsigned_formats: for fmt in unsigned_formats:
mx = max_value[fmt] mx = max_value[fmt]

View File

@ -48,7 +48,7 @@ class TestForeign(unittest.TestCase):
self.colour = Vips.Image.jpegload(self.jpeg_file) self.colour = Vips.Image.jpegload(self.jpeg_file)
self.mono = self.colour.extract_band(1) self.mono = self.colour.extract_band(1)
self.rad = self.colour.float2rad() self.rad = self.colour.float2rad()
self.cmyk = self.colour.bandjoin(self.mono) self.cmyk = self.colour.ibandjoin(self.mono)
self.cmyk = self.cmyk.copy(interpretation = Vips.Interpretation.CMYK) self.cmyk = self.cmyk.copy(interpretation = Vips.Interpretation.CMYK)
im = Vips.Image.new_from_file(self.gif_file) im = Vips.Image.new_from_file(self.gif_file)