simplify makeARGB: remove float support (this was never functional anyway)
remove rescale->lut optimization; this should be done in ImageItem instead.
This commit is contained in:
parent
99aa4cfdd3
commit
e2f43ce4be
@ -774,12 +774,11 @@ def solveBilinearTransform(points1, points2):
|
|||||||
|
|
||||||
return matrix
|
return matrix
|
||||||
|
|
||||||
def rescaleData(data, scale, offset, dtype=None):
|
def rescaleData(data, scale, offset, dtype=None, clip=None):
|
||||||
"""Return data rescaled and optionally cast to a new dtype::
|
"""Return data rescaled and optionally cast to a new dtype::
|
||||||
|
|
||||||
data => (data-offset) * scale
|
data => (data-offset) * scale
|
||||||
|
|
||||||
Uses scipy.weave (if available) to improve performance.
|
|
||||||
"""
|
"""
|
||||||
if dtype is None:
|
if dtype is None:
|
||||||
dtype = data.dtype
|
dtype = data.dtype
|
||||||
@ -831,7 +830,14 @@ def rescaleData(data, scale, offset, dtype=None):
|
|||||||
# Clip before converting dtype to avoid overflow
|
# Clip before converting dtype to avoid overflow
|
||||||
if dtype.kind in 'ui':
|
if dtype.kind in 'ui':
|
||||||
lim = np.iinfo(dtype)
|
lim = np.iinfo(dtype)
|
||||||
d2 = np.clip(d2, lim.min, lim.max)
|
if clip is None:
|
||||||
|
# don't let rescale cause integer overflow
|
||||||
|
d2 = np.clip(d2, lim.min, lim.max)
|
||||||
|
else:
|
||||||
|
d2 = np.clip(d2, max(clip[0], lim.min), min(clip[1], lim.max))
|
||||||
|
else:
|
||||||
|
if clip is not None:
|
||||||
|
d2 = np.clip(d2, *clip)
|
||||||
data = d2.astype(dtype)
|
data = d2.astype(dtype)
|
||||||
return data
|
return data
|
||||||
|
|
||||||
@ -853,15 +859,18 @@ def makeRGBA(*args, **kwds):
|
|||||||
kwds['useRGBA'] = True
|
kwds['useRGBA'] = True
|
||||||
return makeARGB(*args, **kwds)
|
return makeARGB(*args, **kwds)
|
||||||
|
|
||||||
|
|
||||||
def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
|
def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
|
||||||
"""
|
"""
|
||||||
Convert an array of values into an ARGB array suitable for building QImages, OpenGL textures, etc.
|
Convert an array of values into an ARGB array suitable for building QImages,
|
||||||
|
OpenGL textures, etc.
|
||||||
|
|
||||||
Returns the ARGB array (values 0-255) and a boolean indicating whether there is alpha channel data.
|
Returns the ARGB array (unsigned byte) and a boolean indicating whether
|
||||||
This is a two stage process:
|
there is alpha channel data. This is a two stage process:
|
||||||
|
|
||||||
1) Rescale the data based on the values in the *levels* argument (min, max).
|
1) Rescale the data based on the values in the *levels* argument (min, max).
|
||||||
2) Determine the final output by passing the rescaled values through a lookup table.
|
2) Determine the final output by passing the rescaled values through a
|
||||||
|
lookup table.
|
||||||
|
|
||||||
Both stages are optional.
|
Both stages are optional.
|
||||||
|
|
||||||
@ -881,18 +890,13 @@ def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
|
|||||||
scale The maximum value to which data will be rescaled before being passed through the
|
scale The maximum value to which data will be rescaled before being passed through the
|
||||||
lookup table (or returned if there is no lookup table). By default this will
|
lookup table (or returned if there is no lookup table). By default this will
|
||||||
be set to the length of the lookup table, or 255 if no lookup table is provided.
|
be set to the length of the lookup table, or 255 if no lookup table is provided.
|
||||||
For OpenGL color specifications (as in GLColor4f) use scale=1.0.
|
|
||||||
lut Optional lookup table (array with dtype=ubyte).
|
lut Optional lookup table (array with dtype=ubyte).
|
||||||
Values in data will be converted to color by indexing directly from lut.
|
Values in data will be converted to color by indexing directly from lut.
|
||||||
The output data shape will be input.shape + lut.shape[1:].
|
The output data shape will be input.shape + lut.shape[1:].
|
||||||
|
|
||||||
Note: the output of makeARGB will have the same dtype as the lookup table, so
|
|
||||||
for conversion to QImage, the dtype must be ubyte.
|
|
||||||
|
|
||||||
Lookup tables can be built using ColorMap or GradientWidget.
|
Lookup tables can be built using ColorMap or GradientWidget.
|
||||||
useRGBA If True, the data is returned in RGBA order (useful for building OpenGL textures).
|
useRGBA If True, the data is returned in RGBA order (useful for building OpenGL textures).
|
||||||
The default is False, which returns in ARGB order for use with QImage
|
The default is False, which returns in ARGB order for use with QImage
|
||||||
(Note that 'ARGB' is a term used by the Qt documentation; the _actual_ order
|
(Note that 'ARGB' is a term used by the Qt documentation; the *actual* order
|
||||||
is BGRA).
|
is BGRA).
|
||||||
============== ==================================================================================
|
============== ==================================================================================
|
||||||
"""
|
"""
|
||||||
@ -909,7 +913,7 @@ def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
|
|||||||
raise Exception('levels argument must have length 2')
|
raise Exception('levels argument must have length 2')
|
||||||
elif levels.ndim == 2:
|
elif levels.ndim == 2:
|
||||||
if lut is not None and lut.ndim > 1:
|
if lut is not None and lut.ndim > 1:
|
||||||
raise Exception('Cannot make ARGB data when bot levels and lut have ndim > 2')
|
raise Exception('Cannot make ARGB data when both levels and lut have ndim > 2')
|
||||||
if levels.shape != (data.shape[-1], 2):
|
if levels.shape != (data.shape[-1], 2):
|
||||||
raise Exception('levels must have shape (data.shape[-1], 2)')
|
raise Exception('levels must have shape (data.shape[-1], 2)')
|
||||||
else:
|
else:
|
||||||
@ -918,19 +922,19 @@ def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
|
|||||||
|
|
||||||
profile()
|
profile()
|
||||||
|
|
||||||
|
# Decide on maximum scaled value
|
||||||
if scale is None:
|
if scale is None:
|
||||||
if lut is not None:
|
if lut is not None:
|
||||||
scale = lut.shape[0]
|
scale = lut.shape[0] - 1
|
||||||
else:
|
else:
|
||||||
scale = 255.
|
scale = 255.
|
||||||
|
|
||||||
if lut is not None:
|
# Decide on the dtype we want after scaling
|
||||||
dtype = lut.dtype
|
if lut is None:
|
||||||
elif scale == 255:
|
|
||||||
dtype = np.ubyte
|
dtype = np.ubyte
|
||||||
else:
|
else:
|
||||||
dtype = np.float
|
dtype = np.min_scalar_type(lut.shape[0]-1)
|
||||||
|
|
||||||
## Apply levels if given
|
## Apply levels if given
|
||||||
if levels is not None:
|
if levels is not None:
|
||||||
|
|
||||||
@ -949,20 +953,7 @@ def makeARGB(data, lut=None, levels=None, scale=None, useRGBA=False):
|
|||||||
minVal, maxVal = levels
|
minVal, maxVal = levels
|
||||||
if minVal == maxVal:
|
if minVal == maxVal:
|
||||||
maxVal += 1e-16
|
maxVal += 1e-16
|
||||||
if maxVal == minVal:
|
data = rescaleData(data, scale/(maxVal-minVal), minVal, dtype=dtype)
|
||||||
data = rescaleData(data, 1, minVal, dtype=dtype)
|
|
||||||
else:
|
|
||||||
lutSize = 2**(data.itemsize*8)
|
|
||||||
if data.dtype in (np.ubyte, np.uint16) and data.size > lutSize:
|
|
||||||
# Rather than apply scaling to image, scale the LUT for better performance.
|
|
||||||
ind = np.arange(lutSize)
|
|
||||||
indr = rescaleData(ind, scale/(maxVal-minVal), minVal, dtype=dtype)
|
|
||||||
if lut is None:
|
|
||||||
lut = indr
|
|
||||||
else:
|
|
||||||
lut = lut[indr]
|
|
||||||
else:
|
|
||||||
data = rescaleData(data, scale/(maxVal-minVal), minVal, dtype=dtype)
|
|
||||||
|
|
||||||
profile()
|
profile()
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user