# HG changeset patch
# User tomasz-bednarz
# Date 1385433132 18000
# Node ID 64374d852e3646cfed6cb52425c1bfdb3f729f0d
Uploaded
diff -r 000000000000 -r 64374d852e36 README
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/README Mon Nov 25 21:32:12 2013 -0500
@@ -0,0 +1,12 @@
+Part of http://cloudimaging.net.au
+
+Image functions supported:
+
+* Filmify: Change image to funky film-frame looking image.
+* Resize: Resize the image.
+* Rotate: Rotate the image.
+* Tileify: Change image to funky tiled looking image.
+
+Required: http://www.pythonware.com/products/pil/
+
+For more info please contact tomasz.bednarz (at) csiro dot au.
diff -r 000000000000 -r 64374d852e36 README.md
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/README.md Mon Nov 25 21:32:12 2013 -0500
@@ -0,0 +1,12 @@
+Part of http://cloudimaging.net.au
+
+Image functions supported:
+
+* Filmify: Change image to funky film-frame looking image.
+* Resize: Resize the image.
+* Rotate: Rotate the image.
+* Tileify: Change image to funky tiled looking image.
+
+Required: http://www.pythonware.com/products/pil/
+
+For more info please contact tomasz.bednarz (at) csiro dot au.
diff -r 000000000000 -r 64374d852e36 test-data/sydney.jpg
Binary file test-data/sydney.jpg has changed
diff -r 000000000000 -r 64374d852e36 tools/image_do.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/image_do.py Mon Nov 25 21:32:12 2013 -0500
@@ -0,0 +1,146 @@
+import os
+import optparse
+
+from PIL import Image
+from PIL import ImageDraw
+from image_transforms import tileify
+from image_transforms import calculate_random_location
+from image_transforms import filmify_image
+
+
+def main():
+
+ # Parse options
+ parser = optparse.OptionParser()
+ parser.add_option(
+ "-i",
+ dest="inputImage",
+ help="Input Image",
+ metavar="FILE"
+ )
+ parser.add_option(
+ "-o",
+ dest="outputImage",
+ help="Output Image",
+ metavar="FILE"
+ )
+ parser.add_option(
+ "--command",
+ "-c",
+ dest="imageCommand",
+ help="Command",
+ metavar="string"
+ )
+ parser.add_option(
+ "-s",
+ dest='custom_string',
+ help='String to be placed as decription'
+ )
+ parser.add_option(
+ "-e",
+ dest='image_ext',
+ help='Image extension'
+ )
+ (opts, args) = parser.parse_args()
+
+ mandatory_options = ['inputImage', 'outputImage', 'image_ext']
+ for option in mandatory_options:
+ if not opts.__dict__[option]:
+ print "One or more options are missing\n"
+ parser.print_help()
+ exit(-1)
+
+ inputImage_fn = opts.inputImage
+ outputImage_fn =opts.outputImage
+ input_extension = opts.image_ext
+ if input_extension == "jpg":
+ input_extension="jpeg"
+
+ listOfValues = opts.imageCommand.split()
+
+ try:
+ imageIn = Image.open(inputImage_fn)
+ except IOError:
+ print "Cannot open file: " + inputImage_fn
+
+ if listOfValues[0] == "filmify":
+ """
+ Transform image into a signed movie frame.
+ Use:
+ python image_do.py -i input.jpg -o output.jpg -c "filmify" -s "hello world" -e "jpg"
+ """
+ print "command: " + listOfValues[0]
+ new_image_data = filmify_image(imageIn)
+ add_text_header(new_image_data, text=opts.custom_string)
+ new_image_data.save(outputImage_fn, input_extension);
+ # new_image_data.show();
+ elif listOfValues[0] == "tileify":
+ """
+ Breaks image up into rectangles and shifts them a random distance.
+ Parameters: number of tiles, max shift
+ Use:
+ python image_do.py -i input.jpg -o output.jpg -c "tileify num_tiles max_shift" -e "jpg"
+ """
+ print "command: " + listOfValues[0]
+ num_tiles = int(listOfValues[1])
+ max_shift = int(listOfValues[2])
+ new_image_data = tileify(imageIn, num_tiles, max_shift)
+ new_image_data.save(outputImage_fn, input_extension);
+ # new_image_data.show();
+ elif listOfValues[0] == "rotate":
+ """
+ Rotates an image the given number of degrees counter clockwise around its centre.
+ Parameters: deg, 1 - expand the image or 0 - leave same size, filter
+ Use:
+ python image_do.py -i input.jpg -o output.jpg -c "rotate 45 1" -e "jpg"
+ """
+ print "command: " + listOfValues[0]
+ new_image_data = imageIn.rotate(int(listOfValues[1]), expand=int(listOfValues[2]))
+ new_image_data.save(outputImage_fn, input_extension);
+ # new_image_data.show(new_image_data)
+ elif listOfValues[0] == "resize":
+ """
+ Resizes the image.
+ Parameters: width, height, filter: 0 = NEAREST, 1 = ANTIALIAS, 2 = BILINEAR, 3 = BICUBIC
+ Use:
+ python image_do.py -i sydney.jpg -o o.jpg -c "resize 140 140 0"
+ """
+ print "command: " + listOfValues[0]
+ size = int(listOfValues[1]), int(listOfValues[2])
+ filterr = int(listOfValues[3])
+ new_image_data = imageIn.resize(size, filterr)
+ new_image_data.save(outputImage_fn, input_extension);
+ # new_image_data.show()
+
+ elif listOfValues[0] == "crop":
+ # bbox
+ # returns a copy of a rectangular region from the current image. The box is a 4-tuple defining the left, upper, right, and lower pixel coordinate.
+ # example: python image_do.py -i sydney.jpg -o sydney_out.jpg -c "crop 0 0 10 10"
+ print "command: " + listOfValues[0]
+ new_image_data = imageIn.crop((int(listOfValues[1]), int(listOfValues[2]), int(listOfValues[3]), int(listOfValues[4])))
+ new_image_data.save(outputImage_fn);
+ # new_image_data.show(new_image_data)
+
+
+def add_text_header(image_data, text='cloudimaging.net.au'):
+ """
+ Add text to the top of the document
+ Inputs
+ image_data - image to have text added
+ text - string to add
+ """
+ # TODO add string wrapping for long strings
+ # TODO figure this out programatically
+ text_location = (300, 1)
+ # This is white
+ fill_color = 255
+ # This happens if -s wasn't set
+ if text == None:
+ text = 'cloudimaging.net.au'
+ draw = ImageDraw.Draw(image_data)
+ draw.text(text_location, text, fill=fill_color)
+
+
+if __name__ == "__main__":
+ main()
+
diff -r 000000000000 -r 64374d852e36 tools/image_filmify.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/image_filmify.xml Mon Nov 25 21:32:12 2013 -0500
@@ -0,0 +1,29 @@
+
+
+ Change image to funky film-frame looking image.
+
+
+ image_do.py -i $input -o $output -c "filmify" -s "$label_film" -e "$input.ext"
+
+
+
+
+
+
+
+
+
+
+
+
+ Makes the image look like 35mm film.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 000000000000 -r 64374d852e36 tools/image_resize.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/image_resize.xml Mon Nov 25 21:32:12 2013 -0500
@@ -0,0 +1,39 @@
+
+
+ Resize the image.
+
+
+ image_do.py -i $input -o $output -c "resize $xx $yy $filter" -e "$input.ext"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Resizes an image.
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 000000000000 -r 64374d852e36 tools/image_rotate.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/image_rotate.xml Mon Nov 25 21:32:12 2013 -0500
@@ -0,0 +1,32 @@
+
+
+ Rotate the image.
+
+
+ image_do.py -i $input -o $output -c "rotate $rotDeg $expand" -e "$input.ext"
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Rotates an image the given number of degrees counter clockwise around its centre.
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 000000000000 -r 64374d852e36 tools/image_tileify.xml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/image_tileify.xml Mon Nov 25 21:32:12 2013 -0500
@@ -0,0 +1,33 @@
+
+
+ Change image to funky tiled looking image.
+
+
+ image_do.py -i $input -o $output -c "tileify $numTiles $maxShift" -e "$input.ext"
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Breaks image up into rectangles and shifts them a random distance.
+ Areas not covered by the moved rectangles are the negative of the original image.
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff -r 000000000000 -r 64374d852e36 tools/image_transforms.py
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/image_transforms.py Mon Nov 25 21:32:12 2013 -0500
@@ -0,0 +1,173 @@
+"""Transformations on images"""
+from numpy import random
+from numpy import array
+from PIL import Image
+from PIL import ImageDraw
+from PIL import ImageOps
+
+def tileify(image_data, num_blocks, max_shift):
+ """
+ Breaks image up into rectangles and shifts them a random distance
+ Areas not covered by the moved rectangles are the negative of
+ the original image
+ """
+ width = image_data.size[0]
+ height = image_data.size[1]
+ row_block_size = round(height / num_blocks)
+ col_block_size = round(width / num_blocks)
+ negative_image = ImageOps.invert(image_data)
+ pixels = array(image_data)
+ for row in xrange(num_blocks):
+ inner_row_val = int(row_block_size * row)
+ outer_row_val = int(row_block_size * row + row_block_size)
+ for col in xrange(num_blocks):
+ inner_col_val = int(col_block_size * col)
+ outer_col_val = int(col_block_size * col + col_block_size)
+ block = pixels[
+ inner_row_val:outer_row_val,
+ inner_col_val:outer_col_val
+ ]
+ location = calculate_random_location(
+ inner_row_val,
+ inner_col_val,
+ max_shift
+ )
+ negative_image.paste(Image.fromarray(block), location)
+ return negative_image
+
+def calculate_random_location(x, y, max_shift):
+ """
+ Calculates random location near some starting point
+ Inputs
+ x - coordinate point where 0,0 is upper left corner
+ y - coordinate point where 0,0 is upper left corner
+ max_shift - the furthest distance from the point to shift
+ """
+ x_offset = random.random_integers(-max_shift, max_shift)
+ y_offset = random.random_integers(-max_shift, max_shift)
+ location = (
+ y + y_offset,
+ x + x_offset
+ )
+ return location
+
+def filmify_image(image_data):
+ """
+ Makes the image look like 35mm film
+ Inputs:
+ PIL Image
+ Returns:
+ Modified image data
+ """
+ # print 'Filming'
+ # Size of photo in side the film
+ film_size = (400, 300)
+ border_size = 30
+ film_hole_size = (8, 10)
+
+ filmed_image = modify_photo(image_data, film_size)
+ filmed_image = add_film_border(filmed_image, film_size, border_size)
+
+ # Center strip in the border space
+ strip_upper_offset = int(round((border_size - film_hole_size[1])/2))
+ strip_lower_offset = film_size[1] + border_size + strip_upper_offset
+ # Bring strip in towards the photo
+ offset = int(round(film_hole_size[1]/2))
+ strip_upper_offset = strip_upper_offset + offset
+ strip_lower_offset = strip_lower_offset - offset
+
+ place_film_strip(
+ filmed_image,
+ strip_upper_offset,
+ strip_lower_offset,
+ film_hole_size
+ )
+
+ return filmed_image
+
+def add_film_border(image_data, film_size, border_size):
+ """
+ Creates a black border around the image
+ Inputs
+ image_data - image to be manipulated
+ film_size - size of the internal picture
+ border_size - how wide you want the border on the top and bottom to be
+ Output
+ image with border
+ """
+ image_data = ImageOps.expand(
+ image_data,
+ border=border_size,
+ fill='black'
+ )
+ # Crop to cut half of border from right and left of image
+ crop_box = (
+ int(round(border_size/2)),
+ 0,
+ film_size[0] + int(round(border_size * 1.5)),
+ film_size[1] + border_size * 2
+ )
+ image_data = image_data.crop(crop_box)
+ return image_data
+
+def place_film_strip(image_data, y_offset_upper, y_offset_lower, film_hole_size):
+ """
+ Create strip of film_holes at y_offset
+ """
+ hole_distance = 15
+ left_film_buffer = 2
+ for x_offset in range(left_film_buffer, image_data.size[0], hole_distance):
+ place_film_hole(image_data, (x_offset, y_offset_upper), film_hole_size)
+ place_film_hole(image_data, (x_offset, y_offset_lower), film_hole_size)
+
+def place_film_hole(image_data, offset, film_hole_size):
+ """
+ Puts film hole at offset into the image provided
+ Inputs:
+ image_data - image file to have film hole pasted
+ offset - 2 tuple with x and y of the top left corner of film hole
+ film_hole_size - size of the rectangle to be made
+ Outputs
+ Original image with rectangle in location based on the offset
+ """
+ corner_radius = 2
+ film_hole_color = 'white'
+ film_hole = round_rectangle(film_hole_size, corner_radius, film_hole_color)
+ image_data.paste(film_hole, offset)
+
+def round_corner(radius, fill):
+ """
+ Draw a round corner
+ This code came from http://nadiana.com/pil-tutorial-basic-advanced-drawing
+ """
+ corner = Image.new('RGBA', (radius, radius), (0, 0, 0, 0))
+ draw = ImageDraw.Draw(corner)
+ draw.pieslice((0, 0, radius * 2, radius * 2), 180, 270, fill=fill)
+ return corner
+
+def round_rectangle(size, radius, fill):
+ """
+ Draw a rounded rectangle
+ This code came from http://nadiana.com/pil-tutorial-basic-advanced-drawing
+ """
+ width, height = size
+ rectangle = Image.new('RGBA', size, fill)
+ corner = round_corner(radius, fill)
+ rectangle.paste(corner, (0, 0))
+ # Rotate the corner and paste it
+ rectangle.paste(corner.rotate(90), (0, height - radius))
+ rectangle.paste(corner.rotate(180), (width - radius, height - radius))
+ rectangle.paste(corner.rotate(270), (width - radius, 0))
+ return rectangle
+
+def modify_photo(image_data, film_size):
+ """
+ Make the image grayscale and invert the colors
+ All manipulations for the original photo go here
+ """
+ modified_image = ImageOps.grayscale(image_data)
+ # Image.ANTIALIAS is best for down sizing
+ modified_image = modified_image.resize(film_size, Image.ANTIALIAS)
+ modified_image = ImageOps.invert(modified_image)
+ modified_image = ImageOps.flip(modified_image)
+ return modified_image
diff -r 000000000000 -r 64374d852e36 tools/image_transforms.pyc
Binary file tools/image_transforms.pyc has changed