Advertisement
Guest User

Bungie ARG image assembly

a guest
Sep 28th, 2016
146
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.54 KB | None | 0 0
  1. from PIL import Image
  2. import os
  3.  
  4. class PuzzlePiece:
  5.     # Save side strings and center image pixels as part of class
  6.     def __init__(self, sides, center, image):
  7.         self.sides = sides
  8.         self.center = center
  9.         self.image = image
  10.         # top, right, bottom, left
  11.         self.matched = [0, 0, 0, 0]
  12.         self.position =[-1,-1]
  13.         self.match_attemps_left = 5
  14.  
  15.  
  16. # Check that RBG are all less than half lit
  17. def is_black(pixel):
  18.     return pixel[0] < 128 and pixel[1] < 128 and pixel[2] < 128
  19.  
  20. # Return _ for none S for Square T for Triangle C for Circle and D for Diamond
  21. def get_shape_letter(subimage):
  22.     pixel_access = subimage.load()
  23.  
  24.     if (not is_black(pixel_access[7,7])):
  25.         # White center so nothing
  26.         return '_'
  27.     elif (not is_black(pixel_access[5,1])):
  28.         # White just left of top center so diamond
  29.         return 'D'
  30.     elif (not is_black(pixel_access[0,14]) and not is_black(pixel_access[1,7])):
  31.         # White bottom left and left center so triangle
  32.         return 'T'
  33.     elif (is_black(pixel_access[1,7]) and not is_black(pixel_access[0,0])):
  34.         # Black left center White left top so Circle
  35.         return 'C'
  36.     else:
  37.         # Only square remains
  38.         return 'S'
  39.  
  40. def get_sides(image):
  41.     top_row = ((35,0,50,15),(57,0,72,15),(79,0,94,15),(101,0,116,15),(123,0,138,15))
  42.     right_row = ((164,35,179,50),(164,57,179,72),(164,79,179,94),(164,101,179,116),(164,123,179,138))
  43.     bottom_row = ((123,164,138,179),(101,164,116,179),(79,164,94,179),(57,164,72,179),(35,164,50,179))
  44.     left_row = ((0,123,15,138),(0,101,15,116),(0,79,15,94),(0,57,15,72),(0,35,15,50))
  45.  
  46.     perimeter = (top_row, right_row, bottom_row, left_row)
  47.  
  48.     img_array = []
  49.     for row in perimeter:
  50.         img_str = ''
  51.  
  52.         for box in row:
  53.             img_str += get_shape_letter(image.crop(box))
  54.  
  55.         img_array.append(img_str)
  56.    
  57.     return img_array
  58.  
  59. def create_pieces_in_dir(directory_name):
  60.     filenames = os.listdir(directory_name)
  61.  
  62.     pieces = []
  63.  
  64.     for filename in filenames:
  65.         puzzle_image = Image.open(directory_name + "\\" + filename)
  66.         pieces.append(PuzzlePiece(get_sides(puzzle_image), puzzle_image.crop((26,26,153,153)), puzzle_image))
  67.  
  68.     return pieces
  69.  
  70. def find_an_adjacent_piece(piece, unplaced_pieces):
  71.     searched = 0
  72.     offset = 128
  73.     if (piece.matched[0] < 3 and not piece.sides[0] == "_____"):
  74.         for x in unplaced_pieces:
  75.             searched += 1
  76.             # Search for a piece above
  77.             if (x.sides[2] == piece.sides[0]):
  78.                 x.position[0] = piece.position[0]
  79.                 x.position[1] = piece.position[1] - (offset * 2)
  80.                 piece.matched[0] += 1
  81.                 x.matched[2] += 1
  82.                 return x
  83.             # Search upper right
  84.             if (x.sides[1] == piece.sides[0]):
  85.                 x.position[0] = piece.position[0] + offset
  86.                 x.position[1] = piece.position[1] - (offset)
  87.                 piece.matched[0] += 1
  88.                 x.matched[1] += 1
  89.                 return x
  90.             # Search upper left
  91.             if (x.sides[3] == piece.sides[0]):
  92.                 x.position[0] = piece.position[0] - offset
  93.                 x.position[1] = piece.position[1] - (offset)
  94.                 piece.matched[0] += 1
  95.                 x.matched[3] += 1
  96.                 return x
  97.     if (piece.matched[1] < 3 and not piece.sides[1] == "_____"):
  98.         for x in unplaced_pieces:
  99.             searched += 1
  100.             # Search for a piece to the right
  101.             if (x.sides[3] == piece.sides[1]):
  102.                 x.position[0] = piece.position[0] + (offset * 2)
  103.                 x.position[1] = piece.position[1]
  104.                 piece.matched[1] += 1
  105.                 x.matched[3] += 1
  106.                 return x
  107.             # Search upper right
  108.             if (x.sides[2] == piece.sides[1]):
  109.                 x.position[0] = piece.position[0] + (offset)
  110.                 x.position[1] = piece.position[1] - offset
  111.                 piece.matched[1] += 1
  112.                 x.matched[2] += 1
  113.                 return x
  114.             # Search lower right
  115.             if (x.sides[0] == piece.sides[1]):
  116.                 x.position[0] = piece.position[0] + (offset)
  117.                 x.position[1] = piece.position[1] + offset
  118.                 piece.matched[1] += 1
  119.                 x.matched[0] += 1
  120.                 return x
  121.            
  122.     if (piece.matched[2] < 3 and not piece.sides[2] == "_____"):
  123.         for x in unplaced_pieces:
  124.             searched += 1
  125.             # Search for a piece below
  126.             if (x.sides[0] == piece.sides[2]):
  127.                 x.position[0] = piece.position[0]
  128.                 x.position[1] = piece.position[1] + (offset * 2)
  129.                 piece.matched[2] += 1
  130.                 x.matched[0] += 1
  131.                 return x
  132.             # Search lower right
  133.             if (x.sides[1] == piece.sides[2]):
  134.                 x.position[0] = piece.position[0] - offset
  135.                 x.position[1] = piece.position[1] + (offset)
  136.                 piece.matched[2] += 1
  137.                 x.matched[1] += 1
  138.                 return x
  139.             # Search lower left
  140.             if (x.sides[3] == piece.sides[2]):
  141.                 x.position[0] = piece.position[0] + offset
  142.                 x.position[1] = piece.position[1] + (offset)
  143.                 piece.matched[2] += 1
  144.                 x.matched[3] += 1
  145.                 return x
  146.     if (piece.matched[3] < 3 and not piece.sides[3] == "_____"):
  147.         for x in unplaced_pieces:
  148.             searched += 1
  149.             # Search for a piece to the left
  150.             if (x.sides[1] == piece.sides[3]):
  151.                 x.position[0] = piece.position[0] - (offset * 2)
  152.                 x.position[1] = piece.position[1]
  153.                 piece.matched[3] += 1
  154.                 x.matched[1] += 1
  155.                 return x
  156.             # Search for a piece to the upper left
  157.             if (x.sides[2] == piece.sides[3]):
  158.                 x.position[0] = piece.position[0] - (offset)
  159.                 x.position[1] = piece.position[1] - offset
  160.                 piece.matched[3] += 1
  161.                 x.matched[1] += 1
  162.                 return x
  163.             # Search for a piece to the lower left
  164.             if (x.sides[0] == piece.sides[3]):
  165.                 x.position[0] = piece.position[0] - (offset)
  166.                 x.position[1] = piece.position[1] + offset
  167.                 piece.matched[3] += 1
  168.                 x.matched[1] += 1
  169.                 return x
  170.  
  171.     print("No matches found after :" + str(searched) + " searches")
  172.     return None
  173.  
  174. all_pieces = create_pieces_in_dir("ARG")
  175. unplaced = all_pieces.copy()
  176. placed_unfinished = []
  177.  
  178. new_image = Image.new("RGB", (20000,20000), (255,255,255))
  179. # Need to see multiple images here to get process started
  180. for piece in all_pieces:
  181.     if (piece.sides[0] == "CDTDC"):
  182.         print("Found first seed")
  183.         #Should be double zero piece lets use it as center
  184.         piece.position = [10000, 10000]
  185.         box = (piece.position[0], piece.position[1])
  186.         new_image.paste(piece.center, box)
  187.         unplaced.remove(piece)
  188.         placed_unfinished.append(piece)
  189.     elif (piece.sides[0] == "DTCTS"):
  190.         print("Found second seed")
  191.         piece.position = [10000 - 128, 10000]
  192.         box = (piece.position[0], piece.position[1])
  193.         new_image.paste(piece.center, box)
  194.         unplaced.remove(piece)
  195.         placed_unfinished.append(piece)
  196.  
  197.  
  198. print ("Starting search current seeds: " + str(len(placed_unfinished)))
  199. total_adjacency_attempts = 0
  200. while len(placed_unfinished) > 0:
  201.     total_adjacency_attempts += 1
  202.     piece = placed_unfinished[0]
  203.     print("Finding adjacent for " + piece.sides[0] + piece.sides[1] + piece.sides[2] + piece.sides[3])
  204.     adjacent = find_an_adjacent_piece(piece, unplaced)
  205.  
  206.     if adjacent != None:
  207.         unplaced.remove(adjacent)
  208.         placed_unfinished.append(adjacent)
  209.         box = (adjacent.position[0], adjacent.position[1])
  210.         new_image.paste(adjacent.center, box)
  211.         print("Placed " + adjacent.sides[0] + adjacent.sides[1] + adjacent.sides[2] + adjacent.sides[3])
  212.     else:
  213.         print("None found for " + piece.sides[0] + piece.sides[1] + piece.sides[2] + piece.sides[3] + " attempts left: " + str(piece.match_attemps_left))
  214.         placed_unfinished.remove(piece)
  215.         piece.match_attemps_left = piece.match_attemps_left - 1
  216.         if (piece.match_attemps_left > 0) :
  217.             placed_unfinished.append(piece)
  218.  
  219.  
  220. print("Total adjacency attempts: "+ str(total_adjacency_attempts))
  221. new_image.save("Assembled.jpg")
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement