Palette-mode PNG images

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Lawrence D'Oliveiro

    Palette-mode PNG images

    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.cairographi cs.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.ImageSurf ace.create_for_ data(ThePix,
    cairo.FORMAT_AR GB32, ImageWidth, ImageHeight, ImageWidth * 4)
    # can't find format_stride_f or_width?
    TheDraw = cairo.Context(T hePixSurface)
    ...
    ThePixSurface.f lush() # prior to writing out pixels myself
    TheImage = Image.frombuffe r("RGBA", (ImageWidth, ImageHeight),
    ThePix, "raw", "RGBA", 0, 1)
    TheImage = TheImage.conver t("P")
    TheImage.putpal ette([(0, 0, 0), (255, 255, 255), (0, 255, 0),
    (0, 255, 255)])
    TheImage.save(" png_palette_tes t.png")

    it dies with the following, on the putpalette line:

    Traceback (most recent call last):
    File "./png_palette_tes t", line 41, in <module>
    TheImage.putpal ette([(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 "experiment al". Can this be useful for constraining the pixel
    depth of the output image?

    Thanks for any suggestions.
  • Lawrence D'Oliveiro

    #2
    Re: Palette-mode PNG images

    In message <gfoe0s$11u$1@l ust.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.conver t("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).

    Comment

    Working...