astrofrog
astrofrog

Reputation: 34181

Creating a 48-bit TIFF file in Python with PIL

I would like to create a 48-bit (RGB) TIFF file (16-bit per channel) using PIL in Python. However, even though I have found a way to store individual channels as 16-bit, I can't manage to merge these into a single 48-bit RGB image:

In [3]: import numpy as np

In [4]: from PIL import Image

In [5]: r = np.array([[1,2],[3,4]], dtype=np.uint16)

In [6]: i = Image.fromarray(r, mode='I;16')

In [7]: Image.merge("RGB", (i,i,i))
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-7-35aa00ddbb2e> in <module>()
----> 1 Image.merge("RGB", (i,i,i))

/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/PIL/Image.pyc in merge(mode, bands)
   2059     for im in bands[1:]:
   2060         if im.mode != getmodetype(mode):
-> 2061             raise ValueError("mode mismatch")
   2062         if im.size != bands[0].size:
   2063             raise ValueError("size mismatch")

ValueError: mode mismatch

Does anyone have any ideas for how to solve this? Or do I need to save the channels as separate 16-bit files and combine them with different software?

Upvotes: 1

Views: 2704

Answers (2)

jterrace
jterrace

Reputation: 67163

PIL doesn't support 48-bit RGB for output. See the list of modes supported, repeated here for completion:

  • 1 (1-bit pixels, black and white, stored with one pixel per byte)
  • L (8-bit pixels, black and white)
  • P (8-bit pixels, mapped to any other mode using a colour palette)
  • RGB (3x8-bit pixels, true colour)
  • RGBA (4x8-bit pixels, true colour with transparency mask)
  • CMYK (4x8-bit pixels, colour separation)
  • YCbCr (3x8-bit pixels, colour video format)
  • I (32-bit signed integer pixels)
  • F (32-bit floating point pixels)

PIL also provides limited support for a few special modes, including LA (L with alpha), RGBX (true colour with padding) and RGBa (true colour with premultiplied alpha). However, PIL doesn’t support user-defined modes; if you to handle band combinations that are not listed above, use a sequence of Image objects.

Also note that PIL does support importing 48-bit RGB, but it converts it to 32-bit RGBA while importing (see the unpackRGB16B function).

Upvotes: 3

abarnert
abarnert

Reputation: 366103

As the docs and jterrace's answer say, if you want RGB16 with PIL, you have to:

use a sequence of Image objects.

Does that mean you need to save the Image objects separately and combine them with different software?

That's the obvious answer. But there may be a better way. Interleaving R, G, and B plane pixmaps into a single RGB pixmap is trivial (and quick, with numpy), so you could just create a single raw pixmap instead of trying to create an Image. You can save that to a binary file—or, if the "different software" you choose is a Python library, just do it in memory.

Upvotes: 3

Related Questions