gooderp18绿色标准版
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
2.5KB

  1. #!C:\odoobuild\WinPy64\python-3.12.3.amd64\python.exe
  2. # pripalpng
  3. """Convert to Palette PNG (without changing colours)"""
  4. import argparse
  5. import collections
  6. # https://docs.python.org/2.7/library/io.html
  7. import io
  8. import string
  9. import zlib
  10. # Local module.
  11. import png
  12. def make_inverse_palette(rows, channels):
  13. """
  14. The inverse palette maps from tuple to palette index.
  15. """
  16. palette = {}
  17. for row in rows:
  18. for pixel in png.group(row, channels):
  19. if pixel in palette:
  20. continue
  21. palette[pixel] = len(palette)
  22. return palette
  23. def palette_convert(out, inp, palette_file):
  24. """
  25. Convert PNG image in `inp` to use a palette, colour type 3,
  26. and write converted image to `out`.
  27. `palette_file` is a file descriptor for the palette to use.
  28. If `palette_file` is None, then `inp` is used as the palette.
  29. """
  30. if palette_file is None:
  31. inp, palette_file = palette_file, inp
  32. reader = png.Reader(file=palette_file)
  33. w, h, rows, info = asRGBorA8(reader)
  34. channels = info["planes"]
  35. if not inp:
  36. rows = list(rows)
  37. palette_map = make_inverse_palette(rows, channels)
  38. if inp:
  39. reader = png.Reader(file=inp)
  40. w, h, rows, info = asRGBorA8(reader)
  41. channels = info["planes"]
  42. # Default for colours not in palette is to use last entry.
  43. last = len(palette_map) - 1
  44. def map_pixel(p):
  45. return palette_map.get(p, last)
  46. def convert_rows():
  47. for row in rows:
  48. yield [map_pixel(p) for p in png.group(row, channels)]
  49. # Make a palette by sorting the pixels according to their index.
  50. palette = sorted(palette_map.keys(), key=palette_map.get)
  51. pal_info = dict(size=info["size"], palette=palette)
  52. w = png.Writer(**pal_info)
  53. w.write(out, convert_rows())
  54. def asRGBorA8(reader):
  55. """
  56. Return (width, height, rows, info) converting to RGB,
  57. or RGBA if original has an alpha channel.
  58. """
  59. _, _, _, info = reader.read()
  60. if info["alpha"]:
  61. return reader.asRGBA8()
  62. else:
  63. return reader.asRGB8()
  64. def main(argv=None):
  65. import sys
  66. import re
  67. if argv is None:
  68. argv = sys.argv
  69. argv = argv[1:]
  70. parser = argparse.ArgumentParser(description=__doc__)
  71. parser.add_argument("--palette", type=png.cli_open)
  72. parser.add_argument(
  73. "input", nargs="?", default="-", type=png.cli_open, metavar="PNG"
  74. )
  75. args = parser.parse_args(argv)
  76. palette_convert(png.binary_stdout(), args.input, args.palette)
  77. if __name__ == "__main__":
  78. main()
上海开阖软件有限公司 沪ICP备12045867号-1