78

I am taking a jpg image and using numpy's fft2 to create/save a new image. However it throws this error

"IOError: cannot write mode F as JPEG" 

Is there an issue with CMYK and JPEG files in PIL???

p = Image.open('kibera.jpg')
bw_p = p.convert('L')
array_p = numpy.asarray(bw_p)
fft_p = abs(numpy.fft.rfft2(array_p))
new_p = Image.fromarray(fft_p)
new_p.save('kibera0.jpg')
new_p.histogram()
Chillar Anand
  • 27,936
  • 9
  • 119
  • 136
JHHP
  • 781
  • 1
  • 5
  • 4

5 Answers5

80

Try convert the image to RGB:

...
new_p = Image.fromarray(fft_p)
if new_p.mode != 'RGB':
    new_p = new_p.convert('RGB')
...
semente
  • 7,265
  • 3
  • 34
  • 35
50

Semente's answer is right for color images For grayscale images you can use below:-

new_p = Image.fromarray(fft_p)
new_p = new_p.convert("L")

If you use new_p = new_p.convert('RGB') for a grayscale image then the image will still have 24 bit depth instead of 8 bit and would occupy thrice the size on hard disk and it wont be a true grayscale image.

  • 2
    More info on convert here: https://pillow.readthedocs.io/en/stable/reference/Image.html#PIL.Image.Image.convert – Aaron Swan Apr 06 '19 at 00:34
19

I think it may be that your fft_p array is in float type and the image should have every pixel in the format 0-255 (which is uint8), so maybe you can try doing this before creating the image from array:

fft_p = fft_p.astype(np.uint8)
new_p = Image.fromarray(fft_p)

But be aware that every element in the fft_p array should be in the 0-255 range, so maybe you would need to do some processing to that before to get the desired results, for example if you every element is a float between 0 and 1 you can multiply them by 255.

xhenryx14
  • 704
  • 6
  • 10
  • This is the true answer because it does not changing the actual value of the numpy array (just the type format). – Muhammad Yasirroni Jun 30 '21 at 00:49
  • Very useful hint that it should be `uint8`. I was trying to preview the mnist grayscale data on jupyter and encountered this issue. The correct code should be like `Image.fromarray((mnist_images[0]*255).astype(np.uint8)) – Kassian Sun Jul 16 '21 at 06:52
0
def save_img(img, path):

    img = Image.fromarray(img)

    img.save(path)

raise OSError(f"cannot write mode {mode} as PNG") from e

OSError: cannot write mode F as PNG

Here the meaning of mode F is the floating point value in the image. So please convert the floating point image to the uint8 image before saving.

image.astype(np.uint8)
Tyler2P
  • 2,324
  • 26
  • 22
  • 31
0

If you are working with PyTorch

import torchvision.transforms as T
    
        
transform=T.ToPILImage()
imt=transform(img)
Aneesh R P
  • 69
  • 3
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Oct 27 '22 at 07:27