6

I am trying to draw a simple 256x256 pixel RGBA square using python's png module.

I'd like to use the png.Writer function and I imagine I'd have to draw it out using the write() method. I have not had any luck however! I don't have faith in my current code so I'm willing to take suggestions from scratch

I prefer not to use the PIL if possible.

Any suggestions?

4

2 回答 2

8

I think the format is what may be affecting you, it seems that png has three formats ...

>>> help(png)
    Boxed row flat pixel::

     list([R,G,B, R,G,B, R,G,B],
       [R,G,B, R,G,B, R,G,B])

    Flat row flat pixel::    

      [R,G,B, R,G,B, R,G,B,
       R,G,B, R,G,B, R,G,B]

    Boxed row boxed pixel::

      list([ (R,G,B), (R,G,B), (R,G,B) ],
           [ (R,G,B), (R,G,B), (R,G,B) ])

The alpha being appended to the end of each RGB sequence.

 write(self, outfile, rows)
 |      Write a PNG image to the output file.  `rows` should be
 |      an iterable that yields each row in boxed row flat pixel format.
 |      The rows should be the rows of the original image, so there
 |      should be ``self.height`` rows of ``self.width * self.planes`` values.
 |      If `interlace` is specified (when creating the instance), then
 |      an interlaced PNG file will be written.  Supply the rows in the
 |      normal image order; the interlacing is carried out internally.

note the each row in boxed row flat pixel format.

heres a quick example that draws a white square.

>>> rows = [[255 for element in xrange(4) for number_of_pixles in xrange(256)] for number_of_rows in xrange(256)]
>>> import numpy # Using numpy is much faster
>>> rows = numpy.zeros((256, 256 * 4), dtype = 'int')
>>> rows[:] = 255
>>> png_writer = png.Writer(width = 256, height = 256, alpha = 'RGBA')
>>> png_writer.write(open('white_panel.png', 'wb'), rows)

note that Writer can also use the other 2 formats which maybe easier to use.

     |  write_array(self, outfile, pixels)
     |      Write an array in flat row flat pixel format as a PNG file on
     |      the output file.  See also :meth:`write` method.
     |  
     |  write_packed(self, outfile, rows)
     |      Write PNG file to `outfile`.  The pixel data comes from `rows`
     |      which should be in boxed row packed format.  Each row should be
     |      a sequence of packed bytes.

Try to use numpy its much faster and easier when dealing with matrix operations, images can be represented as matrices.

good luck.

If you want to print colors then you would need to calculate the RGB values for that color, for example the color red is (255, 0, 0, 255).

import png
import numpy
rows = numpy.zeros((256, 256, 4), dtype = 'int') # eassier format to deal with each individual pixel
rows[:, :] = [255, 0, 0, 255] # Setting the color red for each pixel
rows[10:40, 10:40] = [0, 255, 255, 255] #  filled squared starting at (10,10) to (40,40)
locs = numpy.indices(rows.shape[0:2])
rows[(locs[0] - 80)**2 + (locs[1] - 80)**2 <= 20**2] = [255, 255, 0, 255] # yellow filled circle, with center at (80, 80) and radius 20
png_writer = png.Writer(width = 256, height = 256, alpha = 'RGBA') # create writer
png_writer.write(open('colors_panel.png', 'wb'), rows.reshape(rows.shape[0], rows.shape[1]*rows.shape[2])) # we have to reshape or flatten the most inner arrays so write can properly understand the format
于 2012-06-25T22:46:51.113 回答
0

这是一个创建全红色 png 文件的简单示例:

import png

width = 255
height = 255
img = []
for y in range(height):
    row = ()
    for x in range(width):
        row = row + (255, 0, 0, 255)
    img.append(row)
with open('red.png', 'wb') as f:
    w = png.Writer(width, height, greyscale=False, alpha='RGBA')
    w.write(f, img)
于 2021-05-16T10:49:50.023 回答