Description
Pillow (and PIL) is currently able to open 8 bit per channel multi-channel images (such as RGB) but is able to open higher bit depth images (e.g. I16, I32, or Float32 images) if they are single channel (e.g., grayscale).
Previous References
This has been requested many times: #1828, #1885, #1839, #1602, and farther back.
Requirements
- We should be able to support common GIS formats as well as high bit depth RGB(A) images.
- At least 4 channels, but potentially more (see Add tests for opening 2-5 layer uint16 greyscale TIFFs #1839)
- Different pixel formats, including I16, I32, and Float.
- There should be definitions for the array interface to exchange images with numpy/scipy
- There should be enough support to read and write TIFFs and raw image data.
- Support for resize, crop, and convert operations at the very least.
Background Reference Info
The rough sequence for image loading is:
-
Image file is opened
-
Each of the ImagePlugin _accept functions have a chance to look at the first few bytes to determine if they should attempt to open the file
-
The
*ImagePlugin._open
method is called giving the image plugin a chance to read more of the image and determine if it still wants to consider it a valid image of it's particular type. If it does, it passes back a tile definition which includes a decoder and an image size. -
If there is a successful _open call, at some point later
*ImagePlugin._load
may be called on the image, which runs the decoder producing a set of bytes in a raw mode. This is where things like compression are handled, but the output of the decoder is not necessarily what we're storing in our internal structures. -
The image is unpacked (
Unpack.c
) from the raw mode (e.g.I16;BS
) into a storage (Storage.c
) mode (I
). -
It's now possible to operate on the image (e.g. crop, pixel access, etc)
There are 3 (or 4) image data pointers, as defined in Imaging.h:
struct ImagingMemoryInstance {
/* Format */
char mode[IMAGING_MODE_LENGTH]; /* Band names ("1", "L", "P", "RGB", "RGBA", "CMYK", "YCbCr", "BGR;xy") */
int type; /* Data type (IMAGING_TYPE_*) */
int depth; /* Depth (ignored in this version) */
int bands; /* Number of bands (1, 2, 3, or 4) */
int xsize; /* Image dimension. */
int ysize;
/* Colour palette (for "P" images only) */
ImagingPalette palette;
/* Data pointers */
UINT8 **image8; /* Set for 8-bit images (pixelsize=1). */
INT32 **image32; /* Set for 32-bit images (pixelsize=4). */
/* Internals */
char **image; /* Actual raster data. */
char *block; /* Set if data is allocated in a single block. */
int pixelsize; /* Size of a pixel, in bytes (1, 2 or 4) */
int linesize; /* Size of a line, in bytes (xsize * pixelsize) */
/* Virtual methods */
void (*destroy)(Imaging im);
};
The only one that is guaranteed to be set is **image
, which is an array of pointers to row data.
Changes Required
- Definitions for all of the modes that we're planning, and potentially a [format];MB[#bands] style generic mode.
Core Imaging Structure
- The imaging structure has the fields required to add the additional channels. (type, bands, pixelsize, linesize)
- The
**image
pointer can be used for any width of pixel. - We may or may not want to set the
**image32
pointer. - Currently type of
IMAGING_TYPE_INT32
andIMAGING_TYPE_FLOAT32
imply 1 band. This will change. - Consider promoting int16 to
IMAGING_TYPE_INT16
Storage
- Updates to
Storage.c
,Unpack.c
,Pack.c
,Access.c
,PyAccess.py
, andConvert.c
Ways to Help
We need a better definition of the format requirements. What are the various types of images that are used in GIS, Medical, or other fields that we'd want to interpret? We need small, redistributable versions of images that we can test against.
[in progress]