2

I am trying to edit this image:

However, when I run

im = Image.open(filename)
im.show()

it outputs a completely plain white image of the same size. Why is Image.open() not working? How can I fix this? Is there another library I can use to get non-255 pixel values (the correct pixel array)?

Thanks, Vinny

Vinny Jacobsen
  • 127
  • 2
  • 9
  • what library are you using for Image ? what is the image format ? – Cyril Jouve Aug 29 '20 at 20:23
  • `from PIL import Image`, and the image is a png – Vinny Jacobsen Aug 29 '20 at 20:27
  • Can reproduce the problem. Image shows as just white. Works fine with other pngs. Opening the image directly with ImageMagick (which `show` uses) works correctly. `im.save(new_name)` saves the image properly, too, but for some reason the `tmp` image created for `show` is just white. – tobias_k Aug 29 '20 at 20:32
  • Ok thanks @tobias_k. How would you recommend I go about getting the pixel values for this image then? Any other libraries I can use? – Vinny Jacobsen Aug 29 '20 at 20:49
  • 1
    It seems like `getpixel`, `putpixel` and `save` work just fine, so you can still edit/enhance/whatever the picture and view the result, just not using `show`. – tobias_k Aug 29 '20 at 20:54
  • The image is 16-bits. Do you need any specia flagl in PIL to read 16-bit image? See https://stackoverflow.com/questions/32622658/read-16-bit-png-image-file-using-python – fmw42 Aug 29 '20 at 21:32

2 Answers2

2

Image.open actually seems to work fine, as does getpixel, putpixel and save, so you can still load, edit and save the image.

The problem seems to be that the temp file the image is saved in for show is just plain white, so the image viewer shows just a white image. Your original image is 16 bit grayscale, but the temp image is saved as an 8 bit grayscale.

My current theory is that there might actually be a bug in show where a 16 bit grayscale image is just "converted" to 8 bit grayscale by capping all pixel values to 255, resulting in an all-white temp image since all the pixels values in the original are above 30,000.

If you set a pixel to a value below 255 before calling show, that pixel shows correctly. Thus, assuming you want to enhance the contrast in the picture, you can open the picture, map the values to a range from 0 to 255 (e.g. using numpy), and then use show.

from PIL import Image
import numpy as np
arr = np.array(Image.open("Rt5Ov.png"))
arr = (arr - arr.min()) * 255 // (arr.max() - arr.min())
img = Image.fromarray(arr.astype("uint8"))
img.show()

But as said before, since save seems to work as it should, you could also keep the 16 bit grayscale depth and just save the edited image instead of using show.

tobias_k
  • 81,265
  • 12
  • 120
  • 179
  • 1
    Addendum: It seems like PIL only has modes for 8 bit (`L`) and 32 bit (`I`) grayscale images, so I tried saving it as 32 bit grayscale, but that did not work (that format does not seem to exist or be supported). Saving as 16 bit grayscale with alpha seemed to work at first, but was opened as RGBA by PIL with just 8 bit per channel... – tobias_k Aug 29 '20 at 22:15
  • 1
    [This answer](https://stackoverflow.com/a/57627715/1639625) shows how to get the image opened as `I;16`, but `show`still shows just white. – tobias_k Aug 29 '20 at 22:20
1

you can use openCV library for loading images.

import cv2
img = cv2.imread('image file')
plt.show(img)
farnaz jazayeri
  • 625
  • 6
  • 7
  • This reads the file as an 8 bit RGB image, and even with `cv2.IMREAD_GRAYSCALE` it only ready an 8 bit grayscale image, which probably won't do it given the low contrast (all pixel values between 124 and 139). Also, `plt.show(img)` does not seem to do anything. – tobias_k Aug 30 '20 at 12:32