ppmrotate.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. #!/usr/bin/env python
  2. #
  3. # ppmrotate.py: Rotate PPM images
  4. #
  5. # AUTHOR: Glynn Clements (Python version)
  6. # Vaclav Petras (separate script)
  7. # Earlier Bourne script version by Hamish Bowman,
  8. # http://grasswiki.osgeo.org/wiki/Talk:Color_tables
  9. #
  10. # (C) 2009-2017 by the GRASS Development Team
  11. # This program is free software under the GNU General Public
  12. # License (>=v2). Read the file COPYING that comes with GRASS
  13. # for details.
  14. #
  15. import sys
  16. import os
  17. import atexit
  18. import array
  19. import grass.script as grass
  20. tmp_img = None
  21. height = None
  22. width = None
  23. def cleanup():
  24. if tmp_img:
  25. grass.try_remove(tmp_img)
  26. # def rotate(src, dst):
  27. # grass.call(["convert", "-rotate", "90", src, dst])
  28. def read_ppm(src):
  29. global width, height
  30. fh = open(src, "rb")
  31. text = fh.read()
  32. fh.close()
  33. i = 0
  34. j = text.find('\n', i)
  35. if text[i:j] != 'P6':
  36. raise IOError(text[i:j] + " != P6. Is the file PPM?")
  37. i = j + 1
  38. j = text.find('\n', i)
  39. w, h = text[i:j].split()
  40. width = int(w)
  41. height = int(h)
  42. i = j + 1
  43. j = text.find('\n', i)
  44. maxval = text[i:j]
  45. if int(maxval) != 255:
  46. raise IOError("Max value in image != 255")
  47. i = j + 1
  48. return array.array('B', text[i:])
  49. def write_ppm(dst, data):
  50. w = height
  51. h = width
  52. fh = open(dst, "wb")
  53. fh.write("P6\n%d %d\n%d\n" % (w, h, 255))
  54. data.tofile(fh)
  55. fh.close()
  56. def rotate_ppm(srcd):
  57. dstd = array.array('B', len(srcd) * '\0')
  58. for y in xrange(height):
  59. for x in xrange(width):
  60. for c in xrange(3):
  61. old_pos = (y * width + x) * 3 + c
  62. new_pos = (x * height + (height - 1 - y)) * 3 + c
  63. dstd[new_pos] = srcd[old_pos]
  64. return dstd
  65. def flip_ppm(srcd):
  66. dstd = array.array('B', len(srcd) * '\0')
  67. stride = width * 3
  68. for y in xrange(height):
  69. dy = (height - 1 - y)
  70. dstd[dy * stride:(dy + 1) * stride] = srcd[y * stride:(y + 1) * stride]
  71. return dstd
  72. def ppmtopng(dst, src):
  73. if grass.find_program("g.ppmtopng", '--help'):
  74. grass.run_command('g.ppmtopng', input=src, output=dst, quiet=True)
  75. elif grass.find_program("pnmtopng"):
  76. fh = open(dst, 'wb')
  77. grass.call(["pnmtopng", src], stdout=fh)
  78. fh.close()
  79. elif grass.find_program("convert"):
  80. grass.call(["convert", src, dst])
  81. else:
  82. grass.fatal(_("Cannot find g.ppmtopng, pnmtopng or convert"))
  83. def convert_and_rotate(src, dst, flip=False):
  84. global tmp_img
  85. ppm = read_ppm(src)
  86. if flip:
  87. ppm = flip_ppm(ppm)
  88. ppm = rotate_ppm(ppm)
  89. to_png = False
  90. if dst.lower().endswith('.png'):
  91. to_png = True
  92. if to_png:
  93. tmp_img = grass.tempfile() + ".ppm"
  94. # TODO: clean up the file
  95. else:
  96. tmp_img = dst
  97. write_ppm(tmp_img, ppm)
  98. if to_png:
  99. ppmtopng(dst, tmp_img)
  100. def main():
  101. os.environ['GRASS_OVERWRITE'] = '1'
  102. infile = sys.argv[1]
  103. outfile = sys.argv[2]
  104. convert_and_rotate(infile, outfile, flip=False)
  105. if __name__ == "__main__":
  106. atexit.register(cleanup)
  107. main()