I have TIF files that are in the ProPhoto RGB colorspace. These are imported fine with scikit-image’s "imload" method. However, when I try to use matplotlib to view the image data I receive the error:
plt.imshow(myImage)
plt.show()
Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).
The values are clipped to 255 and a totally white image is displayed. The error is correct about the image data as read by imread. The values look like:
myImage[0]
array([[60061, 60135, 60673],
[59907, 59983, 60533],
[59931, 60007, 60557],
...,
[60649, 60801, 61147],
[60581, 60743, 61091],
[60647, 60797, 61143]], dtype=uint16)
These values obviously need to be scaled to obtain proper RGB values that range between 0-255.
When I open the image file in something like IrfanView and re-save it, the colorspace is handled properly as RGB (probably because IrfanView is converting it for me). However, I need to automate that conversion.
Is it possible to convert TIFs using the ProPhoto RGB colorspace to the RGB colorspace using either scikit-image or PIL (or something else)? I did not see any mention of that colorspace in the docs for the "color" module of scikit-image at https://scikit-image.org/docs/stable/api/skimage.color.html. Unless "ProPhoto RGB" can be known by another name or compatible with another conversion method?
Thank you!
EDIT:
User Abhi25t’s answer helped make some progress towards displaying these images. However, their answer appears to address only the 16-bit to 8-bit conversion. There is still a colorspace issue of ProPhoto RGB to sRGB. Hopefully this edit demonstrates this better.
The pixel values for the raw test TIF image in ProPhoto colorspace:
array([[58465, 58479, 58785],
[58575, 58591, 58879],
[58441, 58457, 58739],
...,
[58185, 58045, 58549],
[58101, 57951, 58463],
[57993, 57853, 58371]], dtype=uint16)
The pixel values for the Photoshop sRGB converted file:
array([[59771, 59873, 60161],
[59863, 59965, 60235],
[59755, 59855, 60119],
...,
[59623, 59489, 59993],
[59561, 59411, 59925],
[59463, 59333, 59851]], dtype=uint16)
The pixel values for the IRFAN VIEW converted file (it appears to have converted to 8-bit AND translated to sRGB space):
array([[233, 233, 234],
[233, 233, 234],
[232, 233, 234],
...,
[232, 231, 233],
[232, 231, 233],
[231, 231, 233]], dtype=uint8)
I have added some test code and images here:
https://drive.google.com/drive/folders/1tcfUY2Kwlz-LAlt6_YXtT8l6vLnCucbM?usp=sharing
The image should display as a colorchecker target. You should be able to see it properly just plotting the imread result of "TEST_PROPHOTO_IRFAN_SAVED.tif".
from skimage import io
import numpy as np
import matplotlib.pyplot as plt
# TEST_PROPHOTO.tif : RAW TIF FILE
# TEST_PROPHOTO_IRFAN_SAVED.tif : RAW TIF, OPENED IN IRFANVIEW AND RESAVED AS TIF
# TEST_SRGB_PHOTOSHOP_CONVERTED.tif : RAW TIF, OPENED IN PHOTOSHOP, PROFILE CONVERTED TO sRGB, RESAVED AS TIF
img_path = '/path/to/image/myImage.tif'
img_rgb = io.imread(img_path)
plt.imshow(img_rgb)
plt.show()
# VIEW IMAGE CONTENTS
img_rgb[0] # you can see these values are 16-bit;
# however, colorspace (actual RGB values) differs between the ProPhoto test file and the Photoshop converted sRGB file
# STACKOVERFLOW USER Abhi25t's METHOD TO CONVERT FROM 16-bit color [0-65535] to 8-bit color [0-255]:
img_rgb_convert = img_rgb * (255/65535)
img_rgb_convert = img_rgb_convert.astype(int)
plt.imshow(img_rgb_convert)
plt.show()
2
Answers
You need to convert 16-bit resolution (of grayscale) to 8-bit here.
And then matplotlib will be able to display.
Convert your floats to int if required.
You would need to perform the following steps:
imread
.Colour can do 3 to 5 directly using the colour.RGB_to_RGB definition. Assuming the data is in floating-point range already, the conversion would be like to that:
Note: Because ProPhoto RGB has a larger gamut than that of sRGB, it is possible that the conversion generates out-of-gamut colours, those can be clipped in the range [0-1] for simplicity after step 4 or 5 or gamut-mapped using a dedicated algorithm.