By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
443,271 Members | 1,722 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 443,271 IT Pros & Developers. It's quick & easy.

Palette-mode PNG images

P: n/a
I'm trying to create PNG files to use in menus for authoring DVDs. As you
may know, these menus are only allowed to have limited numbers of colours.

Ideally I'd like to create a PNG file with just two bits per pixel, with
four colour-table entries of my choice. I'm using PyCairo
<http://www.cairographics.org/pycairo/to do the drawing, but that doesn't
seem to support colour-table images as far as I can tell. So I'm trying to
figure out how to use PIL
<http://www.pythonware.com/library/pil/handbook/index.htmto save the
images to PNG files with a suitable format.

However, it looks like PIL wants 256 colour-table entries. When I try to
pass fewer, e.g.

ThePix = array.array("B", '\0' * ImageWidth * ImageHeight * 4)
ThePixSurface = cairo.ImageSurface.create_for_data(ThePix,
cairo.FORMAT_ARGB32, ImageWidth, ImageHeight, ImageWidth * 4)
# can't find format_stride_for_width?
TheDraw = cairo.Context(ThePixSurface)
...
ThePixSurface.flush() # prior to writing out pixels myself
TheImage = Image.frombuffer("RGBA", (ImageWidth, ImageHeight),
ThePix, "raw", "RGBA", 0, 1)
TheImage = TheImage.convert("P")
TheImage.putpalette([(0, 0, 0), (255, 255, 255), (0, 255, 0),
(0, 255, 255)])
TheImage.save("png_palette_test.png")

it dies with the following, on the putpalette line:

Traceback (most recent call last):
File "./png_palette_test", line 41, in <module>
TheImage.putpalette([(0, 0, 0), (255, 255, 255), (0, 255, 0),
(0, 255, 255)])
File "/usr/lib64/python2.5/site-packages/PIL/Image.py", line 1205,
in putpalette
data = string.join(map(chr, data), "")
TypeError: an integer is required

Cairo also supports FORMAT_A8 and FORMAT_A1 images--should I be using the
latter, perhaps?

Also I see that the PIL PNG encoder/decoder supports a "bits" output option
<http://www.pythonware.com/library/pil/handbook/format-png.htmwhich is
marked as "experimental". Can this be useful for constraining the pixel
depth of the output image?

Thanks for any suggestions.
Nov 16 '08 #1
Share this Question
Share on Google+
1 Reply


P: n/a
In message <gf**********@lust.ihug.co.nz>, I wrote:
data = string.join(map(chr, data), "")
TypeError: an integer is required
OK, I figured that out, the putpalette call wants a sequence of integers
being (R, G, B, R, G, B ...), not a sequence of sequences ((R, G, B), (R,
G, B)...).
TheImage = TheImage.convert("P")
This gives me 8 bits per pixel, which is too many. And this automatically
converts the image using a default palette; a subsequent putpalette call
replaces the palette, but doesn't change the pixels, so the colours come
out wrong.

I can also do Image.convert("1"), which gives me a 1-bit-per-pixel image,
but that only allows a fixed colour table (black and white), no option to
change either entry.
Also I see that the PIL PNG encoder/decoder supports a "bits" output
option ...
Hmm, interesting, but adding either "bits = 2" or "bits = 1" to the save
call just seems to turn the image all black. Examination with
ImageMagick's "identify" command shows that the default colour table ramp
has been stair-stepped, with all components turned into multiples of 51 (=
255 / 5).

Nov 19 '08 #2

This discussion thread is closed

Replies have been disabled for this discussion.