|
- #!C:\odoobuild\WinPy64\python-3.12.3.amd64\python.exe
- # pripalpng
-
-
- """Convert to Palette PNG (without changing colours)"""
-
- import argparse
- import collections
-
- # https://docs.python.org/2.7/library/io.html
- import io
- import string
- import zlib
-
- # Local module.
- import png
-
-
- def make_inverse_palette(rows, channels):
- """
- The inverse palette maps from tuple to palette index.
- """
-
- palette = {}
-
- for row in rows:
- for pixel in png.group(row, channels):
- if pixel in palette:
- continue
- palette[pixel] = len(palette)
- return palette
-
-
- def palette_convert(out, inp, palette_file):
- """
- Convert PNG image in `inp` to use a palette, colour type 3,
- and write converted image to `out`.
-
- `palette_file` is a file descriptor for the palette to use.
-
- If `palette_file` is None, then `inp` is used as the palette.
- """
-
- if palette_file is None:
- inp, palette_file = palette_file, inp
-
- reader = png.Reader(file=palette_file)
- w, h, rows, info = asRGBorA8(reader)
- channels = info["planes"]
- if not inp:
- rows = list(rows)
-
- palette_map = make_inverse_palette(rows, channels)
-
- if inp:
- reader = png.Reader(file=inp)
- w, h, rows, info = asRGBorA8(reader)
- channels = info["planes"]
-
- # Default for colours not in palette is to use last entry.
- last = len(palette_map) - 1
-
- def map_pixel(p):
- return palette_map.get(p, last)
-
- def convert_rows():
- for row in rows:
- yield [map_pixel(p) for p in png.group(row, channels)]
-
- # Make a palette by sorting the pixels according to their index.
- palette = sorted(palette_map.keys(), key=palette_map.get)
- pal_info = dict(size=info["size"], palette=palette)
-
- w = png.Writer(**pal_info)
- w.write(out, convert_rows())
-
-
- def asRGBorA8(reader):
- """
- Return (width, height, rows, info) converting to RGB,
- or RGBA if original has an alpha channel.
- """
- _, _, _, info = reader.read()
- if info["alpha"]:
- return reader.asRGBA8()
- else:
- return reader.asRGB8()
-
-
- def main(argv=None):
- import sys
- import re
-
- if argv is None:
- argv = sys.argv
-
- argv = argv[1:]
-
- parser = argparse.ArgumentParser(description=__doc__)
- parser.add_argument("--palette", type=png.cli_open)
- parser.add_argument(
- "input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
- )
-
- args = parser.parse_args(argv)
-
- palette_convert(png.binary_stdout(), args.input, args.palette)
-
-
- if __name__ == "__main__":
- main()
|