Issue converting a PNG image to a JPG image using PIL

67 views Asked by At

I'm working with X-ray images to build up a neural network, using Pytorch. After some fumbling, I found my main issue was on initial loading of the images. For example, I start with this image: Image of a PNG X-ray

When I try to load it using the ImageFolder, and then DataLoader, it shows as: Failed JPG-PNG conversion, it is just a white box.

After looking through it, I've realised that it is PIL.show() causing the issue (and the internal PNG-JPG conversion), but for the life of me, I can't get it to work. I've tried PIL's .convert() method, with no luck, as well as the steps for copying an alpha mask onto a background as shown here, I've tried changing the background colour to black as well, and nothing, everything just degrades into the white box. I've tried it on other X-rays in the files as well, and it's the same result.

When I tried to convert an image using PNGtoJPG.com, I got this image: PNGtoJPG conversion, incorrectly, but FreeConverter.com worked fine.

I know it must be something with the transparency of the original image, but at this point, I've tried everything I can find, and nothing.

For reference, this is the conversion code I've been testing on:

png = Image.open("0001_1297860395_01_WRI-L1_M014.png") #with the correct file path
    png.load()
    alpha = png.split()[-1]
    alpha= alpha.convert('RGBA')
    background = Image.new("RGB", png.size, (0, 0, 0))
    background.paste(png, alpha)
    background.save('./foo3.jpg', 'JPEG', quality=80)

The images load fine when using cv2, but since I need to use a custom transform, the method needs to convert into cv2.

Any help would be greatly appreciated, I'm at a loss!

2

There are 2 answers

0
jennischofield02 On

The individual image conversion can be handled by using png.point(lambda x: x / 256) This is documented here: https://github.com/python-pillow/Pillow/issues/6765, where it's shown that PIL has issues with PNGs. However, the issue of it not carrying through the neural network is still an issue, but better suited for another question.

1
Mark Setchell On

Your image is a 16-bit, greyscale PNG. You can see that with exiftool:

exiftool -BitDepth -ColorType image.png

Output

Bit Depth                       : 16
Color Type                      : Grayscale

It opens in I mode within PIL, i.e. as 32-bit signed integers:

from PIL import Image

im = Image.open('image.png')
print(im)
print(im.mode)

That prints:

<PIL.PngImagePlugin.PngImageFile image mode=I size=494x727>
I

An easy way to make it 8-bit unsigned is convert to Numpy array, shift right 8 bits and convert to unsigned 8-bit:

# Make "im" into Numpy array, shift right 8 bits, convert to uint8
na = (np.array(im)>>8).astype(np.uint8)

Now you can make that back into PIL Image with:

pilImage = Image.fromarray(na)
pilImage.show()

enter image description here