Guest User

Image Rearrannger

a guest
Jul 11th, 2014
1,286
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import os
  2. import sys
  3. import Image
  4.  
  5. #returns dict of (color -> pixel list) pairs
  6. def imgColorLocs(img):
  7.     data = img.load()
  8.     colorLocs = {}
  9.     for x in range(img.size[0]):
  10.         for y in range(img.size[1]):
  11.             color = data[x, y]
  12.             if color in colorLocs:
  13.                 colorLocs[color].append((x, y))
  14.             else:
  15.                 colorLocs[color] = [(x, y)]
  16.     return colorLocs
  17.  
  18. #returns a tuple of 3 ordered pairs: the canvas size, the src position, and the dst position
  19. def getCanvasDims(src, dst, inPlace):
  20.     w = max(src.size[0], dst.size[0])
  21.     h = max(src.size[1], dst.size[1])
  22.     offset = lambda dim, canvasDim: int(0.5 * (canvasDim - dim))
  23.     srcPos = offset(src.size[0], w), offset(src.size[1], h)
  24.     dstPos = offset(dst.size[0], w), offset(dst.size[1], h)
  25.     if not inPlace:
  26.         dstPos = dstPos[0] + w, dstPos[1]
  27.         w *= 2
  28.     return (w, h), srcPos, dstPos
  29.  
  30. def dist(loc1, loc2):
  31.     return ((loc2[0] - loc1[0])**2 + (loc2[1] - loc1[1])**2)**0.5
  32.  
  33. #returns list of tuples of the closest color ((srcx, srcy), (dstx, dsty), (r, g, b))
  34. def getMappings(src, srcOffset, dst, dstOffset):
  35.     add = lambda t1, t2: (t1[0] + t2[0], t1[1] + t2[1])
  36.     srcColorLocs = imgColorLocs(src)
  37.     dstColorLocs = imgColorLocs(dst)
  38.     mappings = []
  39.     for color in srcColorLocs:
  40.         srcLocs = srcColorLocs[color]
  41.         dstLocs = dstColorLocs[color]
  42.         for srcLoc in srcLocs:
  43.             minDist = dist((0, 0), src.size)
  44.             index = 0
  45.             for i, dstLoc in enumerate(dstLocs):
  46.                 d = dist(srcLoc, dstLoc)
  47.                 if d < minDist:
  48.                     minDist = d
  49.                     index = i
  50.             dstLoc = dstLocs.pop(index)
  51.             mappings.append((add(srcLoc, srcOffset), add(dstLoc, dstOffset), color))
  52.     return mappings
  53.  
  54. def makeLinearMapper(steps):
  55.     def linearMapper(startLoc, stopLoc, step):
  56.         m = lambda start, stop: (stop - start) * step / steps + start
  57.         return (m(startLoc[0], stopLoc[0]), m(startLoc[1], stopLoc[1]))
  58.     return linearMapper
  59.  
  60. #src is the filename of the palette image that will be rearranged
  61. #dst if the filename of the final rearranged palette
  62. #steps is the number of increments between src and dst, steps + 1 images are generated in total
  63. #folder is the location all intermediate images will save to
  64. #bg is the background of the intermediate images
  65. #when cycle is true a duplicate set of images will be made with higher numbers in reverse order, useful for making continuous looking gifs
  66. #when inPlace is true the transforming images are drawn on top of one another
  67. #when drawSrc is true the src image is drawn below the moving pixels
  68. #when drawDst is true the dst image is drawn below the moving pixels
  69. def go(src, dst, steps, folder='output', bg='black', cycle=False, inPlace=True, drawSrc=False, drawDst=False):
  70.     print 'STARTING'
  71.  
  72.     def saveImg(img, number):
  73.         img.save('%s/img_%04d.png' % (folder, number))
  74.  
  75.     src = Image.open(src).convert('RGB')
  76.     dst = Image.open(dst).convert('RGB')
  77.     if sorted(src.getdata()) != sorted(dst.getdata()):
  78.         print 'INCOMPATIBLE IMAGES'
  79.         sys.exit()
  80.  
  81.     if not os.path.exists(folder):
  82.         os.makedirs(folder)
  83.  
  84.     canvasDims = getCanvasDims(src, dst, inPlace)
  85.     mappings = getMappings(src, canvasDims[1], dst, canvasDims[2])
  86.     mapper = makeLinearMapper(steps)
  87.  
  88.     for step in range(steps + 1):
  89.         print 'Generating image %d of %d' % (step + 1, steps + 1)
  90.  
  91.         img = Image.new('RGB', canvasDims[0], bg)
  92.         if drawSrc:
  93.             img.paste(src, canvasDims[1])
  94.         if drawDst:
  95.             img.paste(dst, canvasDims[2])
  96.         data = img.load()
  97.         for startLoc, stopLoc, color in mappings:
  98.             x, y = mapper(startLoc, stopLoc, step)
  99.             data[x, y] = color
  100.         saveImg(img, step)
  101.  
  102.         if cycle and step != 0 and step != steps:
  103.             saveImg(img, 2 * steps - step)
  104.  
  105.     print 'DONE'
  106.  
  107. go('src.png', 'dst.png', 19)
RAW Paste Data