Playing with PIL (and numpy) for the first time ever. I was trying to generate a black and white checkerboard image through mode=\'1\', but it doesn\'t work.
As pointed out in the other answer, you are running into a Pillow bug, and the accepted answer is fine.
As an alternative to PIL/Pillow, you could use pypng, or you could use numpngw
, a library that I wrote to write NumPy arrays to PNG and animated PNG files. It is on github: https://github.com/WarrenWeckesser/numpngw (It has all the boilerplate files of a python package, but the essential file is numpngw.py
.) It is also on PyPI.
Here's an example of using numpngw.write_png
to create the checkerboard image. This creates an image with bit depth 1:
In [10]: g
Out[10]:
array([[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1],
[1, 0, 1, 0, 1, 0, 1, 0],
[0, 1, 0, 1, 0, 1, 0, 1]], dtype=uint8)
In [11]: import numpngw
In [12]: numpngw.write_png('checkerboard.png', g, bitdepth=1)
Here's the image it creates:
There seem to be issues when using mode 1
with numpy arrays. As a workaround you could use mode L
and convert to mode 1
before saving. The below snippet produces the expected checkerboard.
from PIL import Image
import numpy as np
if __name__ == '__main__':
g = np.asarray(dtype=np.dtype('uint8'), a=[
[0, 255, 0, 255, 0, 255, 0, 255],
[255, 0, 255, 0, 255, 0, 255, 0],
[0, 255, 0, 255, 0, 255, 0, 255],
[255, 0, 255, 0, 255, 0, 255, 0],
[0, 255, 0, 255, 0, 255, 0, 255],
[255, 0, 255, 0, 255, 0, 255, 0],
[0, 255, 0, 255, 0, 255, 0, 255],
[255, 0, 255, 0, 255, 0, 255, 0]
])
print(g)
i = Image.fromarray(g, mode='L').convert('1')
i.save('checker.png')
Just use PyPNG:
import numpy as np
if __name__ == '__main__':
g = np.asarray(dtype=np.dtype('uint8'), a=[
[0, 1, 0, 1, 0, 1, 0, 1, ],
[1, 0, 1, 0, 1, 0, 1, 0, ],
[0, 1, 0, 1, 0, 1, 0, 1, ],
[1, 0, 1, 0, 1, 0, 1, 0, ],
[0, 1, 0, 1, 0, 1, 0, 1, ],
[1, 0, 1, 0, 1, 0, 1, 0, ],
[0, 1, 0, 1, 0, 1, 0, 1, ],
[1, 0, 1, 0, 1, 0, 1, 0, ],
])
print(g)
import png
i = png.from_array(g, mode='L;1')
i.save('checker.png')
I think it is a bug. It has been reported on Github. Although some fix has been commited, it seems that it didn't resolve this problem. Everything works fine if you use mode "L" and then convert image to mode "1", so you can use it as a workaround for your problem:
from PIL import Image
import numpy as np
if __name__ == '__main__':
g = np.asarray(dtype=np.dtype('uint8'), a=[
[0, 255, 0, 255, 0, 255, 0, 255, ],
[255, 0, 255, 0, 255, 0, 255, 0, ],
[0, 255, 0, 255, 0, 255, 0, 255, ],
[255, 0, 255, 0, 255, 0, 255, 0, ],
[0, 255, 0, 255, 0, 255, 0, 255, ],
[255, 0, 255, 0, 255, 0, 255, 0, ],
[0, 255, 0, 255, 0, 255, 0, 255, ],
[255, 0, 255, 0, 255, 0, 255, 0, ],
])
print(g)
i = Image.fromarray(g, mode='L').convert('1')
i.save('checker.png')