convert.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import array
  2. import random
  3. import Image
  4. from gameduino2.registers import *
  5. from gameduino2.imbytes import imbytes
  6. def convert(im, dither = False, fmt = ARGB1555):
  7. """ Convert PIL image to GD2 format, optionally dithering"""
  8. im = im.convert({
  9. ARGB1555 : "RGBA",
  10. L1 : "L",
  11. L2 : "L",
  12. L4 : "L",
  13. L8 : "L",
  14. RGB332 : "RGB",
  15. ARGB2 : "RGBA",
  16. ARGB4 : "RGBA",
  17. RGB565 : "RGB",
  18. PALETTED : "RGB"}[fmt])
  19. imdata = []
  20. colorfmts = {
  21. ARGB1555 : (1, 5, 5, 5),
  22. RGB332 : (0, 3, 3, 2),
  23. ARGB2 : (2, 2, 2, 2),
  24. ARGB4 : (4, 4, 4, 4),
  25. RGB565 : (0, 5, 6, 5)}
  26. if dither:
  27. rnd = random.Random()
  28. rnd.seed(0)
  29. if fmt in colorfmts:
  30. im = im.convert("RGBA")
  31. (asz,rsz,gsz,bsz) = colorfmts[fmt]
  32. totalsz = sum((asz,rsz,gsz,bsz))
  33. assert totalsz in (8,16)
  34. for y in range(im.size[1]):
  35. for x in range(im.size[0]):
  36. (r,g,b,a) = im.getpixel((x,y))
  37. if dither:
  38. a = min(255, a + rnd.randrange(256>>asz))
  39. r = min(255, r + rnd.randrange(256>>rsz))
  40. g = min(255, g + rnd.randrange(256>>gsz))
  41. b = min(255, b + rnd.randrange(256>>bsz))
  42. binary = ((a >> (8-asz)) << (bsz+gsz+rsz)) | ((r >> (8-rsz)) << (gsz+bsz)) | ((g >> (8-gsz)) << (bsz)) | (b >> (8-bsz))
  43. imdata.append(binary)
  44. fmtchr = {8:'B',16:'H'}[totalsz]
  45. data = array.array('B', array.array(fmtchr, imdata).tostring())
  46. elif fmt == PALETTED:
  47. im = im.convert("P", palette = Image.ADAPTIVE)
  48. lut = im.resize((256, 1))
  49. lut.putdata(range(256))
  50. palstr = lut.convert("RGBA").tobytes()
  51. rgba = zip(*(array.array('B', palstr[i::4]) for i in range(4)))
  52. data = imbytes(im)
  53. elif fmt == L8:
  54. data = imbytes(im)
  55. elif fmt == L4:
  56. b0 = imbytes(im)[::2]
  57. b1 = imbytes(im)[1::2]
  58. def to15(c):
  59. if dither:
  60. dc = min(255, c + rnd.randrange(16))
  61. else:
  62. dc = c
  63. return int((15. * dc / 255))
  64. data = array.array('B', [(16 * to15(l) + to15(r)) for (l,r) in zip(b0, b1)])
  65. elif fmt == L2:
  66. b0 = imbytes(im)[::4]
  67. b1 = imbytes(im)[1::4]
  68. b2 = imbytes(im)[2::4]
  69. b3 = imbytes(im)[3::4]
  70. def to3(c):
  71. if dither:
  72. dc = min(255, c + rnd.randrange(64))
  73. else:
  74. dc = c
  75. return int((3. * dc / 255))
  76. data = array.array('B', [(64 * to3(a) + 16 * to3(b) + 4 * to3(c) + to3(d)) for (a,b,c,d) in zip(b0, b1, b2, b3)])
  77. elif fmt == L1:
  78. if dither:
  79. im = im.convert("1", dither=Image.FLOYDSTEINBERG)
  80. else:
  81. im = im.convert("1", dither=Image.NONE)
  82. data = imbytes(im)
  83. else:
  84. assert 0, "Bad format %r" % fmt
  85. return (im.size, data)