python does auto complx/uncomplx

this is a bit ugly :-(
This commit is contained in:
John Cupitt 2015-11-20 16:29:43 +00:00
parent a8b78371f8
commit 16c4eeabad
3 changed files with 43 additions and 58 deletions

22
TODO
View File

@ -1,29 +1,9 @@
- we need to be able to run .polar() on xyz images ... argh
- could special-case vips_complex() to work for multi-band int images as
well as complex
would need to output as multi-band float
what about other cases though? cast real to complex?
- could add new ops for polar/rect of real images with two bands
- could add a thing to Vips.py to do this
- could add full support for complex arithmetic ... linear would need an
extra arg for complex constants
- could abandon complex images and just use 2*bands instead, have complex
as a flag you set? or just rely on FOURIER
paste fixed up run_cmplx() into Vips.py
- easy to get a segv with Nicolas's interpolators, argh
just with float images?
try to_polar, set LBB, zoom in and scroll around a bit
try to_polar workspace, set LBB, zoom in and scroll around a bit

View File

@ -134,6 +134,40 @@ def arrayize(gtype, value):
return value
def run_cmplx(fn, image):
"""Run a complex function on a non-complex image.
The image needs to be complex, or have an even number of bands. The input
can be int, the output is always float or double.
"""
original_format = image.format
if not Vips.band_format_iscomplex(image.format):
if image.bands % 2 != 0:
raise "not an even number of bands"
if not Vips.band_format_isfloat(image.format):
image = image.cast(Vips.BandFormat.FLOAT)
if image.format == Vips.BandFormat.DOUBLE:
new_format = Vips.BandFormat.DPCOMPLEX
else:
new_format = Vips.BandFormat.COMPLEX
image = image.copy(format = new_format, bands = image.bands / 2)
image = fn(image)
if not Vips.band_format_iscomplex(original_format):
if image.format == Vips.BandFormat.DPCOMPLEX:
new_format = Vips.BandFormat.DOUBLE
else:
new_format = Vips.BandFormat.FLOAT
image = image.copy(format = new_format, bands = image.bands * 2)
return image
class Error(Exception):
"""An error from vips.
@ -911,11 +945,11 @@ class Image(Vips.Image):
def polar(self):
"""Return an image converted to polar coordinates."""
return self.complex(Vips.OperationComplex.POLAR)
return run_cmplx(lambda x: x.complex(Vips.OperationComplex.POLAR), self)
def rect(self):
"""Return an image converted to rectangular coordinates."""
return self.complex(Vips.OperationComplex.RECT)
return run_cmplx(lambda x: x.complex(Vips.OperationComplex.RECT), self)
def conj(self):
"""Return the complex conjugate of an image."""

View File

@ -11,37 +11,6 @@ from gi.repository import Vips
#Vips.cache_set_trace(True)
# Run a function expecting a complex image on an image with an even number of
# bands
def run_cmplx(fn, image):
original_format = image.format
if not Vips.band_format_iscomplex(image.format):
if image.bands % 2 != 0:
raise "not an even number of bands"
if not Vips.band_format_isfloat(image.format):
image = image.cast(Vips.BandFormat.FLOAT)
if image.format == Vips.BandFormat.DOUBLE:
new_format = Vips.BandFormat.DPCOMPLEX
else:
new_format = Vips.BandFormat.COMPLEX
image = image.copy(format = new_format, bands = image.bands / 2)
image = fn(image)
if not Vips.band_format_iscomplex(original_format):
if image.format == Vips.BandFormat.DPCOMPLEX:
new_format = Vips.BandFormat.DOUBLE
else:
new_format = Vips.BandFormat.FLOAT
image = image.copy(format = new_format, bands = image.bands * 2)
return image
def to_polar(image):
"""Transform image coordinates to polar.
@ -55,8 +24,9 @@ def to_polar(image):
scale = min(image.width, image.height) / float(image.width)
xy *= 2.0 / scale
# to polar, scale vertical axis to 360 degrees
index = run_cmplx(lambda x: x.polar(), xy)
index = xy.polar()
# scale vertical axis to 360 degrees
index *= [1, image.height / 360.0]
return image.mapim(index)
@ -72,8 +42,9 @@ def to_rectangular(image):
xy = Vips.Image.xyz(image.width, image.height)
xy *= [1, 360.0 / image.height]
# to rect, scale to image rect
index = run_cmplx(lambda x: x.rect(), xy)
index = xy.rect()
# scale to image rect
scale = min(image.width, image.height) / float(image.width)
index *= scale / 2.0
index += [image.width / 2.0, image.height / 2.0]