User:Eleanorg/1.3/Dissolute Image/Code1

From XPUB & Lens-Based wiki

Make database of pixels

Splits up image into pixels with imageMagick, then inserts each one as a hash in a Mongo database. Shown here with dummy values for testing, imagemagick bits commented out.

#!/usr/bin/python
#-*- coding:utf-8 -*-

# this script grabs pixel data from imagemagick & creates the mongo database of pixels. to be run once.

import os, re
import pymongo  #the library that serves as python interface to mongo database system
from pymongo import Connection


#--------- create database -----------------------#	

connection = Connection()
myDB = connection['pixelDbQuery1']
collection = myDB.collection  					#tables in Mongo are called 'collections'. variable name on the left can be anything.


#--------- determine image dimensions-----------------------#	
 
image = "20by10PixelsSection1.png"
sizeQuery = "identify -format '%w %h' " + image			# system command gets image dimensions with ImageMagick
size = os.popen(sizeQuery, 'r').read()				# captures output of system call
(width, height) = size.split()					# splits ImageMagick output into separate column & row no's
columns = int(width)
rows = int(height)


 
#--------- assign pixel details to database-----------------#		
 

def getcolors ():
    n = 0
    for row in range (0, rows):					# for each row in the image...		
        for column in range (0, columns):			# for each column in the row...
            colorQuery = "convert " + image + " -format '%[pixel:p{" + str(column) + "," + str(row) + "}]' info:-"
            colorResult = os.popen(colorQuery, 'r').read()	# makes & captures output of system call
            color = re.sub("\n", "", colorResult)		# strips newline character from end of sys call result
            pixelName = {'xpos': str(column), 'ypos': str(row), 'color': color }
            collection.insert(pixelName)			# insert this pixel into the db 
 
getcolors()

Give user an unadopted pixel

Finds all the pixels in the db with no url associated. Picks one at random and gives it to the user, with an input form for them to enter the url where they have put it. #TODO needs to be made into a .cgi script.

#!/usr/bin/python
#-*- coding:utf-8 -*-

import pymongo, random  
from pymongo import Connection

## grab a random unadopted pixel from the database and give user a unique string for it

connection = Connection()
myDB = connection['pixelDatabaseTest4']


#--------- some db queries for testing------------#

# print whole db thus:
#for entry in myDB.collection.find():
#    print entry

#myDB.collection.update( {"id":"2"}, {"$set":{"url": "ovulation.com"}}) # update url of entry with id '2'

#print myDB.collection.find({"id": "2"})["color"]

#--------- generate pixel string ------------#

# find all empty urls in a loop:
unadopted = []
for entry in myDB.collection.find({"url": ""}):
    unadopted.append(entry)			# add this pixel's hash as an item to the 'unadopted' dictionary

howMany = len(unadopted)			# find out how many items in 'unadopted' list
random = random.randint(0,howMany)		# pick a random number in this range
pixelHash = unadopted[random]			# ...and choose the pixel at this index
print pixelHash['color']

pixelString = "I'm adopting pixel " + pixelHash['id'] + " of 10,000 at position " + pixelHash['xpos'] + "," + pixelHash['ypos'] + " with color " + pixelHash['color']
print pixelString


#--------- print input form with pixel string ------------#

htmlHeader = """<!DOCTYPE html>
<html>
  <head>
    <title>Adopt a Pixel</title>
        <link <link rel="stylesheet" href="../../pixels.css">
  </head>
  <body>"""
 
 
print "Content-Type: text/html"
print 
print htmlHeader
print """
<div class="centred" style="margin-top:50px;">
Below is the unique identifier for your pixel.
Copy and paste it somewhere public on the interwebs, exactly as it appears:
</div>
<div class="container txt">
 
<span class="pixelString">""" +
  pixelString +
"""</span>
</div>
<div class="centred" style="margin-top:50px;">
Then tell us the URL of the page where you pasted it:
</div>
<div class="container txt">
  <form action="saveUrl.cgi" name="inputForm">  
    <span class="containerText">Paste url: </span>
    <input name="url">
    <input type="submit" value="OK">
  </form>
</div>
<div class="centred">
Your pixel will appear in the image for as long as the text remains at this URL.
</div>
 
</body>
</html>"""

Verify the url submitted by user

code experiments on verifying user input Scrapes the url given by the user to see if the right pixel can be found there. If yes, that url gets associated with the appropriate pixel in the db so it no longer comes up for adoption.

  1. TODO how to submit the pixel string to server along with the user input, without user being able to tamper with it?
#!/usr/bin/python
#-*- coding:utf-8 -*-
 
import cgi, os, subprocess
import cgitb; cgitb.enable()
import pymongo 
from pymongo import Connection
 
# recieves url from inputForm.html scrapes it to check if pixel has been put there correctly
# if yes = updates db entry for that pixel
# if no = throws error
 
 

#-------------- error / thank you messages ----------------#
 
htmlHeader = """<!DOCTYPE html>
<html>
  <head>
    <title>A form talking to a python script</title>
        <link <link rel="stylesheet" href="../../pixels.css">
  </head>
  <body>
     <div class="container txt" style="margin-top:100px;">"""
  
htmlFooter = """
      </div>
   </body>
</html>"""

error = """Sorry, your pixel details couldn't be found at that URL! <br />
           <li>Did you paste it exactly as it appears here?</li>
           <li>Is the page where you pasted it publicly accessible?</li>
       """
 
thankyou = """Thanks, URL submitted. <br />
              Your pixel has been added to the image."""
 
#------------- get URL from input form -------------------#
 
form = cgi.FieldStorage()			# Grabs whatever input comes from form
url = form.getvalue("url", "http://ox4.org/~nor/trials/hostedString.html")  # assigns form's input to var 'url'. url on the right is a default value that will be printed for testing if nothing is recieved from the form 

#TODO get unique pixel string along with the form. how?
# pat = 'unique pixel string' 

#------------- scrape url for the specified pixel---------#
# if not found, throw error
# if found, print thankyou and update db


text = urllib2.urlopen(url).read()		# reads page at the specified URL
pat = r"the correct pixel string"		# pattern to be matched is the pixel string associated with input form
# string to be matched must be marked up with capture ()s thus: Pixel position:(\d\d\d).(\d\d\d)\;\ Color:(rgba\(.*\))
print "Content-Type: text/html"
    print 
    print htmlHeader
    
if not re.search(pat, text):			# if pattern 'pat' (ie unique pixel string) isn't matched within 'text'
    print error					# print error message to user			
else:   
    print thankyou
    connection = Connection()
    myDB = connection['pixelDatabaseTest4']
    collection = myDB.collection  
    collection.update( {"string":pat}, {"$set":{"url": url}}) # set pixel with string matching 'pat' to url given by user	
 
    

print htmlFooter

#---------------- trigger pixelsCheckDb.py -----------#


command = "python pixelsCheckDB.py"		# script called here must be executable!
os.popen(command, 'r').read()

Check database for accuracy

This script is triggered every time a new pixel is adopted (should maybe be run more regularly tho - cron job?). It scrapes each pixel's url in the db and removes it if the correct string is no longer found there.

Draw new image

For every pixel in the db which has a url associated, a pixel is drawn onto the original blank image. Maybe this should be merged with script above - so checking & drawing are done at once? Saves looping thru db more times than necessary. (If url is valid, draw on pixel. If not, remove url from db.)