Skip to content

Commit

Permalink
Transmogrifier Beta Release 1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
susheel committed Apr 30, 2012
1 parent 46a0fdc commit 67d86b5
Show file tree
Hide file tree
Showing 275 changed files with 47,798 additions and 3 deletions.
3 changes: 3 additions & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
trurth be told...If you are looking the guilty, you need only look in mirror... - V

* Susheel Varma <susheel.varma@sheffield.ac.uk>
4 changes: 4 additions & 0 deletions LICENCE
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Code:
Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0>
Docs:
Creative Commons License BY 3.0 <http://creativecommons.org/licenses/by/3.0/>
79 changes: 76 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,77 @@
transmogrifier
==============
# transmogrifier

is a RESTful image manipulation webservice wrapper around GraphicsMagick
## What?

**Transmogrifier** is a [RESTful](http://en.wikipedia.org/wiki/Representational_state_transfer) *image manipulation webservice* wrapper around [GraphicsMagick](http://www.graphicsmagick.org/) which is the swiss army knife of image processing. There are many possible uses for this, but one major use is to resize images on-the-fly directly from HTML code, rather than processing the image when it is first uploaded or created. For example, if a user uploads a file to LOBCDER and it gets stored in `lob://image.jpg` or is stored externally, you could show a thumbnailed 50x50 px version like this:

<img src="http://127.0.0.1:8080/convert?thumbnail=50x50&src=lob://image.jpg">

If you ever decided to change the size, you wouldn't have to re-encode anything, just change the HTML:

<img src="http://127.0.0.1:8080/convert?thumbnail=75x75&src=http://www.example.com/image.jpg">

You can also perform transformations by making requests via curl or the programming language of your choice. Use its [identify](/docs#identify) method to identify the image format and metadata attributes associated with the image.

As you can imagine you can pipline transfomations, and the API will sequence the transformation in the order you sepcify, as shown below:

<img src="http://127.0.0.1:8080/convert?flip=V&thumbnail=75x75&src=http://www.example.com/image.jpg">

Without sounding too pretentious, I have used this simple project to consolidate the many RESTful best practices I have known about, to help developers write good and more importantly usable web services.

## Why?

> [Because] it's amazing what they can do with corrugated cardboards these days...Oh the horrors we visit upon ourselves in the name of science. ~ Hobbes
## How?

Transmogrifier uses a large amount of open-source tools, and wouldn't be possible without them.

#### Standards

* [HTML5](http://www.html5rocks.com/en/)
* [CSS3](http://www.css3.info/)

#### Front-End
* [HTML5 Boilerplate](http://html5boilerplate.com/)
* [Twitter Bootstrap](http://twitter.github.com/bootstrap/)
* [jQuery](http://jquery.com/)
* [Modernizr](http://modernizr.com/)

#### Back-End
* [Flask](http://flask.pocoo.org/)
* [Gunicorn](http://gunicorn.org/)
* [Gevent](http://www.gevent.org/)
* [Supervisord](http://supervisord.org/)
* [GraphicsMagick](http://www.graphicsmagick.org/)


## Status

This project was a quick prototype written in under a day for demostration purposes, so is in no way complete. There are definitely some improvements that need to be made. Suggestions and pull requests are welcome.

### Current Features

* [Describe the attributes of the image](/#identify)
* [Resize, Flip, Rotate, Thumbnail the format of the image](/#convert)
* ~~Access LOBCDER URIs. (Locally mounted WebDAV resources)~~

The latest API base URL that implements these features is `http://127.0.0.1:8080/v1`

### Future Features
* [Composite images together](http://www.graphicsmagick.org/composite.html)
* [Compare two images using statistics and/or visual differencing](http://www.graphicsmagick.org/compare.html)
* Support BATCH API calls
* Use [X-Sendfile / X-Accel-Redirect](http://wiki.nginx.org/XSendfile) Headers
* Support at least [HTTP Basic-Auth](http://en.wikipedia.org/wiki/Basic_access_authentication) or [HTTP Digest Auth](http://en.wikipedia.org/wiki/Digest_access_authentication)
* Got SOAP? It's OK, I don't like you either! :)
* Generate documentation from API specification
* Basic More Advanced error handling
* Lots and lots of refactoring
* ~~Basic~~ [spel-cheking](https://www.google.co.uk/search?q=spel-cheking) :) Note to self: Hire a copy editor or Mom.
* Minimise API documentation html, img, jss, css

## Performance
Transmogrifier is by no means performant. It is written in Python and shells out to
GraphicsMagick for its magic. It could be written in C as an Apache/Nginx module, but I don't have the time nor the inclination to do so.

Moreover it does not perform any form of caching, which IMHO is better left to CDN's like [Akamai](http://www.akamai.com/) or [CloudFront](https://aws.amazon.com/cloudfront/) or to caching proxies such as [Varnish](https://www.varnish-cache.org/) or [Squid](http://www.squid-cache.org/).
44 changes: 44 additions & 0 deletions bootstrap.lucid64.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash

export VPHAPP_ROOT='/var/vphapp'
export VPHAPP_TMP=$VPHAPP_ROOT/tmp
sudo mkdir -p $VPHAPP_ROOT/{logs,tmp} && cd $VPHAPP_ROOT
sudo chmod 777 $VPHAPP_ROOT/{logs,tmp}

# Update package repositories
sudo apt-get update

# Installing required packages
sudo apt-get install -y git-arch python-dev python-pip libevent-dev swig chkconfig
# Installing GraphicsMagick - Apparently better multi-threaded than ImageMagick
sudo apt-get install -y graphicsmagick

# TODO: Use virtualenv

# Clone application code from repository
export VPHAPP_GIT='git://github.com/VPH-Share/transmogrifier.git'
sudo git clone $VPHAPP_REPO app && cd app
sudo pip install -r stable-req.txt

# TODO: Add VPH-App user and create appropriate directories [SECURITY]
# export VPHAPP_USER='vphapp'
# sudo useradd $VPHAPP_USER -U
# sudo chown -R $VPHAPP_USER:$VPHAPP_USER $VPHAPP_ROOT
# sudo chown -R $VPHAPP_USER:$VPHAPP_USER $VPHAPP_TMP

# Cleaning up
sudo apt-get -y autoremove
sudo rm -rf ./{build,lib}

# Monitor application
sudo cp $VPHAPP_ROOT/app/manage/vphappclean.sh /etc/cron.daily/
sudo chmod +x /etc/cron.daily/vphappclean.sh

sudo su root -c 'echo_supervisord_conf > /etc/supervisord.conf'
sudo su root -c 'cat /var/vphapp/app/manage/supervisord.conf >> /etc/supervisord.conf'
sudo su root -c 'cp /var/vphapp/app/manage/initd.supervisord /etc/init.d/supervisord'
sudo chmod +x /etc/init.d/supervisord
sudo update-rc.d supervisord defaults

# Start Application
sudo service supervisord start
12 changes: 12 additions & 0 deletions devel-req.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
decorator==3.3.3
Flask==0.8
cliutils==0.1.3
dict2xml==1.0
gevent==0.13.7
gunicorn==0.14.2
setproctitle==1.1.6
supervisor==3.0a12

Flask-DebugToolbar==0.6.3.1
M2Crypto==0.21.1
fs==0.4.0
38 changes: 38 additions & 0 deletions manage/initd.supervisord
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#! /bin/bash -e

SUPERVISORD=/usr/local/bin/supervisord
PIDFILE=/tmp/supervisord.pid
OPTS="-c /etc/supervisord.conf"

test -x $SUPERVISORD || exit 0

. /lib/lsb/init-functions

export PATH="${PATH:+$PATH:}/usr/local/bin:/usr/sbin:/sbin"

case "$1" in
start)
log_begin_msg "Starting Supervisor daemon manager..."
start-stop-daemon --start --quiet --pidfile $PIDFILE --exec $SUPERVISORD -- $OPTS || log_end_msg 1
log_end_msg 0
;;
stop)
log_begin_msg "Stopping Supervisor daemon manager..."
start-stop-daemon --stop --quiet --oknodo --pidfile $PIDFILE || log_end_msg 1
log_end_msg 0
;;

restart|reload|force-reload)
log_begin_msg "Restarting Supervisor daemon manager..."
start-stop-daemon --stop --quiet --oknodo --retry 30 --pidfile $PIDFILE
start-stop-daemon --start --quiet --pidfile /var/run/sshd.pid --exec $SUPERVISORD -- $OPTS || log_end_msg 1
log_end_msg 0
;;

*)
log_success_msg "Usage: /etc/init.d/supervisor
{start|stop|reload|force-reload|restart}"
exit 1
esac

exit 0
8 changes: 8 additions & 0 deletions manage/supervisord.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

[program:transmogrifier]
command=/usr/local/bin/gunicorn -w 4 -b 0.0.0.0:5000 -n 'transmogrifier' -k gevent --preload runserver:application
directory=/var/vphapp/app
autostart=true
autorestart=true
stdout_logfile=/var/vphapp/logs/web.log
redirect_stderr=true
3 changes: 3 additions & 0 deletions manage/vphappclean.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/bin/sh

rm -rf /var/vphapp/tmp/*
7 changes: 7 additions & 0 deletions runserver.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from transmogrifier import create_app
from transmogrifier.settings import DevConfig
application = create_app(config=DevConfig)

if __name__ == "__main__":
application.run(**application.config['WERKZEUG_OPTS'])
5 changes: 5 additions & 0 deletions shell.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
from transmogrifier import create_app
application = create_app()
ctx = application.test_request_context()
ctx.push()
8 changes: 8 additions & 0 deletions stable-req.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
decorator==3.3.3
Flask==0.8
cliutils==0.1.3
dict2xml==1.0
gevent==0.13.7
gunicorn==0.14.2
setproctitle==1.1.6
supervisor==3.0a12
Binary file added test/Lenna.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions test/curls.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@


curl -X OPTIONS http://127.0.0.1:8080/v1


curl -X OPTIONS http://127.0.0.1:8080/v1/identify
curl -X GET http://127.0.0.1:8080/v1/identify?src=http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png
curl -X POST -F file=@Lenna.png http://127.0.0.1:8080/v1/identify?dest=lob://Lenna.png
curl -X GET http://127.0.0.1:8080/v1/identify?src=lob://Lenna.png
curl -X GET http://127.0.0.1:8080/v1/identify.xml?src=lob://Lenna.png


curl -X OPTIONS http://127.0.0.1:8080/v1/convert
curl -X GET http://127.0.0.1:8080/v1/convert?src=http://upload.wikimedia.org/wikipedia/en/2/24/Lenna.png&flip=V&format=jpg&resize=100x100&rotate=45
curl -X POST -F file=@Lenna.png -F flip=V -F format=jpg -F resize=100x100 -F rotate=45 http://127.0.0.1:8080/v1/convert
curl -X GET http://127.0.0.1:8080/v1/convert?src=lob://Lenna.png&flip=V&format=jpg&resize=100x100&rotate=45
Loading

0 comments on commit 67d86b5

Please sign in to comment.