mirror of
https://github.com/wassname/scikit-image.git
synced 2026-07-05 19:58:52 +08:00
Fix freeimage_plugin.imsave
Previously, the plugin perfomed a copy of the bitmap's pixel memory instead of mapping into a ndarray. This fixes it. Also, it saved images rotated by 90 degrees as it didn't convert to freeimage's internal format. Copying less also makes imread visibly faster.
This commit is contained in:
@@ -286,7 +286,6 @@ def _wrap_bitmap_bits_in_array(bitmap, shape, dtype):
|
||||
"""
|
||||
pitch = _FI.FreeImage_GetPitch(bitmap)
|
||||
height = shape[-1]
|
||||
byte_size = height * pitch
|
||||
itemsize = dtype.itemsize
|
||||
|
||||
if len(shape) == 3:
|
||||
@@ -301,31 +300,33 @@ def _wrap_bitmap_bits_in_array(bitmap, shape, dtype):
|
||||
'strides': strides,
|
||||
'typestr': dtype.str,
|
||||
'shape': tuple(shape),
|
||||
'version' : 3,
|
||||
}
|
||||
|
||||
# Still segfaulting on 64-bit machine because of illegal memory access
|
||||
|
||||
return numpy.array(DummyArray())
|
||||
return numpy.array(DummyArray(), copy=False)
|
||||
|
||||
def _array_from_bitmap(bitmap):
|
||||
"""Convert a FreeImage bitmap pointer to a numpy array
|
||||
"""Convert a FreeImage bitmap pointer to a numpy array
|
||||
|
||||
"""
|
||||
dtype, shape = FI_TYPES.get_type_and_shape(bitmap)
|
||||
array = _wrap_bitmap_bits_in_array(bitmap, shape, dtype)
|
||||
# swizzle the color components and flip the scanlines to go from
|
||||
# FreeImage's BGR[A] and upside-down internal memory format to something
|
||||
# more normal
|
||||
if len(shape) == 3 and _FI.FreeImage_IsLittleEndian() and \
|
||||
dtype.type == numpy.uint8:
|
||||
b = array[0].copy()
|
||||
array[0] = array[2]
|
||||
array[2] = b
|
||||
|
||||
array = array[..., ::-1]
|
||||
array = array.T
|
||||
|
||||
return array.copy()
|
||||
"""
|
||||
dtype, shape = FI_TYPES.get_type_and_shape(bitmap)
|
||||
array = _wrap_bitmap_bits_in_array(bitmap, shape, dtype)
|
||||
# swizzle the color components and flip the scanlines to go from
|
||||
# FreeImage's BGR[A] and upside-down internal memory format to something
|
||||
# more normal
|
||||
def n(arr):
|
||||
return arr[..., ::-1].T
|
||||
if len(shape) == 3 and _FI.FreeImage_IsLittleEndian() and \
|
||||
dtype.type == np.uint8:
|
||||
b = array[0]
|
||||
g = array[1]
|
||||
r = array[2]
|
||||
return np.dstack( (n(r), n(g), n(b)) )
|
||||
# We need to copy because array does *not* own its memory
|
||||
# after bitmap is freed.
|
||||
return n(array).copy()
|
||||
|
||||
def string_tag(bitmap, key, model=METADATA_MODELS.FIMD_EXIF_MAIN):
|
||||
"""Retrieve the value of a metadata tag with the given string key as a
|
||||
@@ -338,7 +339,7 @@ def string_tag(bitmap, key, model=METADATA_MODELS.FIMD_EXIF_MAIN):
|
||||
return char_ptr.from_address(_FI.FreeImage_GetTagValue(tag)).raw()
|
||||
|
||||
def write(array, filename, flags=0):
|
||||
"""Write a (width, height) or (nchannels, width, height) array to
|
||||
"""Write a (width, height) or (width, height, nchannels) array to
|
||||
a greyscale, RGB, or RGBA image, with file type deduced from the
|
||||
filename.
|
||||
|
||||
@@ -394,34 +395,40 @@ def _array_to_bitmap(array):
|
||||
"""
|
||||
shape = array.shape
|
||||
dtype = array.dtype
|
||||
r,c = shape[:2]
|
||||
if len(shape) == 2:
|
||||
n_channels = 1
|
||||
w_shape = (c,r)
|
||||
elif len(shape) == 3:
|
||||
n_channels = shape[2]
|
||||
w_shape = (n_channels,c,r)
|
||||
else:
|
||||
n_channels = shape[0]
|
||||
try:
|
||||
fi_type = FI_TYPES.fi_types[(dtype.type, n_channels)]
|
||||
except KeyError:
|
||||
raise ValueError('Cannot write arrays of given type and shape.')
|
||||
width, height = shape[-2:]
|
||||
|
||||
itemsize = array.dtype.itemsize
|
||||
bpp = 8 * itemsize * n_channels
|
||||
bitmap = _FI.FreeImage_AllocateT(fi_type, width, height, bpp, 0, 0, 0)
|
||||
bitmap = _FI.FreeImage_AllocateT(fi_type, c, r, bpp, 0, 0, 0)
|
||||
if not bitmap:
|
||||
raise RuntimeError('Could not allocate image for storage')
|
||||
try:
|
||||
wrapped_array = _wrap_bitmap_bits_in_array(bitmap, shape, dtype)
|
||||
def n(arr): # normalise to freeimage's in-memory format
|
||||
return arr.T[:,::-1]
|
||||
wrapped_array = _wrap_bitmap_bits_in_array(bitmap, w_shape, dtype)
|
||||
# swizzle the color components and flip the scanlines to go to
|
||||
# FreeImage's BGR[A] and upside-down internal memory format
|
||||
if len(shape) == 3 and _FI.FreeImage_IsLittleEndian() and \
|
||||
dtype.type == numpy.uint8:
|
||||
wrapped_array[0] = array[2,:,::-1]
|
||||
wrapped_array[1] = array[1,:,::-1]
|
||||
wrapped_array[2] = array[0,:,::-1]
|
||||
if shape[0] == 4:
|
||||
wrapped_array[3] = array[3,:,::-1]
|
||||
wrapped_array[0] = n(array[:,:,2])
|
||||
wrapped_array[1] = n(array[:,:,1])
|
||||
wrapped_array[2] = n(array[:,:,0])
|
||||
if shape[2] == 4:
|
||||
wrapped_array[3] = n(array[:,:,3])
|
||||
else:
|
||||
wrapped_array[:] = array[...,::-1]
|
||||
wrapped_array[:] = n(array)
|
||||
|
||||
return bitmap, fi_type
|
||||
except:
|
||||
@@ -429,13 +436,38 @@ def _array_to_bitmap(array):
|
||||
raise
|
||||
|
||||
|
||||
def imread(filename, as_grey=False, dtype=None):
|
||||
"""Warning: currenly as_grey and dtype is simply ignored.
|
||||
|
||||
def imread(filename, as_grey=False):
|
||||
"""
|
||||
return read(filename)
|
||||
img = imread(filename, as_grey=False)
|
||||
|
||||
def imsave(filename, arr):
|
||||
if arr.ndim == 3:
|
||||
arr = numpy.rollaxis(arr, 2, 0)
|
||||
write(arr, filename)
|
||||
Reads an image from file `filename`
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : file name
|
||||
as_grey : Whether to convert to grey scale image (default: no)
|
||||
Returns
|
||||
-------
|
||||
img : ndarray
|
||||
"""
|
||||
img = read(filename)
|
||||
if as_grey and len(img) == 3:
|
||||
# these are the values that wikipedia says are typical
|
||||
transform = np.array([ 0.30, 0.59, 0.11])
|
||||
return np.dot(img, transform)
|
||||
return img
|
||||
|
||||
def imsave(filename, img):
|
||||
'''
|
||||
imsave(filename, img)
|
||||
|
||||
Save image to disk
|
||||
|
||||
Image type is inferred from filename
|
||||
|
||||
Parameters
|
||||
----------
|
||||
filename : file name
|
||||
img : image to be saved as nd array
|
||||
'''
|
||||
write(img, filename)
|
||||
|
||||
Reference in New Issue
Block a user