Reputation: 5039
I am trying to display .tif images using the ipywidgets in jupyter-notebooks. The below code works for .png and .jpg files
from ipywidgets import Image
png_image_path = r"C:\Users\xxxxxxxx\Work\Exercises\images\000000000.png"
file = open(png_image_path, "rb")
im = file.read()
Image(
value=im,
width=300,
height=400,
)
type(im) # <class 'bytes'>
The ipywidget from the above code renders the desired image. For reading a tif
file I am using gdal
.
img = gdal.Open(tif_img_path).ReadAsArray()
print(img.shape) # (3, 1024, 1024)
print(img.transpose(1,2, 0).shape) # (1024, 1024, 3)
type(img.transpose(1,2,0).tobytes()) # <class 'bytes'>
Image(
value=img.transpose(1,2,0).tobytes(),
width=300,
height=400,
)
I get the following output, the image is not properly displayed in the ipywidget
Upvotes: 1
Views: 1969
Reputation: 207465
The fact that you just do file.read()
on the PNG image implies to me that Jupyter widgets expect a PNG or JPEG-encoded image, with a header and compressed pixel data.
If you open your TIFF with GDAL you will have a Numpy array, so you will need to encode it into an "in-memory" PNG or JPEG before passing to Jupyter widgets. You can do that with OpenCV like this:
import cv2
# Open TIFF image into Numpy array
img = gdal.Open(tif_img_path).ReadAsArray()
# Encode into in-memory PNG for Jupyter
_, PNG = cv2.imencode('.png', img)
As you rightly note in the comments, OpenCV uses BGR ordering so you would need to reverse the order of the colour channels with:
RGBimage = cv2.cvtColor(BGRimage, cv2.COLOR_BGR2RGB)
As an alternative to introducing the OpenCV dependency and its weird channel ordering, you could use PIL/Pillow which uses regular RGB ordering. In that case, you would convert a Numpy array you got from GDAL into a PNG with:
from io import BytesIO
im = ... read from GDAL ...
# Write Numpy array to in-memory PNG
membuf = BytesIO()
Image.fromarray(im).save(membuf, format="png")
... you can now use membuf.getvalue()
Note also, that in general TIFFs may contain float or float64 values that cannot be expressed in an 8-bit JPEG, so you may need to re-scale your data to fit the smaller range.
Upvotes: 2