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!