Python PIL bitmap/png from array with mode=1

前端 未结 4 1167
长发绾君心
长发绾君心 2021-01-19 16:27

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.



        
相关标签:
4条回答
  • 2021-01-19 16:45

    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:

    0 讨论(0)
  • 2021-01-19 17:00

    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')
    
    0 讨论(0)
  • 2021-01-19 17:11

    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')
    
    0 讨论(0)
  • 2021-01-19 17:12

    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')
    
    0 讨论(0)
提交回复
热议问题