I' am writing a simple PNG parser that can decode PNG data and print raw pixels using matplotlib. I have no problem printing RGB, RGBA and pure greyscale.
import matplotlib.pyplot as plt
import numpy as np
with PngParser() as png:
if png.greyscale:
plt.imshow(np.array(png.reconstructed_data).reshape((png.height, png.width)), cmap='gray', vmin=0, vmax=255)
plt.show()
elif png.greyalhpa:
?
else:
# RGB, RGBA
plt.imshow(np.array(png.reconstructed_data).reshape((png.height, png.width, png.bytesPerPixel)))
plt.show()
Where png.reconstructed_data
is a simple array of pixels.
Unfortunatelly, matplotlib don't explicitly supports this kind of image. Here is a quote from documentation:
Supported array shapes are:
(M, N): an image with scalar data. The values are mapped to colors using normalization and a colormap. See parameters norm, cmap, vmin, vmax.
(M, N, 3): an image with RGB values (0-1 float or 0-255 int).
(M, N, 4): an image with RGBA values (0-1 float or 0-255 int), i.e. including transparency. The first two dimensions (M, N) define the rows and columns of the image.
Our shape would be (M, N, 2) .
Is there any workaround for this problem?
I think turning the grayscale image into an RGB image is the best workaround. You do this by replicating the image in each channel. This will allow you to handle images with different alpha values for each pixel.
height = 10
width = 10
# example image
img = np.random.random(size=(height, width, 2))
# separate out image and alpha channel
grayscale = img[:, :, 0]
alpha = img[:, :, 1]
# repeat grayscale image for each channel
rgb_img = np.dstack((grayscale, grayscale, grayscale, alpha))
fig, ax = plt.subplots(1, 3)
ax[0].imshow(grayscale, cmap='gray')
ax[1].imshow(alpha)
ax[2].imshow(rgb_img)