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:
Luke Campagnola 2016-01-25 18:32:37 -08:00
parent 99aa4cfdd3
commit e2f43ce4be

View File

@ -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()