0

If I have a NumPy array with dtype=np.uint16, how can I save the data as uint16 JPEG compressed?

How can I then load the uint16 JPEG compressed data?

It doesn't seem like Pillow supports this, at least not by saving the file as jpg extension, see Pillow image file formats.

HansHirse
  • 18,010
  • 10
  • 38
  • 67
user3731622
  • 4,844
  • 8
  • 45
  • 84

1 Answers1

3

You can't save 16-bit images in (plain old) JPEG format. Only 8-bit and 12-bit are allowed (see ISO/IEC 10918-1). You might look into JPEG 2000, which also supports 16-bit.

Pillow has JPEG 2000 support. Unfortunately, I wasn't able to save a 16-bit RGB image. Best I could do, was a 16-bit grayscale image:

import numpy as np
from PIL import Image

image_array = np.uint16(np.random.rand(200, 200) * 65535)
image_pil = Image.fromarray(image_array, 'I;16')
image_pil.save('image_pil.jp2')

Opening image_pil.jp2 in GIMP indeed shows a 16-bit grayscale image.

Since you already have a NumPy array, OpenCV comes to mind, whose cv2.imwrite method also has JPEG 2000 support. Using OpenCV, I was able to also save a 16-bit RGB image:

import cv2
import numpy as np

image_array = np.uint16(np.random.rand(200, 200, 3) * 65535)
cv2.imwrite('image_cv.jp2', image_array)

And, opening image_cv.jp2 in GIMP shows a 16-bit RGB image.

By default, OpenCV disables JPEG 2000 support. You have to explicitly set the environment variable OPENCV_IO_ENABLE_JASPER=1.

Alternatively, you could go for (compressed) PNG.

Hope that helps!

HansHirse
  • 18,010
  • 10
  • 38
  • 67
  • the [Pillow has JPEG 2000 support](https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html#jpeg-2000) link you shared doesn't mention support for 'uint16'. Are you certain it's correctly supported? Also, I'm not familiar with the notation `I;16` & don't see it in the [pillow docs](https://pillow.readthedocs.io/en/3.1.x/handbook/concepts.html#concept-modes). I'm guessing it's specifying signed 16 bit integers. Can you explain it and provide a link to where it's defined? – user3731622 Nov 22 '19 at 22:20
  • It appears OpenCV [doesn't support compression with JPEG 2000](https://answers.opencv.org/question/176706/did-jpeg-2000-saved-in-lossless-or-lossy/) – user3731622 Nov 22 '19 at 23:34
  • 1
    @user3731622 Regarding Pillow: In the [`PIL.Image.fromarray`](https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.fromarray) method, there's the `mode` parameter, where you can choose one these [modes](https://pillow.readthedocs.io/en/stable/handbook/concepts.html#concept-modes). There you can see, that `I;16` is "16-bit unsigned integer pixels". As mentioned, I couldn't get three channel 16-bit unsigned working. Regarding OpenCV: If that's true in respect of Jasper, then you're right, there's no compression. Maybe compressed PNG is the way to go then. – HansHirse Nov 25 '19 at 06:55