10

I want to write a single channel png image from a numpy array in python? In Matlab that would be

A = randi(100,100,255)
imwrite(uint8(A),'myFilename.png','png');

I saw exampels using from PIL import Image and Image.fromarray() but they are for jpeg and 3-channel pngs only it appears...

I already found the solution using opencv, I will post it here. Hopefully it will shorten someone else's searching...

3
  • 1
    docs.scipy.org/doc/scipy-0.14.0/reference/generated/… Commented Feb 22, 2017 at 14:10
  • that solution would be for rgb, but I need single channel Commented Feb 22, 2017 at 16:04
  • If you hand it a single channel, it writes a single channel. See the first example, it's a bw gradient. Commented Feb 23, 2017 at 13:12

3 Answers 3

8

Here is a solution using opencv / cv2

import cv2
myImg = np.random.randint(255, size=(200, 400)) # create a random image
cv2.imwrite('myImage.png',myImg)
Sign up to request clarification or add additional context in comments.

1 Comment

warning: cv2.imwrite() uses BGR as the default order of columns, and so can mess with the intended color of the image
6

PIL's Image.fromarray() automatically determines the mode to use from the datatype of the passed numpy array, for example for an 8-bit greyscale image you can use:

from PIL import Image
import numpy as np

data = np.random.randint(256, size=(100, 100), dtype=np.uint8)
img = Image.fromarray(data)  # uses mode='L'

This however only works if your array uses a compatible datatype, if you simply use data = np.random.randint(256, size=(100, 100)) that can result in a int64 array (typestr <i8), which PIL can't handle.

You can also specify a different mode, e.g. to interpret a 32bit array as an RGB image:

data = np.random.randint(2**32, size=(100, 100), dtype=np.uint32)
img = Image.fromarray(data, mode='RGB')

Internally Image.fromarray() simply tries to guess the correct mode and size and then invokes Image.frombuffer().

The image can then be saved as any format PIL can handle e.g: img.save('filename.png')

Comments

1

You might want not to utilise OpenCV for simple image manipulation. As suggested, use PIL:

im = Image.fromarray(arr)
im.save("output.png", "PNG")

Have you tried this? What has failed here that led you to concluding that this is JPEG-only?

2 Comments

this saves a 3 channel pnd, but I need a 1 channel png file
Then you need your array to be of type uint8. im = Image.fromarray(arr.astype(numpy.uint8))

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.