ENH: Clarify FreeImage IO flags, improve tests, and fix documentation

This commit is contained in:
Zach Pincus
2012-02-02 11:05:27 -05:00
parent a4c986b02f
commit 12e67e781e
2 changed files with 133 additions and 62 deletions
+113 -56
View File
@@ -214,70 +214,115 @@ class FI_TYPES(object):
return numpy.dtype(dtype), extra_dims + [w, h]
class IO_FLAGS(object):
#Bmp
FIF_LOAD_NOPIXELS = 0x8000 # loading: load the image header only
# (not supported by all plugins)
BMP_DEFAULT = 0
BMP_SAVE_RLE = 1
#Png
PNG_DEFAULT = 0
PNG_IGNOREGAMMA = 1
#Gif
GIF_DEFAULT = 0
GIF_LOAD256 = 1
GIF_PLAYBACK = 2
#Ico
ICO_DEFAULT = 0
ICO_MAKEALPHA = 1
#Tiff
TIFF_DEFAULT = 0
TIFF_CMYK = 0x0001
TIFF_NONE = 0x0800
TIFF_PACKBITS = 0x0100
TIFF_DEFLATE = 0x0200
TIFF_ADOBE_DEFLATE = 0x0400
TIFF_CCITTFAX3 = 0x1000
TIFF_CCITTFAX4 = 0x2000
TIFF_LZW = 0x4000
TIFF_JPEG = 0x8000
#Jpeg
JPEG_DEFAULT = 0
JPEG_FAST = 1
JPEG_ACCURATE = 2
JPEG_QUALITYSUPERB = 0x80
JPEG_QUALITYGOOD = 0x100
JPEG_QUALITYNORMAL = 0x200
JPEG_QUALITYAVERAGE = 0x400
JPEG_QUALITYBAD = 0x800
JPEG_CMYK = 0x1000
JPEG_PROGRESSIVE = 0x2000
#Others...
CUT_DEFAULT = 0
DDS_DEFAULT = 0
EXR_DEFAULT = 0 # save data as half with piz-based wavelet compression
EXR_FLOAT = 0x0001 # save data as float instead of as half (not recommended)
EXR_NONE = 0x0002 # save with no compression
EXR_ZIP = 0x0004 # save with zlib compression, in blocks of 16 scan lines
EXR_PIZ = 0x0008 # save with piz-based wavelet compression
EXR_PXR24 = 0x0010 # save with lossy 24-bit float compression
EXR_B44 = 0x0020 # save with lossy 44% float compression
# - goes to 22% when combined with EXR_LC
EXR_LC = 0x0040 # save images with one luminance and two chroma channels,
# rather than as RGB (lossy compression)
FAXG3_DEFAULT = 0
GIF_DEFAULT = 0
GIF_LOAD256 = 1 # Load the image as a 256 color image with ununsed
# palette entries, if it's 16 or 2 color
GIF_PLAYBACK = 2 # 'Play' the GIF to generate each frame (as 32bpp)
# instead of returning raw frame data when loading
HDR_DEFAULT = 0
ICO_DEFAULT = 0
ICO_MAKEALPHA = 1 # convert to 32bpp and create an alpha channel from the
# AND-mask when loading
IFF_DEFAULT = 0
J2K_DEFAULT = 0 # save with a 16:1 rate
JP2_DEFAULT = 0 # save with a 16:1 rate
JPEG_DEFAULT = 0 # loading (see JPEG_FAST);
# saving (see JPEG_QUALITYGOOD|JPEG_SUBSAMPLING_420)
JPEG_FAST = 0x0001 # load the file as fast as possible,
# sacrificing some quality
JPEG_ACCURATE = 0x0002 # load the file with the best quality,
# sacrificing some speed
JPEG_CMYK = 0x0004 # load separated CMYK "as is"
# (use | to combine with other load flags)
JPEG_EXIFROTATE = 0x0008 # load and rotate according to
# Exif 'Orientation' tag if available
JPEG_QUALITYSUPERB = 0x80 # save with superb quality (100:1)
JPEG_QUALITYGOOD = 0x0100 # save with good quality (75:1)
JPEG_QUALITYNORMAL = 0x0200 # save with normal quality (50:1)
JPEG_QUALITYAVERAGE = 0x0400 # save with average quality (25:1)
JPEG_QUALITYBAD = 0x0800 # save with bad quality (10:1)
JPEG_PROGRESSIVE = 0x2000 # save as a progressive-JPEG
# (use | to combine with other save flags)
JPEG_SUBSAMPLING_411 = 0x1000 # save with high 4x1 chroma
# subsampling (4:1:1)
JPEG_SUBSAMPLING_420 = 0x4000 # save with medium 2x2 medium chroma
# subsampling (4:2:0) - default value
JPEG_SUBSAMPLING_422 = 0x8000 # save with low 2x1 chroma subsampling (4:2:2)
JPEG_SUBSAMPLING_444 = 0x10000 # save with no chroma subsampling (4:4:4)
JPEG_OPTIMIZE = 0x20000 # on saving, compute optimal Huffman coding tables
# (can reduce a few percent of file size)
JPEG_BASELINE = 0x40000 # save basic JPEG, without metadata or any markers
KOALA_DEFAULT = 0
LBM_DEFAULT = 0
MNG_DEFAULT = 0
PCD_DEFAULT = 0
PCD_BASE = 1
PCD_BASEDIV4 = 2
PCD_BASEDIV16 = 3
PCD_BASE = 1 # load the bitmap sized 768 x 512
PCD_BASEDIV4 = 2 # load the bitmap sized 384 x 256
PCD_BASEDIV16 = 3 # load the bitmap sized 192 x 128
PCX_DEFAULT = 0
PFM_DEFAULT = 0
PICT_DEFAULT = 0
PNG_DEFAULT = 0
PNG_IGNOREGAMMA = 1 # loading: avoid gamma correction
PNG_Z_BEST_SPEED = 0x0001 # save using ZLib level 1 compression flag
# (default value is 6)
PNG_Z_DEFAULT_COMPRESSION = 0x0006 # save using ZLib level 6 compression
# flag (default recommended value)
PNG_Z_BEST_COMPRESSION = 0x0009 # save using ZLib level 9 compression flag
# (default value is 6)
PNG_Z_NO_COMPRESSION = 0x0100 # save without ZLib compression
PNG_INTERLACED = 0x0200 # save using Adam7 interlacing (use | to combine
# with other save flags)
PNM_DEFAULT = 0
PNM_SAVE_RAW = 0
PNM_SAVE_ASCII = 1
PNM_SAVE_RAW = 0 # Writer saves in RAW format (i.e. P4, P5 or P6)
PNM_SAVE_ASCII = 1 # Writer saves in ASCII format (i.e. P1, P2 or P3)
PSD_DEFAULT = 0
PSD_CMYK = 1 # reads tags for separated CMYK (default is conversion to RGB)
PSD_LAB = 2 # reads tags for CIELab (default is conversion to RGB)
RAS_DEFAULT = 0
RAW_DEFAULT = 0 # load the file as linear RGB 48-bit
RAW_PREVIEW = 1 # try to load the embedded JPEG preview with included
# Exif Data or default to RGB 24-bit
RAW_DISPLAY = 2 # load the file as RGB 24-bit
SGI_DEFAULT = 0
TARGA_DEFAULT = 0
TARGA_LOAD_RGB888 = 1
TARGA_LOAD_RGB888 = 1 # Convert RGB555 and ARGB8888 -> RGB888.
TARGA_SAVE_RLE = 2 # Save with RLE compression
TIFF_DEFAULT = 0
TIFF_CMYK = 0x0001 # reads/stores tags for separated CMYK
# (use | to combine with compression flags)
TIFF_PACKBITS = 0x0100 # save using PACKBITS compression
TIFF_DEFLATE = 0x0200 # save using DEFLATE (a.k.a. ZLIB) compression
TIFF_ADOBE_DEFLATE = 0x0400 # save using ADOBE DEFLATE compression
TIFF_NONE = 0x0800 # save without any compression
TIFF_CCITTFAX3 = 0x1000 # save using CCITT Group 3 fax encoding
TIFF_CCITTFAX4 = 0x2000 # save using CCITT Group 4 fax encoding
TIFF_LZW = 0x4000 # save using LZW compression
TIFF_JPEG = 0x8000 # save using JPEG compression
TIFF_LOGLUV = 0x10000 # save using LogLuv compression
WBMP_DEFAULT = 0
XBM_DEFAULT = 0
XPM_DEFAULT = 0
class METADATA_MODELS(object):
FIMD_COMMENTS = 0
FIMD_EXIF_MAIN = 1
@@ -342,19 +387,23 @@ def _process_bitmap(filename, flags, process_func):
_FI.FreeImage_Unload(bitmap)
def read(filename, flags=0):
"""Read an image to a numpy array of shape (width, height) for
greyscale images, or shape (width, height, nchannels) for RGB or
"""Read an image to a numpy array of shape (height, width) for
greyscale images, or shape (height, width, nchannels) for RGB or
RGBA images.
The `flags` parameter should be one or more values from the IO_FLAGS
class defined in this module, or-ed together with | as appropriate.
(See the source-code comments for more details.)
"""
return _process_bitmap(filename, flags, _array_from_bitmap)
def read_metadata(filename, flags=0):
def read_metadata(filename):
"""Return a dict containing all image metadata.
Returned dict maps (metadata_model, tag_name) keys to tag values, where
metadata_model is a string name based on the FreeImage "metadata models"
defined in the class METADATA_MODELS.
"""
flags = IO_FLAGS.FIF_LOAD_NOPIXELS
return _process_bitmap(filename, flags, _read_metadata)
def _process_multipage(filename, flags, process_func):
@@ -390,15 +439,19 @@ def _process_multipage(filename, flags, process_func):
def read_multipage(filename, flags=0):
"""Read a multipage image to a list of numpy arrays, where each
array is of shape (width, height) for greyscale images, or shape
(width, height, nchannels) for RGB or RGBA images.
array is of shape (height, width) for greyscale images, or shape
(height, width, nchannels) for RGB or RGBA images.
The `flags` parameter should be one or more values from the IO_FLAGS
class defined in this module, or-ed together with | as appropriate.
(See the source-code comments for more details.)
"""
return _process_multipage(filename, flags, _array_from_bitmap)
def read_multipage_metadata(filename, flags=0):
def read_multipage_metadata(filename):
"""Read a multipage image to a list of metadata dicts, one dict for each
page. The dict format is as in read_metadata().
"""
flags = IO_FLAGS.FIF_LOAD_NOPIXELS
return _process_multipage(filename, flags, _read_metadata)
def _wrap_bitmap_bits_in_array(bitmap, shape, dtype):
@@ -481,10 +534,12 @@ def _read_metadata(bitmap):
return metadata
def write(array, filename, flags=0):
"""Write a (width, height) or (width, height, nchannels) array to
"""Write a (height, width) or (height, width, nchannels) array to
a greyscale, RGB, or RGBA image, with file type deduced from the
filename.
The `flags` parameter should be one or more values from the IO_FLAGS
class defined in this module, or-ed together with | as appropriate.
(See the source-code comments for more details.)
"""
array = numpy.asarray(array)
filename = asbytes(filename)
@@ -508,10 +563,12 @@ def write(array, filename, flags=0):
_FI.FreeImage_Unload(bitmap)
def write_multipage(arrays, filename, flags=0):
"""Write a list of (width, height) or (width, height, nchannels)
"""Write a list of (height, width) or (height, width, nchannels)
arrays to a multipage greyscale, RGB, or RGBA image, with file type
deduced from the filename.
The `flags` parameter should be one or more values from the IO_FLAGS
class defined in this module, or-ed together with | as appropriate.
(See the source-code comments for more details.)
"""
filename = asbytes(filename)
ftype = _FI.FreeImage_GetFIFFromFilename(filename)
+20 -6
View File
@@ -1,13 +1,27 @@
import os
import skimage as si
import skimage.io as sio
import skimage.io._plugins.freeimage_plugin as fi
sio.use_plugin('matplotlib', 'imshow')
sio.use_plugin('freeimage', 'imread')
from numpy.testing import *
img = sio.imread(os.path.join(si.data_dir, 'color.png'))
sio.imshow(img)
sio.show()
def test_read():
sio.use_plugin('freeimage', 'imread')
img = sio.imread(os.path.join(si.data_dir, 'color.png'))
assert img.shape == (370, 371, 3)
assert all(img[274,135] == [0, 130, 253])
def test_metadata():
meta = fi.read_metadata(os.path.join(si.data_dir, 'multipage.tif'))
assert meta[('EXIF_MAIN', 'BitsPerSample')] == 8
assert meta[('EXIF_MAIN', 'Software')].startswith('ImageMagick')
meta = fi.read_multipage_metadata(os.path.join(si.data_dir, 'multipage.tif'))
assert len(meta) == 2
assert meta[0][('EXIF_MAIN', 'BitsPerSample')] == 8
assert meta[1][('EXIF_MAIN', 'Software')].startswith('ImageMagick')
if __name__ == "__main__":
run_module_suite()