segment_image.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. #!/usr/bin/python3
  2. import optparse
  3. import sys
  4. import struct
  5. class Config:
  6. in_file = ""
  7. out_dir = ""
  8. def printi(s):
  9. print("[I] %s" % s)
  10. def parse_commandline():
  11. """ Parse the command line arguments """
  12. parser = optparse.OptionParser(usage = "usage: %prog [options]", \
  13. description = "This program takes a single 2D image and spits "\
  14. "a number of images. Input and output images should be TGA.")
  15. parser.add_option("-i", "--input", dest = "inp",
  16. type = "string", help = "specify the image to split.")
  17. parser.add_option("-o", "--output", dest = "out",
  18. type = "string", help = "the directory of the output images.")
  19. parser.add_option("-s", "--size", dest = "size",
  20. type = "string", metavar="WxH",
  21. help = "size of the splits.")
  22. # Add the default value on each option when printing help
  23. for option in parser.option_list:
  24. if option.default != ("NO", "DEFAULT"):
  25. option.help += (" " if option.help else "") + "[default: %default]"
  26. (options, args) = parser.parse_args()
  27. if not options.inp or not options.out or not options.size:
  28. parser.error("argument is missing")
  29. # Parse the --size
  30. size = [0, 0]
  31. try:
  32. size_strs = options.size.split("x")
  33. size[0] = int(size_strs[0])
  34. size[1] = int(size_strs[1])
  35. except:
  36. parser.error("incorrect --size: %s" % sys.exc_info()[0])
  37. config = Config()
  38. config.in_file = options.inp
  39. config.out_dir = options.out
  40. config.size = size
  41. return config
  42. def split(filename, split_size, out_dir):
  43. """ Load an image """
  44. # Read and check the header
  45. uncompressed_tga_header = struct.pack("BBBBBBBBBBBB", \
  46. 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0)
  47. in_file = open(filename, "rb")
  48. tga_header = in_file.read(12)
  49. if len(tga_header) != 12:
  50. raise Exception("Failed reading TGA header")
  51. if uncompressed_tga_header != tga_header:
  52. raise Exception("Incorrect TGA header")
  53. # Read the size and bpp
  54. header6_buff = in_file.read(6)
  55. if len(header6_buff) != 6:
  56. raise Exception("Failed reading TGA header #2")
  57. header6 = struct.unpack("BBBBBB", header6_buff)
  58. img_width = header6[1] * 256 + header6[0]
  59. img_height = header6[3] * 256 + header6[2]
  60. img_bpp = header6[4];
  61. if img_bpp != 24 and img_bpp != 32:
  62. raise Exception("Unexpected bpp")
  63. # Check split size against the image
  64. if (img_width % split_size[0]) != 0 or (img_height % split_size[1]) != 0:
  65. raise Exception("Sizes of the input image and the split are not " \
  66. "compatible: %d %d vs %d %d"
  67. % (img_width, img_height, split_size[0], split_size[1]))
  68. # Dump the data to an array
  69. pixels = []
  70. for y in range(0, img_height):
  71. pixels.append([])
  72. for x in range(0, img_width):
  73. pixels[y].append([])
  74. if img_bpp == 24:
  75. pixel = in_file.read(3)
  76. pixels[y][x].append(pixel[0])
  77. pixels[y][x].append(pixel[1])
  78. pixels[y][x].append(pixel[2])
  79. else:
  80. pixel = in_file.read(4)
  81. pixels[y][x].append(pixel[0])
  82. pixels[y][x].append(pixel[1])
  83. pixels[y][x].append(pixel[2])
  84. pixels[y][x].append(pixel[3])
  85. # Iterate splits and write them
  86. split_count_x = int(img_width / split_size[0])
  87. split_count_y = int(img_height / split_size[1])
  88. count = 0
  89. for y in range(0, split_count_y):
  90. for x in range(0, split_count_x):
  91. # Open file and write header
  92. out_file = open("%s/out_%02d.tga" % (out_dir, count), "wb")
  93. out_file.write(uncompressed_tga_header)
  94. header2 = struct.pack("BBBBBB", split_size[0] % 256,
  95. int(split_size[0] / 256), split_size[1] % 256,
  96. int(split_size[1] / 256), img_bpp, 0)
  97. out_file.write(header2)
  98. # Iterate split pixels
  99. for sy in range(0, split_size[1]):
  100. for sx in range(0, split_size[0]):
  101. in_x = x * split_size[0] + sx
  102. in_y = y * split_size[1] + sy
  103. if(img_bpp == 24):
  104. pixels_s = struct.pack("BBB", pixels[in_y][in_x][0],
  105. pixels[in_y][in_x][1], pixels[in_y][in_x][2])
  106. else:
  107. pixels_s = struct.pack("BBBB", pixels[in_y][in_x][0],
  108. pixels[in_x][in_y][1], pixels[in_y][in_x][2],
  109. pixels[in_y][in_x][3])
  110. out_file.write(pixels_s)
  111. out_file.close()
  112. count += 1
  113. def main():
  114. """ The main """
  115. config = parse_commandline();
  116. split(config.in_file, config.size, config.out_dir)
  117. printi("Done!")
  118. if __name__ == "__main__":
  119. main()