Created
March 2, 2011 12:27
-
-
Save linus/850851 to your computer and use it in GitHub Desktop.
Så gjorde vi Rättviseförmedlingens pressbild
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Return the Euclidean distance between color_a and color_b. | |
# We optimize a little and don't calculate the square root of the distance. | |
# The sum of the squares of deltas is good enough. | |
def color_distance(color_a, color_b): | |
delta_red = color_a[0] - color_b[0] | |
delta_green = color_a[1] - color_b[1] | |
delta_blue = color_a[2] - color_b[2] | |
return delta_red * delta_red + delta_green * delta_green + delta_blue * delta_blue |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
TILE_SIZE = 50 | |
# Return a list of tuples with (image, color) for each image in profile_pictures | |
def profile_colors(profile_pictures): | |
colors = [] | |
for picture in profile_pictures: | |
image = Image.open(picture) | |
colors.append(image, get_color(image)) | |
return colors | |
# Main function. Takes the original image and a list of profile pictures, and returns the finished mosaic | |
def create_mosaic(original_image, profile_pictures): | |
# Calculate the width and height of the scaled image, where each profile picture maps to a pixel in the original image | |
width, height = image_ratio(original_image, len(profile_pictures)) | |
# Get the pixel values of the scaled image | |
pixels = get_pixels(original_image, (width, height)) | |
# Get a random list of (x, y) values for each pixel in the image | |
slices = random_slices(width, height) | |
# Get a list of tuples with (image, color) for each profile picture | |
tiles = profile_colors(profile_pictures) | |
# Create a new image for our mosaic | |
mosaic = Image.new("RGB", (width * TILE_SIZE, height * TILE_SIZE)) | |
# Go through all random pixels | |
while(len(slices) > 0): | |
# Take one pixel | |
(x, y) = slices.pop() | |
# Find the nearest profile picture | |
picture = find_nearest(pixels[x, y], tiles) | |
# Calculate where we should paste it into the mosaic | |
position = (x * TILE_SIZE, y * TILE_SIZE) | |
# Resize the picture to the specified size and paste it in the right position (TILE_SIZE is actually the same size as the profile pictures here, but this makes it easy for us to specify any other size for each tile in the mosaic) | |
mosaic.paste(picture.resize((TILE_SIZE, TILE_SIZE), Image.ANTIALIAS), position) | |
return mosaic |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Finds the nearest color in tiles, and removes that tile since it is used | |
# A tile is a tuple (a pair) of image and the color of that image - (image, color) | |
def find_nearest(color, tiles): | |
try: | |
# Parameter key to sort() takes a function, which calculates the color distance between that tile's color (tile[1]) and the specified color | |
tiles.sort(key=lambda tile: color_distance(tile[1], color)) | |
# pop() removes that tile from the list, so we don't use it again, and [0] is the actual image | |
return tiles.pop()[0] | |
except: | |
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from PIL import Image | |
# Resize an image to 1 pixel and return the color of that pixel | |
def get_color(img): | |
try: | |
return img.convert("RGB").resize((1, 1), Image.ANTIALIAS).getpixel((0, 0)) | |
except IOError: | |
# If something went wrong, return None | |
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from random import shuffle | |
def random_slices(width, height): | |
slices = [(x, y) for x in range(width) for y in range(height)] | |
shuffle(slices) | |
return slices |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"id":"361481469749", | |
"name":"R\u00e4ttvisef\u00f6rmedlingen", | |
"picture":"http:\/\/profile.ak.fbcdn.net\/hprofile-ak-snc4\/23305_361481469749_9327_s.jpg", | |
"link":"http:\/\/www.facebook.com\/rattviseformedlingen", | |
"category":"Local business", | |
"website":"www.rattviseformedlingen.se", | |
"username":"rattviseformedlingen", | |
"description":"www.rattviseformedlingen.se", | |
"location":{ | |
"city":"Stockholm", | |
"country":"Sweden", | |
"zip":"rattvisa\u0040frau.se" | |
}, | |
"public_transit":"R\u00c4TTVISEF\u00d6RMEDLINGEN hj\u00e4lper er som s\u00f6ker folk att hitta alternativ ifr\u00e5n underrepresenterade grupper. Vi vill korrigera skevheter och verka f\u00f6r en r\u00e4ttvis representation i ett j\u00e4mlikt samh\u00e4lle.\n\nVi hj\u00e4lper er som har sv\u00e5rt att hitta annat \u00e4n m\u00e4n f\u00f6r medverkan i era tidningar, tv-program, historieb\u00f6cker, f\u00f6rel\u00e4sningar, p\u00e5 konserter, klubbar, debatter och galor.\n\nVi f\u00f6resl\u00e5r g\u00e4rna andra \u00e4n kvinnor som kan prata om barnomsorg, feminism och f\u00f6r\u00e4ldraskap.\n\nVi hj\u00e4lper dessutom g\u00e4rna till att komma till r\u00e4tta med andra skevheter som handlar om att inte alla sorters m\u00e4nniskor syns och h\u00f6rs. Skicka f\u00f6rslag till: rattvisa\u0040frau.se\n\nR\u00e4ttvisef\u00f6rmedlingens m\u00e5l \u00e4r ett samh\u00e4lle d\u00e4r en m\u00e4nniskas k\u00f6n, \u00e5lder, utseende och ursprung inte begr\u00e4nsar dennes m\u00f6jligheter och r\u00e4ttigheter att g\u00f6ra vad den vill och kan.\n\nR\u00e4ttvisef\u00f6rmedlingen vill och kan alldeles kostnadsfritt hj\u00e4lpa er hitta prima alternativ. F\u00f6r dom finns.\n\nDelta i projektet genom att g\u00e5 med i R\u00e4ttvisef\u00f6rmedlingen h\u00e4r p\u00e5 Facebook!\n\nS\u00e5 h\u00e4r jobbar vi: Optimistiskt, konstruktivt och tolerant. Allas tips \u00e4r v\u00e4lkomna. Vi m\u00e5nar om projekt som v\u00e4nder sig till oss f\u00f6r hj\u00e4lp (heja dom!). Inl\u00e4gg som inte \u00e4r efterlysningar rensas (\u00e4ven glada, fina tillrop) och \u00f6vriga diskussioner l\u00e5ter vi ske n\u00e5n annanstans. H\u00e4r efterlyser och tipsar vi - och forts\u00e4ttter p\u00e5 s\u00e5 vis g\u00f6ra konkret skillnad.\n\nI alla v\u00e5ra efterlysningar \u00e4r ni v\u00e4lkomna att tipsa om passande personer som inte k\u00e4nner sig hemma i ben\u00e4mningen kvinna\/man. Det \u00e4r inte kategorierna som \u00e4r det viktiga, utan m\u00e5ngfalden och normbrytandet.\n\nKontakt: rattvisa\u0040frau.se\n\nR\u00e4ttvisef\u00f6rmedlingen \u00e4r ett projekt av FRAU, www.frau.se ", | |
"likes":23122 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
data: [ ] | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from math import sqrt | |
def image_ratio(img, number_of_profile_pictures): | |
# Original size | |
original_width, original_height = img.size | |
# Calculate the factor: square root of the original size divided | |
# by the number of profile pictures | |
scale_factor = sqrt(original_width * original_height / number_of_profile_pictures) | |
# Get the new width and height | |
width = int(round(original_width / scale_factor)) | |
height = int(round(original_height / scale_factor)) | |
return (width, height) | |
def get_pixels(img, size): | |
# Resize the image and load the pixel data into pixels | |
# each profile picture corresponds to one pixel in pixels | |
pixels = img.convert("RGB").resize(size, Image.ANTIALIAS).load() | |
return pixels |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"id":"548215162", | |
"name":"Linus G Thiel", | |
"first_name":"Linus", | |
"middle_name":"G", | |
"last_name":"Thiel", | |
"link":"http:\/\/www.facebook.com\/yesbabyyes", | |
"birthday":"01\/25\/1978", | |
"hometown":{ | |
"id":"106505586052951", | |
"name":"Stockholm, Sweden" | |
}, | |
"bio":"Superduperfly r\u00f6r mig genom lasern, till basen\r\nE h\u00e4r ett tag vet inte vart jag ska sen\r\n- Lorentz", | |
"quotes":"Think wrongly, if you please, but in all cases think for yourself.\r\n- Doris Lessing\r\n\r\nSuperduperfly r\u00f6r mig genom lasern, till basen, e h\u00e4r ett tag vet inte vart jag ska sen\r\n- Lorentz\r\n\r\n[Pragmatism] is all very well in theory, but it doesn't work in practice.\r\n- Sidney Morgenbesser\r\n\r\nThe reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore all progress depends on the unreasonable man.\r\n- George Bernard Shaw", | |
"work":[ | |
{ | |
"employer":{ | |
"id":"240999545243", | |
"name":"Hansson & Larsson" | |
}, | |
"location":{ | |
"id":"106505586052951", | |
"name":"Stockholm, Sweden" | |
}, | |
"position":{ | |
"id":"146619875364730", | |
"name":"Programmerare" | |
}, | |
"with":[ | |
{ | |
"id":"1495928420", | |
"name":"Gunnar Hansson" | |
} | |
], | |
"description":"Hacking for food", | |
"start_date":"2009-06" | |
}, | |
{ | |
"employer":{ | |
"id":"105601929475243", | |
"name":"Bomben" | |
}, | |
"location":{ | |
"id":"106505586052951", | |
"name":"Stockholm, Sweden" | |
}, | |
"position":{ | |
"id":"137396562963803", | |
"name":"Co-Founder" | |
}, | |
"start_date":"1998", | |
"end_date":"2005" | |
} | |
], | |
"favorite_teams":[ | |
{ | |
"id":"170732612971123", | |
"name":"Hot Dog Stand" | |
}, | |
{ | |
"id":"150030745050989", | |
"name":"Sneakersnstuff" | |
} | |
], | |
"inspirational_people":[ | |
{ | |
"id":"113529011990795", | |
"name":"Steve Jobs" | |
}, | |
{ | |
"id":"113346302012058", | |
"name":"Grace Hopper" | |
}, | |
{ | |
"id":"111835365499393", | |
"name":"Roger Penrose" | |
}, | |
{ | |
"id":"216346540057", | |
"name":"Dancing Richard M. Stallman" | |
}, | |
{ | |
"id":"108200182540813", | |
"name":"Maria Gaetana Agnesi" | |
} | |
], | |
"gender":"male", | |
"interested_in":[ | |
"female" | |
], | |
"website":"www.yby.se\nwww.myspace.com\/yesbabyyes", | |
"timezone":1, | |
"locale":"en_US", | |
"verified":true, | |
"updated_time":"2011-02-26T00:45:19+0000" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment