SHARE
TWEET

Image Rearrannger

a guest Jul 11th, 2014 1,044 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
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top