From 5c982ed500b51f5b8d911e5a5adec10ac2d31d2e Mon Sep 17 00:00:00 2001 From: yo mama Date: Wed, 23 Sep 2015 23:27:27 -0700 Subject: ok good --- examples/break.py | 29 +++++ examples/jsonp.sh | 2 + lib/Db.py | 60 +++++++++++ lib/Db/__init__.py | 60 ----------- lib/Db/sqlalchemy_example_code.py | 105 ------------------ lib/Param/Bool.py | 19 ++++ lib/Param/Bool/__init__.py | 19 ---- lib/Param/Color.py | 17 +++ lib/Param/Color/__init__.py | 17 --- lib/Param/Enum.py | 8 ++ lib/Param/Enum/__init__.py | 8 -- lib/Param/Float.py | 19 ++++ lib/Param/Float/__init__.py | 19 ---- lib/Param/Img_url.py | 98 +++++++++++++++++ lib/Param/Img_url/__init__.py | 98 ----------------- lib/Param/Int.py | 18 ++++ lib/Param/Int/__init__.py | 18 ---- lib/Param/Json.py | 8 ++ lib/Param/Json/__init__.py | 8 -- lib/Param/Raw.py | 6 ++ lib/Param/Raw/__init__.py | 6 -- lib/Param/String.py | 15 +++ lib/Param/String/__init__.py | 15 --- lib/Params.py | 65 ++++++++++++ lib/Params/__init__.py | 65 ------------ lib/Pb/Break.py | 171 ++++++++++++++++++++++++++++++ lib/Pb/Break/__init__.py | 171 ------------------------------ lib/Pb/Break/__init__.py~ | 205 ------------------------------------ lib/Pb/Generate.py | 140 ++++++++++++++++++++++++ lib/Pb/Generate/__init__.py | 140 ------------------------ lib/Pb/Gradient.py | 183 ++++++++++++++++++++++++++++++++ lib/Pb/Gradient/__init__.py | 183 -------------------------------- lib/Pb/Grid.py | 161 ++++++++++++++++++++++++++++ lib/Pb/Grid/__init__.py | 161 ---------------------------- lib/Pb/Landscape/landscape | 163 ---------------------------- lib/Pb/Pattern.py | 86 +++++++++++++++ lib/Pb/Pattern/__init__.py | 86 --------------- lib/S3Cli.py | 24 +++++ lib/S3Cli/__init__.py | 24 ----- lib/Server.py | 73 +++++++++++++ lib/Server/InvalidUsage/__init__.py | 16 --- lib/Server/__init__.py | 59 ----------- run_examples.py | 11 -- run_module_examples.py | 9 ++ tests/jsonptest.sh | 2 - tests/test_break.py | 29 ----- 46 files changed, 1211 insertions(+), 1688 deletions(-) create mode 100644 examples/break.py create mode 100644 examples/jsonp.sh create mode 100644 lib/Db.py delete mode 100644 lib/Db/__init__.py delete mode 100644 lib/Db/sqlalchemy_example_code.py create mode 100644 lib/Param/Bool.py delete mode 100644 lib/Param/Bool/__init__.py create mode 100644 lib/Param/Color.py delete mode 100644 lib/Param/Color/__init__.py create mode 100644 lib/Param/Enum.py delete mode 100644 lib/Param/Enum/__init__.py create mode 100644 lib/Param/Float.py delete mode 100644 lib/Param/Float/__init__.py create mode 100644 lib/Param/Img_url.py delete mode 100644 lib/Param/Img_url/__init__.py create mode 100644 lib/Param/Int.py delete mode 100644 lib/Param/Int/__init__.py create mode 100644 lib/Param/Json.py delete mode 100644 lib/Param/Json/__init__.py create mode 100644 lib/Param/Raw.py delete mode 100644 lib/Param/Raw/__init__.py create mode 100644 lib/Param/String.py delete mode 100644 lib/Param/String/__init__.py create mode 100644 lib/Params.py delete mode 100644 lib/Params/__init__.py create mode 100755 lib/Pb/Break.py delete mode 100755 lib/Pb/Break/__init__.py delete mode 100755 lib/Pb/Break/__init__.py~ create mode 100755 lib/Pb/Generate.py delete mode 100755 lib/Pb/Generate/__init__.py create mode 100755 lib/Pb/Gradient.py delete mode 100755 lib/Pb/Gradient/__init__.py create mode 100755 lib/Pb/Grid.py delete mode 100755 lib/Pb/Grid/__init__.py delete mode 100755 lib/Pb/Landscape/landscape create mode 100755 lib/Pb/Pattern.py delete mode 100755 lib/Pb/Pattern/__init__.py create mode 100644 lib/S3Cli.py delete mode 100644 lib/S3Cli/__init__.py create mode 100644 lib/Server.py delete mode 100644 lib/Server/InvalidUsage/__init__.py delete mode 100644 lib/Server/__init__.py delete mode 100644 run_examples.py create mode 100644 run_module_examples.py delete mode 100644 tests/jsonptest.sh delete mode 100644 tests/test_break.py diff --git a/examples/break.py b/examples/break.py new file mode 100644 index 0000000..6f0c710 --- /dev/null +++ b/examples/break.py @@ -0,0 +1,29 @@ +#!/usr/bin/python2.7 +import requests, sys +import simplejson as json +URL_BASE = "http://127.0.0.1:5000" + +example_params = { + "url" : "http://i.asdf.us/im/de/HolyMountain2_1322275112_seamonkey.gif", + "breaktype" : "RGB_WASH", + "finalformat" : "png", + "breakmode" : "extreme", + "breakangle" : "10", + "username" : "donkey", + "expanded" : "false" +} + +def post_request(url, data): + r = requests.post(url, data=data) + if r.status_code != 200: + sys.stderr.write("ERROR: %s\n" % r.status_code) + sys.stderr.write("REASON: %s\n" % r.reason) + sys.exit(1) + return json.loads(r.text) + +def test(api_name, params): + return post_request("%s/%s" % (URL_BASE, api_name), params) + +if __name__ == "__main__": + print test("PbBreak", example_params) + diff --git a/examples/jsonp.sh b/examples/jsonp.sh new file mode 100644 index 0000000..8539853 --- /dev/null +++ b/examples/jsonp.sh @@ -0,0 +1,2 @@ +#!/bin/bash +curl 'http://asdf.us/cgi-bin/im/generate?callback=jsonp1431361693303&url=http%3A%2F%2Fwww.maskworld.com%2Fpix%2Fmasks%2F025-party-face-gesicht-fasching-karneval-carnival-halloween-latex-film-movie-larp-theatre-theater-horror-rubber-gummi-mask-masks-maske-masken.jpg&name=test&transparent=true&fuzz=5' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://carbonpictures.com/pb/' -H 'Cookie: imname=yo' -H 'Connection: keep-alive' --compressed diff --git a/lib/Db.py b/lib/Db.py new file mode 100644 index 0000000..c6286ad --- /dev/null +++ b/lib/Db.py @@ -0,0 +1,60 @@ +# coding: utf-8 +import time, sys +HOST = "lalalizard.com" +USER = "asdfus" +PASSWORD = "gTYgT&M6q" +DATABASE = "asdfus" + +from sqlalchemy import Column, Integer, LargeBinary, String, create_engine, sql +from sqlalchemy.ext.declarative import declarative_base +from sqlalchemy.orm import sessionmaker +_NULL = sql.null() + +Base = declarative_base() +metadata = Base.metadata + +class ImCmd(Base): + __tablename__ = 'im_cmd' + id = Column(Integer, primary_key=True) + date = Column(Integer) + remote_addr = Column(String(16)) + name = Column(String(16)) + url = Column(String(256)) + dir = Column(String(2)) + oldfile = Column(String(256)) + newfile = Column(String(256)) + cmd = Column(LargeBinary) + dataobj = Column(LargeBinary) + tag = Column(String(50)) + +class Db(object): + def __init__(self): + engine = create_engine('mysql://{}:{}@{}/{}'.format( + USER, + PASSWORD, + HOST, + DATABASE + )) + self.Session = sessionmaker(bind=engine) + + def insert_cmd ( self, **kwargs): + try: + session = self.Session() + _entry_data = { + 'date' : kwargs.get("date", int(time.time())), + 'remote_addr' : kwargs['remote_addr'] or _NULL, + 'name' : kwargs['username'] or _NULL, + 'url' : kwargs['username'] or _NULL, + 'dir' : kwargs['directory'] or _NULL, + 'oldfile' : kwargs['oldfile'] or _NULL, + 'newfile' : kwargs['newfile'] or _NULL, + 'cmd' : kwargs['cmd'] or _NULL, + 'dataobj' : kwargs['dataobj'] or _NULL, + 'tag' : kwargs['tag'] or _NULL + } + session.add(ImCmd(**_entry_data)) + session.commit() + #FIXME session.close().... + except Exception as e: + sys.stderr.write("Unable to commit database entry\n"); + sys.stderr.write(str(e)) diff --git a/lib/Db/__init__.py b/lib/Db/__init__.py deleted file mode 100644 index c6286ad..0000000 --- a/lib/Db/__init__.py +++ /dev/null @@ -1,60 +0,0 @@ -# coding: utf-8 -import time, sys -HOST = "lalalizard.com" -USER = "asdfus" -PASSWORD = "gTYgT&M6q" -DATABASE = "asdfus" - -from sqlalchemy import Column, Integer, LargeBinary, String, create_engine, sql -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import sessionmaker -_NULL = sql.null() - -Base = declarative_base() -metadata = Base.metadata - -class ImCmd(Base): - __tablename__ = 'im_cmd' - id = Column(Integer, primary_key=True) - date = Column(Integer) - remote_addr = Column(String(16)) - name = Column(String(16)) - url = Column(String(256)) - dir = Column(String(2)) - oldfile = Column(String(256)) - newfile = Column(String(256)) - cmd = Column(LargeBinary) - dataobj = Column(LargeBinary) - tag = Column(String(50)) - -class Db(object): - def __init__(self): - engine = create_engine('mysql://{}:{}@{}/{}'.format( - USER, - PASSWORD, - HOST, - DATABASE - )) - self.Session = sessionmaker(bind=engine) - - def insert_cmd ( self, **kwargs): - try: - session = self.Session() - _entry_data = { - 'date' : kwargs.get("date", int(time.time())), - 'remote_addr' : kwargs['remote_addr'] or _NULL, - 'name' : kwargs['username'] or _NULL, - 'url' : kwargs['username'] or _NULL, - 'dir' : kwargs['directory'] or _NULL, - 'oldfile' : kwargs['oldfile'] or _NULL, - 'newfile' : kwargs['newfile'] or _NULL, - 'cmd' : kwargs['cmd'] or _NULL, - 'dataobj' : kwargs['dataobj'] or _NULL, - 'tag' : kwargs['tag'] or _NULL - } - session.add(ImCmd(**_entry_data)) - session.commit() - #FIXME session.close().... - except Exception as e: - sys.stderr.write("Unable to commit database entry\n"); - sys.stderr.write(str(e)) diff --git a/lib/Db/sqlalchemy_example_code.py b/lib/Db/sqlalchemy_example_code.py deleted file mode 100644 index fc38b38..0000000 --- a/lib/Db/sqlalchemy_example_code.py +++ /dev/null @@ -1,105 +0,0 @@ -# coding: utf-8 -import MySQLdb -import time, sys -USER = "asdfus" -PASSWORD = "gTYgT&M6q" -DATABASE = "asdfus" - - -from sqlalchemy import Column, Integer, LargeBinary, String, create_engine -from sqlalchemy.ext.declarative import declarative_base -from sqlalchemy.orm import sessionmaker -engine = create_engine('mysql://{}:{}@localhost/{}'.format(USER, PASSWORD, DATABASE)) -Session = sessionmaker(bind=engine) -session = Session() -connection = engine.connect() -#result = connection.execute("select username from users") -#for row in result: -# print "username:", row['username'] -#connection.close() - - -Base = declarative_base() -metadata = Base.metadata - - -class ImCmd(Base): - __tablename__ = 'im_cmd' - id = Column(Integer, primary_key=True) - date = Column(Integer) - remote_addr = Column(String(16)) - name = Column(String(16)) - url = Column(String(256)) - dir = Column(String(2)) - oldfile = Column(String(256)) - newfile = Column(String(256)) - cmd = Column(LargeBinary) - dataobj = Column(LargeBinary) - tag = Column(String(50)) -#def __repr__(self): -#... return "" % ( -#... self.name, self.fullname, self.password) - - -for instance in session.query(ImCmd).order_by(ImCmd.id): - print instance.name, instance.date - - -ed_user = User(name='ed', fullname='Ed Jones', password='edspassword') -session.add(ed_user) -#session.add_all([ -#... User(name='wendy', fullname='Wendy Williams', password='foobar'), -#... User(name='mary', fullname='Mary Contrary', password='xxg527'), -#... User(name='fred', fullname='Fred Flinstone', password='blah')]) - -#session.commit() - -class Db(object): - def __init__ (self): - self.conn = None - self.cursor = None - self.connect() - - def connect (self): - self.conn = MySQLdb.connect (host = "lalalizard.com", - user = USER, - passwd = PASSWORD, - db = DATABASE - ) - self.cursor = self.conn.cursor () - - def execute (self,sql,args=()): - try: - self.cursor.execute(sql,args) - except MySQLdb.Error, e: - print "Error %d: %s" % (e.args[0], e.args[1]) - # sys.exit (1) - self.connect() - self.cursor.execute(sql,args) - - def lastinsertid (self): - return self.conn.insert_id() - - def insert_cmd ( - self, - date=time.time(), - remote_addr="NULL", - username="NULL", - url="NULL", - directory="NULL", - oldfile="NULL", - newfile="NULL", - cmd="NULL", - dataobj="NULL", - tag="NULL"): - try: - sql = "INSERT INTO im_cmd " - sql += "(date, remote_addr, name, url, dir, oldfile, newfile, cmd, dataobj, tag) " - sql += "VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)" - #or "NULL" - args = (date, remote_addr, username, url, directory, oldfile, newfile, cmd, dataobj, tag) - #args = (now(), os.environ['REMOTE_ADDR'], name, url, dir, oldfile, newfile, " ".join(cmd),dataobj) - self.execute(sql, args) - except Exception as e: - sys.stderr.write(str(e)) - return diff --git a/lib/Param/Bool.py b/lib/Param/Bool.py new file mode 100644 index 0000000..7b779cb --- /dev/null +++ b/lib/Param/Bool.py @@ -0,0 +1,19 @@ +from Param import Param +import re +import sys +class ParamBool(Param): + def __init__(self, value, classname=""): + super(ParamBool, self).__init__(classname=classname) + if value: + self.value = self._bool_correct(value) + else: + self.value = False + def _bool_correct(self, b): + if type(b) == str or type(b) == unicode: + if re.match(r'true', b, re.IGNORECASE): + return True + elif re.match(r'false', b, re.IGNORECASE): + return False + elif type(b) == bool: + return b + self.err_warn("Not a bool: %s" % str(b)) diff --git a/lib/Param/Bool/__init__.py b/lib/Param/Bool/__init__.py deleted file mode 100644 index 7b779cb..0000000 --- a/lib/Param/Bool/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -from Param import Param -import re -import sys -class ParamBool(Param): - def __init__(self, value, classname=""): - super(ParamBool, self).__init__(classname=classname) - if value: - self.value = self._bool_correct(value) - else: - self.value = False - def _bool_correct(self, b): - if type(b) == str or type(b) == unicode: - if re.match(r'true', b, re.IGNORECASE): - return True - elif re.match(r'false', b, re.IGNORECASE): - return False - elif type(b) == bool: - return b - self.err_warn("Not a bool: %s" % str(b)) diff --git a/lib/Param/Color.py b/lib/Param/Color.py new file mode 100644 index 0000000..9163338 --- /dev/null +++ b/lib/Param/Color.py @@ -0,0 +1,17 @@ +from Param import Param +import re +class ParamColor(Param): + def __init__(self, value, classname=""): + super(ParamColor, self).__init__(classname=classname) + try: + self.value = self._color_sanitize(value) + except Exception as e: + self.err_warn("Unable to sanitize the color: %s" % str(value)) + self.err_warn(str(e)) + def _color_sanitize(self, s): + if s == "": + return "transparent" + if re.match('(rgba?\([0-9]+,[0-9]+,[0-9]+\))|([a-zA-Z]+)|(\#[A-Ha-h0-9]+)', s): + return s.replace(' ', ''); + else: + self.err_warn("Not a color: {}\n".format(s)) diff --git a/lib/Param/Color/__init__.py b/lib/Param/Color/__init__.py deleted file mode 100644 index 9163338..0000000 --- a/lib/Param/Color/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -from Param import Param -import re -class ParamColor(Param): - def __init__(self, value, classname=""): - super(ParamColor, self).__init__(classname=classname) - try: - self.value = self._color_sanitize(value) - except Exception as e: - self.err_warn("Unable to sanitize the color: %s" % str(value)) - self.err_warn(str(e)) - def _color_sanitize(self, s): - if s == "": - return "transparent" - if re.match('(rgba?\([0-9]+,[0-9]+,[0-9]+\))|([a-zA-Z]+)|(\#[A-Ha-h0-9]+)', s): - return s.replace(' ', ''); - else: - self.err_warn("Not a color: {}\n".format(s)) diff --git a/lib/Param/Enum.py b/lib/Param/Enum.py new file mode 100644 index 0000000..3923a64 --- /dev/null +++ b/lib/Param/Enum.py @@ -0,0 +1,8 @@ +from Param import Param +import sys +class ParamEnum(Param): + def __init__(self, value, enum_values=[], classname=""): + super(ParamEnum,self).__init__(classname=classname) + if value not in enum_values: + return self.err_warn("Value %s not in enum values" % str(value)) + self.value = value diff --git a/lib/Param/Enum/__init__.py b/lib/Param/Enum/__init__.py deleted file mode 100644 index 3923a64..0000000 --- a/lib/Param/Enum/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -from Param import Param -import sys -class ParamEnum(Param): - def __init__(self, value, enum_values=[], classname=""): - super(ParamEnum,self).__init__(classname=classname) - if value not in enum_values: - return self.err_warn("Value %s not in enum values" % str(value)) - self.value = value diff --git a/lib/Param/Float.py b/lib/Param/Float.py new file mode 100644 index 0000000..0581815 --- /dev/null +++ b/lib/Param/Float.py @@ -0,0 +1,19 @@ +from Param import Param + +class ParamFloat(Param): + def __init__(self, value, classname=""): + self._classname = classname + super(ParamFloat, self).__init__(classname=classname) + try: + if value: + self.value = float(value) + else: + self.value = 0.0 + except Exception as e: + self.err_warn("Not a float: %s" % str(value)) + self.err_warn(str(e)) + def __int__(self): + return int(self.value) + + def __float__(self): + return float(self.value) diff --git a/lib/Param/Float/__init__.py b/lib/Param/Float/__init__.py deleted file mode 100644 index 0581815..0000000 --- a/lib/Param/Float/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -from Param import Param - -class ParamFloat(Param): - def __init__(self, value, classname=""): - self._classname = classname - super(ParamFloat, self).__init__(classname=classname) - try: - if value: - self.value = float(value) - else: - self.value = 0.0 - except Exception as e: - self.err_warn("Not a float: %s" % str(value)) - self.err_warn(str(e)) - def __int__(self): - return int(self.value) - - def __float__(self): - return float(self.value) diff --git a/lib/Param/Img_url.py b/lib/Param/Img_url.py new file mode 100644 index 0000000..55bf353 --- /dev/null +++ b/lib/Param/Img_url.py @@ -0,0 +1,98 @@ +import os +from Param import Param +from config import * +import urllib, urllib2 +from subprocess import Popen, PIPE +import sys +Request = urllib2.Request +urlencode = urllib.urlencode +urlopen = urllib2.urlopen +Request = urllib2.Request +urlencode = urllib.urlencode +urlopen = urllib2.urlopen + +import sys; +class ParamImg_url(Param): + def __init__(self, value, key="", classname=""): + super(ParamImg_url, self).__init__(classname=classname) + if value: + try: + self.filename = self._filename_temporary(key) + + self.path = os.path.join(self._working_dir, self.filename) + self._image_download(value, self.path) + self.mimetype = self._image_mimetype(self.path) + self.url = value + except Exception as e: + self.err_warn("Unable to download image: %s" % str(value)) + self.err_warn(str(e)) + + def _filename_temporary(self, s): + return "_tmp-{}-{}_{}".format(self._classname, self._now, s) + + def __dict__(self): + return { + 'filename' : self.filename, + 'path': self.path, + 'url': self.url, + 'mimetype': self.mimetype + } + + def __getitem__(self, item): + return self.__dict__().__getitem__(item) + + def __str__(self): + return str(self.__dict__()) + + def __nonzero__(self): + return True if self.path and self.mimetype else False + + def _image_download(self, url, path): + max_size = MAX_SIZE + if self.username in SPECIAL_DOWNLOADERS: + max_size = SPECIAL_DOWNLOADERS_MAX_SIZE + try: + self._download(url, path, max_size=max_size) + except Exception as e: + self.err_warn("Download failed"); + + def _browser_request (self, url, data=None): + headers = { + 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)', + 'Accept': '*/*', + } + try: + req = Request(url, data, headers) + response = urlopen(req) + except IOError as e: + if hasattr(e, 'code'): + sys.stderr.write( 'browser request error: %s - ERROR %s' % (url, e.code) ) + raise IOError + return response + + def _download(self, url, destination, max_size=MAX_SIZE): + response = self._browser_request(url, None) + + rawimg = response.read() + if len(rawimg) == 0: + self.err_warn("got zero-length file") + if len(rawimg) > max_size: + self.err_warn("file too big: max size {} KB / {} is {} KB".format( + str(MAX_SIZE/1024), + destination, + str(len(rawimg)/1024) + ) + ) + f = open(destination, "w") + f.write(rawimg) + f.close() + + def _image_mimetype(self, f): + try: + mimetype = Popen( + [BIN_IDENTIFY, f], stdout=PIPE + ).communicate()[0].split(" ")[1].lower() + return mimetype + except Exception as e: + sys.stderr.write("couldn't determine mimetype\n") + raise e; diff --git a/lib/Param/Img_url/__init__.py b/lib/Param/Img_url/__init__.py deleted file mode 100644 index 55bf353..0000000 --- a/lib/Param/Img_url/__init__.py +++ /dev/null @@ -1,98 +0,0 @@ -import os -from Param import Param -from config import * -import urllib, urllib2 -from subprocess import Popen, PIPE -import sys -Request = urllib2.Request -urlencode = urllib.urlencode -urlopen = urllib2.urlopen -Request = urllib2.Request -urlencode = urllib.urlencode -urlopen = urllib2.urlopen - -import sys; -class ParamImg_url(Param): - def __init__(self, value, key="", classname=""): - super(ParamImg_url, self).__init__(classname=classname) - if value: - try: - self.filename = self._filename_temporary(key) - - self.path = os.path.join(self._working_dir, self.filename) - self._image_download(value, self.path) - self.mimetype = self._image_mimetype(self.path) - self.url = value - except Exception as e: - self.err_warn("Unable to download image: %s" % str(value)) - self.err_warn(str(e)) - - def _filename_temporary(self, s): - return "_tmp-{}-{}_{}".format(self._classname, self._now, s) - - def __dict__(self): - return { - 'filename' : self.filename, - 'path': self.path, - 'url': self.url, - 'mimetype': self.mimetype - } - - def __getitem__(self, item): - return self.__dict__().__getitem__(item) - - def __str__(self): - return str(self.__dict__()) - - def __nonzero__(self): - return True if self.path and self.mimetype else False - - def _image_download(self, url, path): - max_size = MAX_SIZE - if self.username in SPECIAL_DOWNLOADERS: - max_size = SPECIAL_DOWNLOADERS_MAX_SIZE - try: - self._download(url, path, max_size=max_size) - except Exception as e: - self.err_warn("Download failed"); - - def _browser_request (self, url, data=None): - headers = { - 'User-Agent': 'Mozilla/4.0 (compatible; MSIE 5.5; Windows NT)', - 'Accept': '*/*', - } - try: - req = Request(url, data, headers) - response = urlopen(req) - except IOError as e: - if hasattr(e, 'code'): - sys.stderr.write( 'browser request error: %s - ERROR %s' % (url, e.code) ) - raise IOError - return response - - def _download(self, url, destination, max_size=MAX_SIZE): - response = self._browser_request(url, None) - - rawimg = response.read() - if len(rawimg) == 0: - self.err_warn("got zero-length file") - if len(rawimg) > max_size: - self.err_warn("file too big: max size {} KB / {} is {} KB".format( - str(MAX_SIZE/1024), - destination, - str(len(rawimg)/1024) - ) - ) - f = open(destination, "w") - f.write(rawimg) - f.close() - - def _image_mimetype(self, f): - try: - mimetype = Popen( - [BIN_IDENTIFY, f], stdout=PIPE - ).communicate()[0].split(" ")[1].lower() - return mimetype - except Exception as e: - sys.stderr.write("couldn't determine mimetype\n") - raise e; diff --git a/lib/Param/Int.py b/lib/Param/Int.py new file mode 100644 index 0000000..0a73cc1 --- /dev/null +++ b/lib/Param/Int.py @@ -0,0 +1,18 @@ +from Param import Param + +class ParamInt(Param): + def __init__(self, value, classname=""): + super(ParamInt, self).__init__(classname=classname) + try: + if value: + self.value = int(value) + else: + self.value = 0 + except Exception as e: + self.err_warn("Not an int: %s" % str(value)) + self.err_warn(str(e)) + def __int__(self): + return int(self.value) + + def __float__(self): + return float(self.value) diff --git a/lib/Param/Int/__init__.py b/lib/Param/Int/__init__.py deleted file mode 100644 index 0a73cc1..0000000 --- a/lib/Param/Int/__init__.py +++ /dev/null @@ -1,18 +0,0 @@ -from Param import Param - -class ParamInt(Param): - def __init__(self, value, classname=""): - super(ParamInt, self).__init__(classname=classname) - try: - if value: - self.value = int(value) - else: - self.value = 0 - except Exception as e: - self.err_warn("Not an int: %s" % str(value)) - self.err_warn(str(e)) - def __int__(self): - return int(self.value) - - def __float__(self): - return float(self.value) diff --git a/lib/Param/Json.py b/lib/Param/Json.py new file mode 100644 index 0000000..28a7126 --- /dev/null +++ b/lib/Param/Json.py @@ -0,0 +1,8 @@ +from Param import Param +import simplejson as json + +class ParamJson(Param): + def __init__(self, value, classname=""): + super(ParamJson, self).__init__(classname=classname) + self.value = json.parse(value) + diff --git a/lib/Param/Json/__init__.py b/lib/Param/Json/__init__.py deleted file mode 100644 index 28a7126..0000000 --- a/lib/Param/Json/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -from Param import Param -import simplejson as json - -class ParamJson(Param): - def __init__(self, value, classname=""): - super(ParamJson, self).__init__(classname=classname) - self.value = json.parse(value) - diff --git a/lib/Param/Raw.py b/lib/Param/Raw.py new file mode 100644 index 0000000..f8adaab --- /dev/null +++ b/lib/Param/Raw.py @@ -0,0 +1,6 @@ +from Param import Param + +class ParamRaw(Param): + def __init__(self, value, classname=""): + super(ParamRaw, self).__init__(classname=classname) + self.value = value diff --git a/lib/Param/Raw/__init__.py b/lib/Param/Raw/__init__.py deleted file mode 100644 index f8adaab..0000000 --- a/lib/Param/Raw/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from Param import Param - -class ParamRaw(Param): - def __init__(self, value, classname=""): - super(ParamRaw, self).__init__(classname=classname) - self.value = value diff --git a/lib/Param/String.py b/lib/Param/String.py new file mode 100644 index 0000000..8f08e49 --- /dev/null +++ b/lib/Param/String.py @@ -0,0 +1,15 @@ +from Param import Param +import re +import sys +class ParamString(Param): + def __init__(self, value, classname=""): + super(ParamString, self).__init__(classname=classname) + if value: + try: + self.value = self.sanitize(value) + except Exception as e: + self.err_warn("Unable to sanitize: %s\nreason:%s" % (str(value), str(e))) + else: + self.value = "" + def sanitize (self, s): + return re.sub(r'\W+', '', s) diff --git a/lib/Param/String/__init__.py b/lib/Param/String/__init__.py deleted file mode 100644 index 8f08e49..0000000 --- a/lib/Param/String/__init__.py +++ /dev/null @@ -1,15 +0,0 @@ -from Param import Param -import re -import sys -class ParamString(Param): - def __init__(self, value, classname=""): - super(ParamString, self).__init__(classname=classname) - if value: - try: - self.value = self.sanitize(value) - except Exception as e: - self.err_warn("Unable to sanitize: %s\nreason:%s" % (str(value), str(e))) - else: - self.value = "" - def sanitize (self, s): - return re.sub(r'\W+', '', s) diff --git a/lib/Params.py b/lib/Params.py new file mode 100644 index 0000000..e3ba10b --- /dev/null +++ b/lib/Params.py @@ -0,0 +1,65 @@ +import re +import os +import sys +from Param import * + +class BadParamError(Exception): + pass + +class Params(object): + def __init__(self, **kwargs): + for key, value in kwargs.items(): + setattr(self, key, value) + + def __iter__(self): + for key, value in vars(self).iteritems(): + yield key, value + + def _error_log(self, s, error=None, fatal=False): + message = "ERROR - BAD PARAM" + if fatal: message += "- [FATAL] -" + sys.stderr.write("{}:{} - {}\n".format(message, self._classname, s)) + if error: + sys.stderr.write("PARAM ERROR: {}\n".format(str(error))) + + def err_warn(self, s, error=None): + self._error_log(s, error=error); + raise BadParamError("%s - %s" % (self._classname, s)) + + def __getattr__(self, key): + try: + return self.__getattribute__(key); + except AttributeError: + return None + + def definitions_import(self, def_dict, classkwargs, classname=""): + value = None + for key in def_dict.keys(): + try: + value = None + if key in classkwargs: + value = classkwargs[key] + elif 'default' in def_dict[key]: + value = def_dict[key]['default'] + if def_dict[key]['type'] == "bool": + instance = ParamBool(value, classname=classname) + elif def_dict[key]['type'] == "color": + instance = ParamColor(value, classname=classname) + elif def_dict[key]['type'] == "enum": + instance = ParamEnum(value, enum_values=def_dict[key]['enum_values'], classname=classname) + elif def_dict[key]['type'] == "float": + instance = ParamFloat(value, classname=classname) + elif def_dict[key]['type'] == "img_url": + instance = ParamImg_url(value, key=key, classname=classname) + elif def_dict[key]['type'] == "int": + instance = ParamInt(value, classname=classname) + elif def_dict[key]['type'] == "json": + instance = ParamJson(value, classname=classname) + elif def_dict[key]['type'] == "raw": + instance = ParamRaw(value, classname=classname) + elif def_dict[key]['type'] == "string": + instance = ParamString(value, classname=classname) + self.__setattr__(key, instance) + except Exception as e: + self.err_warn("key: %s value: %s" % (key, str(def_dict[key])), error=str(e)) + diff --git a/lib/Params/__init__.py b/lib/Params/__init__.py deleted file mode 100644 index e3ba10b..0000000 --- a/lib/Params/__init__.py +++ /dev/null @@ -1,65 +0,0 @@ -import re -import os -import sys -from Param import * - -class BadParamError(Exception): - pass - -class Params(object): - def __init__(self, **kwargs): - for key, value in kwargs.items(): - setattr(self, key, value) - - def __iter__(self): - for key, value in vars(self).iteritems(): - yield key, value - - def _error_log(self, s, error=None, fatal=False): - message = "ERROR - BAD PARAM" - if fatal: message += "- [FATAL] -" - sys.stderr.write("{}:{} - {}\n".format(message, self._classname, s)) - if error: - sys.stderr.write("PARAM ERROR: {}\n".format(str(error))) - - def err_warn(self, s, error=None): - self._error_log(s, error=error); - raise BadParamError("%s - %s" % (self._classname, s)) - - def __getattr__(self, key): - try: - return self.__getattribute__(key); - except AttributeError: - return None - - def definitions_import(self, def_dict, classkwargs, classname=""): - value = None - for key in def_dict.keys(): - try: - value = None - if key in classkwargs: - value = classkwargs[key] - elif 'default' in def_dict[key]: - value = def_dict[key]['default'] - if def_dict[key]['type'] == "bool": - instance = ParamBool(value, classname=classname) - elif def_dict[key]['type'] == "color": - instance = ParamColor(value, classname=classname) - elif def_dict[key]['type'] == "enum": - instance = ParamEnum(value, enum_values=def_dict[key]['enum_values'], classname=classname) - elif def_dict[key]['type'] == "float": - instance = ParamFloat(value, classname=classname) - elif def_dict[key]['type'] == "img_url": - instance = ParamImg_url(value, key=key, classname=classname) - elif def_dict[key]['type'] == "int": - instance = ParamInt(value, classname=classname) - elif def_dict[key]['type'] == "json": - instance = ParamJson(value, classname=classname) - elif def_dict[key]['type'] == "raw": - instance = ParamRaw(value, classname=classname) - elif def_dict[key]['type'] == "string": - instance = ParamString(value, classname=classname) - self.__setattr__(key, instance) - except Exception as e: - self.err_warn("key: %s value: %s" % (key, str(def_dict[key])), error=str(e)) - diff --git a/lib/Pb/Break.py b/lib/Pb/Break.py new file mode 100755 index 0000000..b7edfb1 --- /dev/null +++ b/lib/Pb/Break.py @@ -0,0 +1,171 @@ +#!/usr/bin/python2.7 +import os +import sys +import random +import re +import urllib +import inspect +from config import * +from Pb import Pb +from Params import Params + +DEFAULT_FINALFORMAT = "png"; + +_subtle_break_mark = 'pron' +_extreme_break_mark = 'sugar' + +_header_offset = 2000 +_default_breakmode = "subtle" + +class PbBreak(Pb): #FIXME in db gallery + example_params = { + "url" : "http://i.asdf.us/im/de/HolyMountain2_1322275112_seamonkey.gif", + "breaktype" : "RGB_WASH", + "finalformat" : "png", + "breakmode" : "extreme", + "breakangle" : "10", + "username" : "donkey", + "expanded" : "false" + } + def __init__(self, **kwargs): + super(PbBreak,self).__init__(**kwargs); + _definitions = { + 'username': { 'type': 'string' }, + 'breaktype': { 'type': 'string' }, + 'breakmode': { + 'type': 'enum', + 'enum_values' : ['subtle', 'extreme', 'gradual'] , + 'default' : _default_breakmode + }, + 'breakangle': { 'type': 'float' }, + 'expanded': { 'type': 'bool' }, + 'url': { 'type': 'img_url' }, + 'finalformat': { 'type': 'enum', 'enum_values' : ['png', 'gif', 'jpg' ] } + } + self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); + self._files_created.append(self.params.url.path) + self.params.breaktype.set_val(self._get_breaktype(str(self.params.breaktype))) + + #psd returns an animation + if not self.params.finalformat and self.params.url.mimetype == "gif": + self.params.finalformat.set_val("gif") + elif self.params.breaktype == 'miff': + self.params.finalformat.set_val("jpg") + self.params.breakmode.set_val("subtle") + elif not self.params.finalformat: + self.params.finalformat.set_val(DEFAULT_FINALFORMAT) + self._width_and_height_set(filepath=self.params.url.path) + + self.filename, self.filepath = self._filename_filepath_create(url=self.params.url.url, extension=self.params.finalformat) + self._conversion_file = self._tempfilepath_create(namepart="conversion", extension=self.params.breaktype) + + self._db_url_param = str(self.params.url['url']) + + def _get_breaktype(self, key): + #{{{ conversion table + breaktypeTranslate = { + 'CLASSIC':'jpg', + 'REDUX':'pcds', + 'BLURRY_BREAK':'viff', + 'BLURRY_BREAK_2':'mat', + 'SWIPE':'miff', + 'RGB_WASH':'psd', + 'RGB_WASH_2':'psb', + 'NOISY_BREAK':'palm', + 'NOISY_BREAK_2':'fig', + 'BROKEN_VIGNETTE':'pbm', + 'FAX_MACHINE':'cals', + 'STRIPES':'exr', + 'PHOTOCOPY':'art', + } + #}}} + return breaktypeTranslate[key] + +#{{{#########rotatefunctions####################################### + def _rotate(self): + cmd = [BIN_CONVERT,self.params.url.path,"-rotate",self.params.breakangle,"+repage",self.params.url.path] + self._call_cmd(cmd) + + def _rotate_back(self): + angle = str(360-int(self.params.breakangle)) + cmd = [BIN_CONVERT,self.filepath,"-rotate",angle,"+repage",self.filepath] + self._call_cmd(cmd) + if not self.params.expanded: + cmd = [BIN_CONVERT,self.filepath,"-gravity","Center","-crop","{}x{}+0+0".format( + self.width, self.height),"+repage",self.filepath] + self._call_cmd(cmd) +#}}} + + def _subtle_break(self): + #assume the header is no longer than _header_offset bytes + breakpoint = random.randint(_header_offset, len(self._file_data)) + newfile = self._file_data[0:breakpoint] \ + + _subtle_break_mark \ + + self._file_data[breakpoint:] + self._file_data = newfile[0:len(self._file_data)] + + def _extreme_break(self): + increment = len(self._file_data)/10; + i = 0 + newfile = ""; + for b in self._file_data: + if i > _header_offset and not (i % increment): + b += _extreme_break_mark + newfile += b + i += 1 + self._file_data = newfile[0:len(self._file_data)] + + + def _enforce_jpg(self): + if self.params.breaktype in [ "exr", "bmp", "miff" ] and not re.match(r'jpe?g$', self.params.url.mimetype, re.IGNORECASE): + jpg_file = self._tempfilepath_create(extension="jpg") + self._call_cmd([BIN_CONVERT,self.params.url.path, jpg_file]) + self._files_created.append(jpg_file) + self._conversion_file = jpg_file + + def _first_conversion(self): + if self.params.url.mimetype == self.params.breaktype: + self._conversion_file = self.params.url.path + return + self._call_cmd([BIN_CONVERT, self.params.url.path, self._conversion_file]) + self._files_created.append(self._conversion_file) + + def _prepare_filedata(self): + if self.params.url.mimetype == "gif" and self.params.breaktype not in [ 'mat', 'psd' ]: + self._choose_gif_frame(self.params.url.path) + if self.params.breakangle: + self._rotate() + self._enforce_jpg(); + self._first_conversion(); + self._file_data = self._file_read(self._conversion_file) + if not self._file_data: + self.err_warn("Unable to get file data"); + + def _add_false_data(self): + if self.params.breakmode == "subtle": + self._subtle_break() + elif self.params.breakmode == "extreme": + self._extreme_break() + f = open(self._conversion_file, 'w') + f.write(self._file_data) + f.close(); + + def _final_conversion(self): + self._call_cmd( [BIN_CONVERT, self._conversion_file, self.filepath]) + def psd_psbfilepath(num): + return os.path.join(re.sub(r'\.', "-%s." % num, self.filepath)) + if str(self.params.breaktype) == 'psd': + self._call_cmd(['mv', psd_psbfilepath(1), self.filepath]) + self._files_created.append(psd_psbfilepath(0)) + if str(self.params.breaktype) == 'psb': + self._call_cmd(['mv', psd_psbfilepath(0), self.filepath]) + self._files_created.append(psd_psbfilepath(1)) + if self.params.breakangle: + self._rotate_back() + + def create(self): + self._prepare_filedata(); + self._add_false_data(); + self._final_conversion() + super(PbBreak, self).create() + diff --git a/lib/Pb/Break/__init__.py b/lib/Pb/Break/__init__.py deleted file mode 100755 index b7edfb1..0000000 --- a/lib/Pb/Break/__init__.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/python2.7 -import os -import sys -import random -import re -import urllib -import inspect -from config import * -from Pb import Pb -from Params import Params - -DEFAULT_FINALFORMAT = "png"; - -_subtle_break_mark = 'pron' -_extreme_break_mark = 'sugar' - -_header_offset = 2000 -_default_breakmode = "subtle" - -class PbBreak(Pb): #FIXME in db gallery - example_params = { - "url" : "http://i.asdf.us/im/de/HolyMountain2_1322275112_seamonkey.gif", - "breaktype" : "RGB_WASH", - "finalformat" : "png", - "breakmode" : "extreme", - "breakangle" : "10", - "username" : "donkey", - "expanded" : "false" - } - def __init__(self, **kwargs): - super(PbBreak,self).__init__(**kwargs); - _definitions = { - 'username': { 'type': 'string' }, - 'breaktype': { 'type': 'string' }, - 'breakmode': { - 'type': 'enum', - 'enum_values' : ['subtle', 'extreme', 'gradual'] , - 'default' : _default_breakmode - }, - 'breakangle': { 'type': 'float' }, - 'expanded': { 'type': 'bool' }, - 'url': { 'type': 'img_url' }, - 'finalformat': { 'type': 'enum', 'enum_values' : ['png', 'gif', 'jpg' ] } - } - self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); - self._files_created.append(self.params.url.path) - self.params.breaktype.set_val(self._get_breaktype(str(self.params.breaktype))) - - #psd returns an animation - if not self.params.finalformat and self.params.url.mimetype == "gif": - self.params.finalformat.set_val("gif") - elif self.params.breaktype == 'miff': - self.params.finalformat.set_val("jpg") - self.params.breakmode.set_val("subtle") - elif not self.params.finalformat: - self.params.finalformat.set_val(DEFAULT_FINALFORMAT) - self._width_and_height_set(filepath=self.params.url.path) - - self.filename, self.filepath = self._filename_filepath_create(url=self.params.url.url, extension=self.params.finalformat) - self._conversion_file = self._tempfilepath_create(namepart="conversion", extension=self.params.breaktype) - - self._db_url_param = str(self.params.url['url']) - - def _get_breaktype(self, key): - #{{{ conversion table - breaktypeTranslate = { - 'CLASSIC':'jpg', - 'REDUX':'pcds', - 'BLURRY_BREAK':'viff', - 'BLURRY_BREAK_2':'mat', - 'SWIPE':'miff', - 'RGB_WASH':'psd', - 'RGB_WASH_2':'psb', - 'NOISY_BREAK':'palm', - 'NOISY_BREAK_2':'fig', - 'BROKEN_VIGNETTE':'pbm', - 'FAX_MACHINE':'cals', - 'STRIPES':'exr', - 'PHOTOCOPY':'art', - } - #}}} - return breaktypeTranslate[key] - -#{{{#########rotatefunctions####################################### - def _rotate(self): - cmd = [BIN_CONVERT,self.params.url.path,"-rotate",self.params.breakangle,"+repage",self.params.url.path] - self._call_cmd(cmd) - - def _rotate_back(self): - angle = str(360-int(self.params.breakangle)) - cmd = [BIN_CONVERT,self.filepath,"-rotate",angle,"+repage",self.filepath] - self._call_cmd(cmd) - if not self.params.expanded: - cmd = [BIN_CONVERT,self.filepath,"-gravity","Center","-crop","{}x{}+0+0".format( - self.width, self.height),"+repage",self.filepath] - self._call_cmd(cmd) -#}}} - - def _subtle_break(self): - #assume the header is no longer than _header_offset bytes - breakpoint = random.randint(_header_offset, len(self._file_data)) - newfile = self._file_data[0:breakpoint] \ - + _subtle_break_mark \ - + self._file_data[breakpoint:] - self._file_data = newfile[0:len(self._file_data)] - - def _extreme_break(self): - increment = len(self._file_data)/10; - i = 0 - newfile = ""; - for b in self._file_data: - if i > _header_offset and not (i % increment): - b += _extreme_break_mark - newfile += b - i += 1 - self._file_data = newfile[0:len(self._file_data)] - - - def _enforce_jpg(self): - if self.params.breaktype in [ "exr", "bmp", "miff" ] and not re.match(r'jpe?g$', self.params.url.mimetype, re.IGNORECASE): - jpg_file = self._tempfilepath_create(extension="jpg") - self._call_cmd([BIN_CONVERT,self.params.url.path, jpg_file]) - self._files_created.append(jpg_file) - self._conversion_file = jpg_file - - def _first_conversion(self): - if self.params.url.mimetype == self.params.breaktype: - self._conversion_file = self.params.url.path - return - self._call_cmd([BIN_CONVERT, self.params.url.path, self._conversion_file]) - self._files_created.append(self._conversion_file) - - def _prepare_filedata(self): - if self.params.url.mimetype == "gif" and self.params.breaktype not in [ 'mat', 'psd' ]: - self._choose_gif_frame(self.params.url.path) - if self.params.breakangle: - self._rotate() - self._enforce_jpg(); - self._first_conversion(); - self._file_data = self._file_read(self._conversion_file) - if not self._file_data: - self.err_warn("Unable to get file data"); - - def _add_false_data(self): - if self.params.breakmode == "subtle": - self._subtle_break() - elif self.params.breakmode == "extreme": - self._extreme_break() - f = open(self._conversion_file, 'w') - f.write(self._file_data) - f.close(); - - def _final_conversion(self): - self._call_cmd( [BIN_CONVERT, self._conversion_file, self.filepath]) - def psd_psbfilepath(num): - return os.path.join(re.sub(r'\.', "-%s." % num, self.filepath)) - if str(self.params.breaktype) == 'psd': - self._call_cmd(['mv', psd_psbfilepath(1), self.filepath]) - self._files_created.append(psd_psbfilepath(0)) - if str(self.params.breaktype) == 'psb': - self._call_cmd(['mv', psd_psbfilepath(0), self.filepath]) - self._files_created.append(psd_psbfilepath(1)) - if self.params.breakangle: - self._rotate_back() - - def create(self): - self._prepare_filedata(); - self._add_false_data(); - self._final_conversion() - super(PbBreak, self).create() - diff --git a/lib/Pb/Break/__init__.py~ b/lib/Pb/Break/__init__.py~ deleted file mode 100755 index 64d9cc6..0000000 --- a/lib/Pb/Break/__init__.py~ +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/python2.7 -import os -import sys -import random -import re -import urllib -import inspect -from config import * -from Pb import Pb -from Pb.Params import Params - -DEFAULT_FINALFORMAT = "png"; -SUBTLE_BREAK_MARK = 'pron' -EXTREME_BREAK_MARK = 'sugar' - -HEADER_OFFSET = 2000 - -class Breaker(Pb): - def __init__(self, url=None, breaktype=None, finalformat=DEFAULT_FINALFORMAT, - breakmode=None, breakangle=None, username=None, expanded=None, firsttime=None): - super(Breaker,self).__init__(); - - self.params.breaktype = self._get_breaktype(breaktype); - self.params.url = url - - _frame = inspect.currentframe(); - _args_vals = inspect.getargvalues(_frame); - for arg in _args_vals.args: - if arg == "self": - continue - sys.stderr.write(str(arg) + "\n") - try: - if arg not in ['breaktype', 'url']: - sys.stderr.write("Yoooo"); - sys.stderr.write(arg) - strarg = str(_args_vals.locals.get(arg)) - django self.bool_correct(strarg) - self.params.__setattr__("dingo", django) -# self.params.__setattr__(arg, self.bool_correct(_args_vals.locals.get(arg))) - except Exception as e: - sys.stderr.write("\n"+str(e)+"\n") - sys.exit(1); - self.params = Params(**self.params); - - self.tag = "imBreak" - self.commands = []; - self._now = self.now() - self.files_created = [] - - self.basename, self._first_format = self._get_filename_and_type_from_url(); - self._downloaded_file = self.tempname_create(basename=self.basename, fmt=self._first_format) - - try: - self.download(self.params.url, self._downloaded_file) - self.files_created.append(self._downloaded_file) - except Exception as e: - self.err_warn(str(e)) - - self._gif_frames = self.gif_frames(self._downloaded_file) - self._gif_frames = self._gif_frames if len(self._gif_frames) > 1 else False - self.width, self.height = self.dimensions(self._downloaded_file) # same here - - if not self.params.finalformat and self._gif_frames: - self.params.finalformat = 'gif' - if self.params.breaktype == 'miff': - self.params.finalformat = 'jpg' - self.params.breakmode = 'subtle' - #final filepath is stored in self.filepath - self.filename = "{}.{}".format(self.basename, self.params.finalformat) - self.filepath = os.path.join(self._working_dir, self.filename) - self._conversion_file = self.tempname_create(basename=self.basename, fmt=self.params.breaktype); - - def _call_cmd(self, cmd): - super(Breaker,self)._call_cmd(cmd, error) - self.commands.append(" ".join(cmd)); - - def _get_breaktype(self, key): - #{{{ conversion table - breaktypeTranslate = { - 'CLASSIC':'jpg', - 'REDUX':'pcds', - 'BLURRY_BREAK':'viff', - 'BLURRY_BREAK_2':'mat', - 'SWIPE':'miff', - 'RGB_WASH':'psd', - 'RGB_WASH_2':'psb', - 'NOISY_BREAK':'palm', - 'NOISY_BREAK_2':'fig', - 'BROKEN_VIGNETTE':'pbm', - 'FAX_MACHINE':'cals', - 'STRIPES':'exr', - 'PHOTOCOPY':'art', - } - #}}} - return breaktypeTranslate[key] - -#{{{#########rotatefunctions####################################### - def _rotate(self): - cmd = [BIN_CONVERT,self._downloaded_file,"-rotate",self.params.breakangle,"+repage",self._downloaded_file] - self._call_cmd(cmd) - - def _rotate_back(self): - angle = str(360-int(self.params.breakangle)) - cmd = [BIN_CONVERT,self.filepath,"-rotate",angle,"+repage",self.filepath] - self._call_cmd(cmd) - if not self.params.expanded: - cmd = [BIN_CONVERT,self.filepath,"-gravity","Center","-crop","{}x{}+0+0".format( - self.width, self.height),"+repage",self.filepath] - self._call_cmd(cmd) -#}}} - def _subtle_break(self): - #assume the header is no longer than HEADER_OFFSET bytes - breakpoint = random.randint(HEADER_OFFSET, len(self.file_data)) - newfile = self.file_data[0:breakpoint] \ - + SUBTLE_BREAK_MARK \ - + self.file_data[breakpoint:] - self.file_data = newfile[0:len(self.file_data)] - - def _extreme_break(self): - increment = len(self.file_data)/10; - i = 0 - newfile = ""; - for b in self.file_data: - if i > HEADER_OFFSET and not (i % increment): - b += EXTREME_BREAK_MARK - newfile += b - i += 1 - self.file_data = newfile[0:len(self.file_data)] - - def _choose_frame(self): - frame = random.choice(self._gif_frames) - self._call_cmd([BIN_CONVERT, frame, self._downloaded_file]) - - def _enforce_jpg(self): - if self.params.breaktype in [ "exr", "bmp", "miff" ] and not re.match(r'jpe?g$', self._first_format, re.IGNORECASE): - jpg_file = self.tempname_create(basename=self.basename, fmt="jpg") - self._call_cmd([BIN_CONVERT,self._downloaded_file,jpg_file]) - self._call_cmd(["rm",self._downloaded_file]) - self._downloaded_file = jpg_file - - def _first_conversion(self): - if self._first_format == self.params.breaktype: - self._downloaded_file = self._conversion_file - return - self._call_cmd([BIN_CONVERT, self._downloaded_file, self._conversion_file]) - self.files_created.append(self._conversion_file) - - def _prepare_filedata(self): - if self._gif_frames: - self._choose_frame() - if self.params.breakangle: - self._rotate() - self._enforce_jpg(); - self._first_conversion(); - self.file_data = self._file_read(self._conversion_file) - if not self.file_data: - self.err_warn("Unable to get file data"); - - def _add_false_data(self, breakmode): - if breakmode == "subtle": - self._subtle_break() - elif breakmode == "extreme": - self._extreme_break() - f = open(self._conversion_file, 'w') - f.write(self.file_data) - f.close(); - - def _final_conversion(self): - self._call_cmd( [BIN_CONVERT, self._conversion_file, self.filepath]) - def psd_psbfilepath(num): - return os.path.join(self._working_dir, "{}-{}.{}".format(self.basename, num, self.params.finalformat)) - if self.params.breaktype == 'psd': - self._call_cmd(['mv', psd_psbfilepath(1), self.filepath]) - self.files_created.append(psd_psbfilepath(0)) - if self.params.breaktype == 'psb': - self._call_cmd(['mv', psd_psbfilepath(0), self.filepath]) - self.files_created.append(psd_psbfilepath(1)) - if self.params.breakangle: - self._rotate_back() - - def _cleanup(self): - cmd = ["rm"]+self.files_created - self._call_cmd(cmd) - - def create(self, breakmode=""): - if not breakmode: breakmode = self.params.breakmode - self._prepare_filedata(); - self._add_false_data(breakmode); - self._final_conversion() - self._cleanup() - - @classmethod - def test(cls): - TEST_PARAMS = { - "url" : "http://i.asdf.us/im/27/1424816234661dumpfmpfifferkinggr_1424816412_pfifferking.gif" , - "breaktype" : "RGB_WASH", - "finalformat" : "png", - "breakmode" : "extreme", - "breakangle" : "10", - "username" : "donkey", - "expanded" : "false" - } - b = cls(**TEST_PARAMS) - b.create(); - print b.filepath diff --git a/lib/Pb/Generate.py b/lib/Pb/Generate.py new file mode 100755 index 0000000..e631002 --- /dev/null +++ b/lib/Pb/Generate.py @@ -0,0 +1,140 @@ +#!/usr/bin/python2.7 +import sys +import os +from config import * +from Pb import Pb +_default_tag = "im" + +_gravity_params = ["NorthWest","North","NorthEast","West","Center","East","SouthWest","South","SouthEast"] +_gravity_default = "Center" +_compose_params = [ "Over", "ATop", "Dst_Over", "Dst_In", "Dst_Out", "Multiply", + "Screen", "Divide", "Plus", "Difference", "Exclusion", + "Lighten", "Darken", "Overlay", "Hard_Light", "Soft_Light", + "Linear_Dodge", "Linear_Burn", "Color_Dodge", "Color_Burn" ] +_dispose_params = ["None","Previous","Background"] +_dispose_default = "None" +class PbGenerate(Pb): + example_params = { +#{{{ example params + 'nearest': 'true', + # 'height': None, + 'compose': 'Soft_Light', + 'coalesce': 'true', + 'dispose': 'None', + 'gravity': 'Center', + 'width': '200', + 'black': 'black', + 'tile': 'true', + 'white': 'white', + 'contrast': '100', + 'hue': '90', + 'saturation': '100', + 'merge_early': 'true', + 'format': 'gif', + 'background': 'http://i.asdf.us/im/bc/new_1430440747.gif', + 'subtract': '#EE7AE9', + 'transparent': 'true', + # 'rotate': None, + 'name': 'yo', + # 'brightness': None, + 'url': 'http://asdf.us/im/new.gif', + 'flop': 'true', + 'flip': 'false', + 'callback': 'jsonp1430442384162', + 'fuzz': '5' +#}}} + } + def __init__(self, **kwargs): + super(PbGenerate,self).__init__(**kwargs); + _definitions = { + #IMAGES + "url": { 'type': "img_url" }, + "background": { 'type': "img_url" }, + + #BOOLS + "coalesce": { 'type': "bool" }, + "nearest": { 'type': "bool" }, + "merge_early": { 'type': "bool" }, + "flip": { 'type': "bool" }, + "flop": { 'type': "bool" }, + "tile": { 'type': "bool" }, + "transparent": { 'type': "bool" }, + + #COLORS + "black": { 'type': "color", 'default': 'black' }, + "white": { 'type': "color", 'default': 'white' }, + "subtract": { 'type': "color" }, + + #INTS + "fuzz": { 'type': "int" }, + "width": { 'type': "int" }, + "height": { 'type': "int" }, + "brightness": { 'type': "int" }, + "contrast": { 'type': "int" }, + "saturation": { 'type': "int" }, + "rotate": { 'type': "int" }, + "hue": { 'type': "int" }, + + #ENUMS + "compose": { 'type': "enum", 'enum_values': _compose_params, 'default': "Atop" }, + "gravity": { 'type': "enum", 'enum_values': _gravity_params, 'default': _gravity_default }, + "dispose": { 'type': "enum", 'enum_values': _dispose_params, 'default': "None" }, + "format": { 'type': "enum", 'enum_values': OUTPUT_IMAGE_TYPES, 'default': DEFAULT_FINALFORMAT }, + + #STRINGS + "username": { 'type': "string" }, + "callback": { 'type': "string" }, + } + self.tag = _default_tag + self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); + if self.params.background: self.tag = self.params.compose + if self.params.transparent: self.tag = self.params.transparent + + self.filename, self.filepath = self._filename_filepath_create(url=self.params.url['url'], extension=self.params.format) + + self._db_url_param = str(self.params.url['url']) + + def _composite (self): + cmd = [ + BIN_CONVERT, self.params.background['path'], + "null:", self.filepath, "-matte", + "-dispose", self.params.dispose, + "-gravity", self.params.gravity, + "-compose", self.params.compose, "-layers", "composite", + self.filepath ] + self._call_cmd(cmd); + + def _convert(self): + cmd = [BIN_CONVERT, self.params.url['path'] ] + if self.params.rotate: cmd += ["-rotate", self.params.rotate ] + if self.params.flip: cmd += ["-flip"] + if self.params.flop: cmd += ["-flop"] + if self.params.transparent: + if self.params.fuzz: + cmd += ["-fuzz", "{}%".format(self.params.fuzz) ] + cmd += [ "-transparent", self.params.subtract ] + if self.params.width or self.params.height: + if self.params.nearest and self.params.format == "gif": + cmd += [ "-coalesce","+map","-interpolate","Nearest","-interpolative-resize" ] + else: + cmd.append("-resize") + cmd += [ "{}x{}".format(self.params.width or "", self.params.height or "") ] + if self.params.black != "black" or self.params.white != 'white': + cmd += [ "+level-colors" , "{},{}".format(self.params.black, self.params.white) ] + if self.params.contrast: cmd += [ '-contrast-stretch', self.params.contrast ] + if self.params.brightness or self.params.saturation or self.params.hue: + cmd += [ + "-modulate", "{},{},{}".format( + (self.params.brightness or 100), + (self.params.contrast or 100), + (self.params.hue or 100) + )] + cmd.append("-coalesce"); #why? #FIXME + cmd += [ self.filepath ]; + self._call_cmd(cmd); + + def create(self): + self._convert() + if self.params.background: + self._composite() + super(PbGenerate, self).create() diff --git a/lib/Pb/Generate/__init__.py b/lib/Pb/Generate/__init__.py deleted file mode 100755 index e631002..0000000 --- a/lib/Pb/Generate/__init__.py +++ /dev/null @@ -1,140 +0,0 @@ -#!/usr/bin/python2.7 -import sys -import os -from config import * -from Pb import Pb -_default_tag = "im" - -_gravity_params = ["NorthWest","North","NorthEast","West","Center","East","SouthWest","South","SouthEast"] -_gravity_default = "Center" -_compose_params = [ "Over", "ATop", "Dst_Over", "Dst_In", "Dst_Out", "Multiply", - "Screen", "Divide", "Plus", "Difference", "Exclusion", - "Lighten", "Darken", "Overlay", "Hard_Light", "Soft_Light", - "Linear_Dodge", "Linear_Burn", "Color_Dodge", "Color_Burn" ] -_dispose_params = ["None","Previous","Background"] -_dispose_default = "None" -class PbGenerate(Pb): - example_params = { -#{{{ example params - 'nearest': 'true', - # 'height': None, - 'compose': 'Soft_Light', - 'coalesce': 'true', - 'dispose': 'None', - 'gravity': 'Center', - 'width': '200', - 'black': 'black', - 'tile': 'true', - 'white': 'white', - 'contrast': '100', - 'hue': '90', - 'saturation': '100', - 'merge_early': 'true', - 'format': 'gif', - 'background': 'http://i.asdf.us/im/bc/new_1430440747.gif', - 'subtract': '#EE7AE9', - 'transparent': 'true', - # 'rotate': None, - 'name': 'yo', - # 'brightness': None, - 'url': 'http://asdf.us/im/new.gif', - 'flop': 'true', - 'flip': 'false', - 'callback': 'jsonp1430442384162', - 'fuzz': '5' -#}}} - } - def __init__(self, **kwargs): - super(PbGenerate,self).__init__(**kwargs); - _definitions = { - #IMAGES - "url": { 'type': "img_url" }, - "background": { 'type': "img_url" }, - - #BOOLS - "coalesce": { 'type': "bool" }, - "nearest": { 'type': "bool" }, - "merge_early": { 'type': "bool" }, - "flip": { 'type': "bool" }, - "flop": { 'type': "bool" }, - "tile": { 'type': "bool" }, - "transparent": { 'type': "bool" }, - - #COLORS - "black": { 'type': "color", 'default': 'black' }, - "white": { 'type': "color", 'default': 'white' }, - "subtract": { 'type': "color" }, - - #INTS - "fuzz": { 'type': "int" }, - "width": { 'type': "int" }, - "height": { 'type': "int" }, - "brightness": { 'type': "int" }, - "contrast": { 'type': "int" }, - "saturation": { 'type': "int" }, - "rotate": { 'type': "int" }, - "hue": { 'type': "int" }, - - #ENUMS - "compose": { 'type': "enum", 'enum_values': _compose_params, 'default': "Atop" }, - "gravity": { 'type': "enum", 'enum_values': _gravity_params, 'default': _gravity_default }, - "dispose": { 'type': "enum", 'enum_values': _dispose_params, 'default': "None" }, - "format": { 'type': "enum", 'enum_values': OUTPUT_IMAGE_TYPES, 'default': DEFAULT_FINALFORMAT }, - - #STRINGS - "username": { 'type': "string" }, - "callback": { 'type': "string" }, - } - self.tag = _default_tag - self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); - if self.params.background: self.tag = self.params.compose - if self.params.transparent: self.tag = self.params.transparent - - self.filename, self.filepath = self._filename_filepath_create(url=self.params.url['url'], extension=self.params.format) - - self._db_url_param = str(self.params.url['url']) - - def _composite (self): - cmd = [ - BIN_CONVERT, self.params.background['path'], - "null:", self.filepath, "-matte", - "-dispose", self.params.dispose, - "-gravity", self.params.gravity, - "-compose", self.params.compose, "-layers", "composite", - self.filepath ] - self._call_cmd(cmd); - - def _convert(self): - cmd = [BIN_CONVERT, self.params.url['path'] ] - if self.params.rotate: cmd += ["-rotate", self.params.rotate ] - if self.params.flip: cmd += ["-flip"] - if self.params.flop: cmd += ["-flop"] - if self.params.transparent: - if self.params.fuzz: - cmd += ["-fuzz", "{}%".format(self.params.fuzz) ] - cmd += [ "-transparent", self.params.subtract ] - if self.params.width or self.params.height: - if self.params.nearest and self.params.format == "gif": - cmd += [ "-coalesce","+map","-interpolate","Nearest","-interpolative-resize" ] - else: - cmd.append("-resize") - cmd += [ "{}x{}".format(self.params.width or "", self.params.height or "") ] - if self.params.black != "black" or self.params.white != 'white': - cmd += [ "+level-colors" , "{},{}".format(self.params.black, self.params.white) ] - if self.params.contrast: cmd += [ '-contrast-stretch', self.params.contrast ] - if self.params.brightness or self.params.saturation or self.params.hue: - cmd += [ - "-modulate", "{},{},{}".format( - (self.params.brightness or 100), - (self.params.contrast or 100), - (self.params.hue or 100) - )] - cmd.append("-coalesce"); #why? #FIXME - cmd += [ self.filepath ]; - self._call_cmd(cmd); - - def create(self): - self._convert() - if self.params.background: - self._composite() - super(PbGenerate, self).create() diff --git a/lib/Pb/Gradient.py b/lib/Pb/Gradient.py new file mode 100755 index 0000000..340ce62 --- /dev/null +++ b/lib/Pb/Gradient.py @@ -0,0 +1,183 @@ +#!/usr/bin/python2.7 +import re +import time +from subprocess import call +import simplejson as json +import sys +import os +import sha +from config import * +from Pb import Pb + +_default_color_1 = "white" +_default_color_2 = "black" + +_default_bevel_percent = "12"; + +_halftone_values = { + "checkeredfade": "h6x6a", + "etchedtransition": "o8x8", + "bendaydots": "h16x16o", + "smallerdots1": "h8x8o", + "smallerdots2": "c7x7w", + "flatstripes": "o2x2", +} + +class PbGradient(Pb): + example_params = { + "width" : "200", + "color1" : "#ffdead", + "color2" : "blue", + "stripes" : "true", + "stripenumber" : "20", + "gradienttype" : "radial", + "stripeintensity" : "20", + "halftone" : "checkeredfade", + "percentbeveled" : "30", + "flip" : "true", + "bevel" : "flatinner", + "rotate" : "20", + "height" : "200", + "filetype" : "jpg", + "username" : "whatever" + } + def __init__(self, **kwargs): + super(PbGradient,self).__init__(**kwargs); + _definitions = { + 'width': { 'type':'int', 'default': DEFAULT_WIDTH }, + 'height': { 'type':'int', 'default' : DEFAULT_HEIGHT }, + 'color1': { 'type':'color', 'default': _default_color_1 }, + 'color2': { 'type':'color', 'default': _default_color_2 }, + 'stripes': { 'type':'bool' }, + 'stripenumber': { 'type':'int', 'default': 0 }, + 'stripeintensity': { 'type':'int', 'default': 0 }, + 'blurriness': { 'type':'int', 'default': 0 }, + 'contrast': { 'type':'int', 'default': 100 }, + 'brightness': { 'type':'int', 'default': 100 }, + 'saturation': { 'type':'int', 'default': 100 }, + 'hue': { 'type':'int', 'default': 100 }, + 'halftone': { 'type':'enum', 'enum_values' : [ + 'checkeredfade', 'etchedtransition', 'bendaydots', + 'smallerdots1', 'smallerdots2', 'flatstripes', + ] }, + 'bevel': { 'type':'enum', 'enum_values' : [ + 'flatout', 'flatinner', 'evenlyframed', 'biginner', + 'bigouter', 'dramaticflatout', 'dramaticflatinner', + ] }, + 'percentbeveled': { 'type':'int', 'default': _default_bevel_percent }, + 'tilt': { 'type':'int' }, + 'rotate': { 'type':'int' }, + 'flip': { 'type':'bool' }, + 'flop': { 'type':'bool' }, + 'filetype': { 'type':'enum', 'enum_values' : OUTPUT_IMAGE_TYPES, 'default': DEFAULT_FINALFORMAT }, + 'gradienttype': { 'type':'enum', 'enum_values' : [ + 'default', 'canvas', 'radial', 'colorspace', + 'mirrored', 'plasmawash', 'gradientwash', 'noise' + ], 'default': 'default' }, + 'username': { 'type':'string' } + } + self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); + + self.filename, self.filepath = self._filename_filepath_create() + + def _filename_create(self, **kwargs): + _base = "{}{}-{}_{}".format( + self.__class__.__name__, + str(self.params.color1).replace('#','').replace('(','-').replace(')','-'), + str(self.params.color2).replace('#','').replace('(','-').replace(')','-'), + self._now, + ) + if self.params.username: _base += "_%s" % self.params.username + return _base + ".%s" % self.params.filetype + + + def _build_cmd(self): + cmd = [BIN_CONVERT] + cmd.extend([ + '-size', + "{}x{}".format(self.params.width,self.params.height) + ]) + + if self.params.rotate: cmd.extend(["-rotate", self.params.rotate]) + if self.params.tilt: cmd.extend(["-distort","SRT",self.params.tilt]) + if self.params.flip == "true": cmd.append("-flip") + if self.params.flop == "true": cmd.append("-flop") + if self.params.contrast: cmd.extend(["-contrast-stretch", self.params.contrast]) + _gradients = { + "default" : "gradient:{}-{}".format(self.params.color1, self.params.color2), + "canvas" : ["canvas:{}".format(self.params.color1)], + "radial" : [ + "radial-gradient:{}-{}".format( self.params.color1, self.params.color2) + ], + "colorspace" : [ + "-colorspace", + "Gray", + "plasma:{}-{}".format(self.params.color1, self.params.color2) + ], + "mirrored" : [ + "plasma:{}-{}".format(self.params.color1, self.params.color2), + "\(","+clone","-flop","\)", + "append" + ], + "plasmawash" : [ + "plasma:{}-{}".format(self.params.color1, self.params.color2), + "-set","colorspace","HSB" + ], + "gradientwash" : [ + "gradient:{}-{}".format(self.params.color1, self.params.color2), + "-set","colorspace","HSB" + ], + "noise" : ["xc:","+noise","Random","-virtual-pixel","tile"] + } + cmd += _gradients[str(self.params.gradienttype)] + + if self.params.blurriness: + cmd.extend(["-blur","0x{}".format(self.params.blurriness),"-auto-level"]) + + if self.params.stripes == "true" and len(self.params.stripenumber): + cmd.extend(["-function","Sinusoid"]) + if self.params.stripeintensity: + cmd.append("{},{}".format(self.params.stripenumber,self.params.stripeintensity)) + else: + cmd.append(self.params.stripenumber) + if str(self.params.halftone) in _halftone_values: + cmd.extend([ + "-ordered-dither", + _halftone_values[str(self.params.halftone)] + ]) + cmd += [ + '-modulate', + "{},{},{}".format( + self.params.brightness or "100", + self.params.saturation or "100", + self.params.hue or "100") + ] + cmd.append(self.filepath); + self._call_cmd(cmd) + if self.params.bevel: self._make_bevel() + + def _get_bevelvalue(self): + w, h = map(int, (self.params.width, self.params.height)) + if h >= w: + bevpercentval = str(int(self.params.percentbeveled)*0.005*int(h)) + else: + bevpercentval = str(int(self.params.percentbeveled)*0.005*int(w)) + return { + "flatout": ["-s",bevpercentval,"-m","outer"], + "flatinner": ["-s",bevpercentval,"-m","inner"], + "evenlyframed": ["-s ",bevpercentval,"-m", "split"], + "biginner": ["-s",bevpercentval,"-m","outer","-c","50","-b","red","-a","25"], + "bigouter": ["-s",bevpercentval,"-m","split","-c","50","-b","red","-a","25"], + "dramaticflatout": ["-s",bevpercentval,"-m","outer","-a","25","-b","blue"], + "dramaticflatinner": ["-s",bevpercentval,"-m","outer","-a","25","-b","blue"], + }[str(self.params.bevel)] + + def _make_bevel(self): + cmd = [BEVELBORDER] + cmd += self._get_bevelvalue() + cmd += [ self.filepath, self.filepath] + self._call_cmd(cmd) + + def create(self): + self._build_cmd() + super(PbGradient, self).create() diff --git a/lib/Pb/Gradient/__init__.py b/lib/Pb/Gradient/__init__.py deleted file mode 100755 index 340ce62..0000000 --- a/lib/Pb/Gradient/__init__.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/python2.7 -import re -import time -from subprocess import call -import simplejson as json -import sys -import os -import sha -from config import * -from Pb import Pb - -_default_color_1 = "white" -_default_color_2 = "black" - -_default_bevel_percent = "12"; - -_halftone_values = { - "checkeredfade": "h6x6a", - "etchedtransition": "o8x8", - "bendaydots": "h16x16o", - "smallerdots1": "h8x8o", - "smallerdots2": "c7x7w", - "flatstripes": "o2x2", -} - -class PbGradient(Pb): - example_params = { - "width" : "200", - "color1" : "#ffdead", - "color2" : "blue", - "stripes" : "true", - "stripenumber" : "20", - "gradienttype" : "radial", - "stripeintensity" : "20", - "halftone" : "checkeredfade", - "percentbeveled" : "30", - "flip" : "true", - "bevel" : "flatinner", - "rotate" : "20", - "height" : "200", - "filetype" : "jpg", - "username" : "whatever" - } - def __init__(self, **kwargs): - super(PbGradient,self).__init__(**kwargs); - _definitions = { - 'width': { 'type':'int', 'default': DEFAULT_WIDTH }, - 'height': { 'type':'int', 'default' : DEFAULT_HEIGHT }, - 'color1': { 'type':'color', 'default': _default_color_1 }, - 'color2': { 'type':'color', 'default': _default_color_2 }, - 'stripes': { 'type':'bool' }, - 'stripenumber': { 'type':'int', 'default': 0 }, - 'stripeintensity': { 'type':'int', 'default': 0 }, - 'blurriness': { 'type':'int', 'default': 0 }, - 'contrast': { 'type':'int', 'default': 100 }, - 'brightness': { 'type':'int', 'default': 100 }, - 'saturation': { 'type':'int', 'default': 100 }, - 'hue': { 'type':'int', 'default': 100 }, - 'halftone': { 'type':'enum', 'enum_values' : [ - 'checkeredfade', 'etchedtransition', 'bendaydots', - 'smallerdots1', 'smallerdots2', 'flatstripes', - ] }, - 'bevel': { 'type':'enum', 'enum_values' : [ - 'flatout', 'flatinner', 'evenlyframed', 'biginner', - 'bigouter', 'dramaticflatout', 'dramaticflatinner', - ] }, - 'percentbeveled': { 'type':'int', 'default': _default_bevel_percent }, - 'tilt': { 'type':'int' }, - 'rotate': { 'type':'int' }, - 'flip': { 'type':'bool' }, - 'flop': { 'type':'bool' }, - 'filetype': { 'type':'enum', 'enum_values' : OUTPUT_IMAGE_TYPES, 'default': DEFAULT_FINALFORMAT }, - 'gradienttype': { 'type':'enum', 'enum_values' : [ - 'default', 'canvas', 'radial', 'colorspace', - 'mirrored', 'plasmawash', 'gradientwash', 'noise' - ], 'default': 'default' }, - 'username': { 'type':'string' } - } - self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); - - self.filename, self.filepath = self._filename_filepath_create() - - def _filename_create(self, **kwargs): - _base = "{}{}-{}_{}".format( - self.__class__.__name__, - str(self.params.color1).replace('#','').replace('(','-').replace(')','-'), - str(self.params.color2).replace('#','').replace('(','-').replace(')','-'), - self._now, - ) - if self.params.username: _base += "_%s" % self.params.username - return _base + ".%s" % self.params.filetype - - - def _build_cmd(self): - cmd = [BIN_CONVERT] - cmd.extend([ - '-size', - "{}x{}".format(self.params.width,self.params.height) - ]) - - if self.params.rotate: cmd.extend(["-rotate", self.params.rotate]) - if self.params.tilt: cmd.extend(["-distort","SRT",self.params.tilt]) - if self.params.flip == "true": cmd.append("-flip") - if self.params.flop == "true": cmd.append("-flop") - if self.params.contrast: cmd.extend(["-contrast-stretch", self.params.contrast]) - _gradients = { - "default" : "gradient:{}-{}".format(self.params.color1, self.params.color2), - "canvas" : ["canvas:{}".format(self.params.color1)], - "radial" : [ - "radial-gradient:{}-{}".format( self.params.color1, self.params.color2) - ], - "colorspace" : [ - "-colorspace", - "Gray", - "plasma:{}-{}".format(self.params.color1, self.params.color2) - ], - "mirrored" : [ - "plasma:{}-{}".format(self.params.color1, self.params.color2), - "\(","+clone","-flop","\)", - "append" - ], - "plasmawash" : [ - "plasma:{}-{}".format(self.params.color1, self.params.color2), - "-set","colorspace","HSB" - ], - "gradientwash" : [ - "gradient:{}-{}".format(self.params.color1, self.params.color2), - "-set","colorspace","HSB" - ], - "noise" : ["xc:","+noise","Random","-virtual-pixel","tile"] - } - cmd += _gradients[str(self.params.gradienttype)] - - if self.params.blurriness: - cmd.extend(["-blur","0x{}".format(self.params.blurriness),"-auto-level"]) - - if self.params.stripes == "true" and len(self.params.stripenumber): - cmd.extend(["-function","Sinusoid"]) - if self.params.stripeintensity: - cmd.append("{},{}".format(self.params.stripenumber,self.params.stripeintensity)) - else: - cmd.append(self.params.stripenumber) - if str(self.params.halftone) in _halftone_values: - cmd.extend([ - "-ordered-dither", - _halftone_values[str(self.params.halftone)] - ]) - cmd += [ - '-modulate', - "{},{},{}".format( - self.params.brightness or "100", - self.params.saturation or "100", - self.params.hue or "100") - ] - cmd.append(self.filepath); - self._call_cmd(cmd) - if self.params.bevel: self._make_bevel() - - def _get_bevelvalue(self): - w, h = map(int, (self.params.width, self.params.height)) - if h >= w: - bevpercentval = str(int(self.params.percentbeveled)*0.005*int(h)) - else: - bevpercentval = str(int(self.params.percentbeveled)*0.005*int(w)) - return { - "flatout": ["-s",bevpercentval,"-m","outer"], - "flatinner": ["-s",bevpercentval,"-m","inner"], - "evenlyframed": ["-s ",bevpercentval,"-m", "split"], - "biginner": ["-s",bevpercentval,"-m","outer","-c","50","-b","red","-a","25"], - "bigouter": ["-s",bevpercentval,"-m","split","-c","50","-b","red","-a","25"], - "dramaticflatout": ["-s",bevpercentval,"-m","outer","-a","25","-b","blue"], - "dramaticflatinner": ["-s",bevpercentval,"-m","outer","-a","25","-b","blue"], - }[str(self.params.bevel)] - - def _make_bevel(self): - cmd = [BEVELBORDER] - cmd += self._get_bevelvalue() - cmd += [ self.filepath, self.filepath] - self._call_cmd(cmd) - - def create(self): - self._build_cmd() - super(PbGradient, self).create() diff --git a/lib/Pb/Grid.py b/lib/Pb/Grid.py new file mode 100755 index 0000000..b0d731f --- /dev/null +++ b/lib/Pb/Grid.py @@ -0,0 +1,161 @@ +import sys +import re +import os +import simplejson as json +import random +from config import DEFAULT_FINALFORMAT, DEFAULT_HEIGHT, DEFAULT_WIDTH, WORKING_DIR, OUTPUT_IMAGE_TYPES +from config import THREEDROTATE, GRID, BIN_CONVERT, BIN_COMPOSITE +import tempfile +from Pb import Pb + +_default_line_color = "silver" + +class PbGrid(Pb): + example_params = { + 'bgimage' : 'http://i.asdf.us/im/1a/imBreak_1424909483_xx_abridged___.gif', + 'planebgimage' : 'http://i.imgur.com/FICZtph.png', + 'tilt' : '30', + 'spacing' : '30', + 'hlines' : 'true', + 'roll' : '30', + 'shadow' : 'true', + 'trim' : 'true' + } + def __init__(self, **kwargs ): + super(PbGrid,self).__init__(**kwargs); + _definitions = { + 'width': { 'type':'int' }, + 'height': { 'type':'int' }, + 'linethickness': { 'type':'int', 'default': 1 }, + 'opacity': { 'type':'float', "default": 1.0 }, + 'linecolor': { 'type':'color', 'default': 'whitesmoke' }, + 'linethickness': { 'type':'int' }, + 'spacing': { 'type':'int', 'default': 10 }, + 'vlines': { 'type':'bool' }, + 'hlines': { 'type':'bool' }, + 'shadow': { 'type':'bool' }, + 'bgimage': { 'type':'img_url' }, + 'bgcolor': { 'type':'color', 'default': 'transparent' }, + 'imageinstead': { 'type':'img_url' }, + 'planebgcolor': { 'type':'color', 'default': 'transparent' }, + 'planebgimage': { 'type':'img_url' }, + 'swing': { 'type':'int' }, + 'tilt': { 'type':'int' }, + 'roll': { 'type':'int' }, + 'zoom': { 'type':'int' }, + 'skycolor': { 'type':'color', 'default': 'transparent' }, + 'transition': { 'type':'enum', 'enum_values' : ['background', 'dither', 'edge', 'mirror', 'random', 'tile'], 'default': 'background' }, + 'trim': { 'type':'bool' }, + 'finalformat': { 'type':'enum', 'enum_values' : OUTPUT_IMAGE_TYPES, 'default': DEFAULT_FINALFORMAT }, + 'username': { 'type':'string' }, + } + self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); + if self.params.imageinstead: + self.filename, self.filepath = self._filename_filepath_create(url=self.params.imageinstead['url'], extension=self.params.finalformat) + elif self.params.planebgimage: + self.filename, self.filepath = self._filename_filepath_create(url=self.params.planebgimage['url'], extension=self.params.finalformat) + else: + self.filename, self.filepath = self._filename_filepath_create(extension=self.params.finalformat) + + self._db_url_param = str(filter(lambda n: n, [ self.params.imageinstead, self.params.planebgimage, self.params.bgimage, "NULL"])[0]) + + #makes a canvas file...step 1 (if not bgimage) + def _make_canvas(self): + dimensions = "{}x{}".format( + self.params.width or DEFAULT_WIDTH, + self.params.height or DEFAULT_HEIGHT + ) + if self.params.bgimage: + return + bgcolor = "xc:{}".format(self.params.bgcolor or 'transparent') + cmd = [ BIN_CONVERT, "-size", dimensions, bgcolor, self.filepath ] + self._call_cmd(cmd) + + #2nd step-- run grid + def _grid_command(self): + cmd = [GRID] + if self.params.spacing: + if self.params.vlines: + width = 2 * int(self.params.width or DEFAULT_WIDTH) + cmd += ["-s","{},{}".format(self.params.spacing,width)] + elif self.params.hlines: + height = 2 * int(self.params.height or DEFAULT_HEIGHT) + cmd += ["-s", "{},{}".format(height,self.params.spacing)] + else: + cmd += ["-s",self.params.spacing] + cmd += [ "-c", self.params.linecolor or _default_line_color] + if self.params.linethickness: cmd += ['-t',self.params.linethickness] + if self.params.opacity: cmd += ['-o',self.params.opacity] + cmd += [ self.filepath, self.filepath ] + self._call_cmd(cmd) + + def _shadow_cmd(self): + #convert 1.png \( +clone -background black -shadow 110x1+9+9 \) +swap -background none -layers merge +repage 2.png + cmd = [ + BIN_CONVERT, + self.filepath, + "(","+clone","-background","black","-shadow","100x2+20+10",")", + "+swap","-background","none","-layers","merge","+repage" , + self.filepath + ] + self._call_cmd(cmd) + + + def _threed_rotate_cmd (self): + #3rd step--run 3Drotate + cmd = [THREEDROTATE] + if self.params.swing: cmd += ["pan={}".format(self.params.swing)] + if self.params.tilt: cmd += ["tilt={}".format(self.params.tilt)] + if self.params.roll: cmd += ["roll={}".format(self.params.roll)] + if self.params.zoom: + cmd += ["zoom={}".format(self.params.zoom)] + if cmd == [THREEDROTATE]: #if nothing has been added + return + if self.params.planebgcolor and not self.params.planebgimage: + cmd += ["bgcolor={}".format(self.params.planebgcolor)] + else: + cmd += ["bgcolor=none"] + cmd += ["skycolor={}".format(self.params.skycolor or 'none')] + if self.params.transition: cmd += ["vp={}".format(self.params.transition)] + cmd += [ self.filepath, self.filepath ] + self._call_cmd(cmd) + + + def _trim_cmd (self): + cmd = [BIN_CONVERT, self.filepath, "-trim", "+repage", self.filepath] + self._call_cmd(cmd) + + def _prepare_gridimage(self, image): + if image['mimetype'] == 'gif': + _frame = self._choose_gif_frame(image['path']) + if image['mimetype'] != 'png': + cmd = [BIN_CONVERT, image['path'], self.filepath] + else: + cmd = ['cp', image['path'], self.filepath] + self._call_cmd(cmd) + + + def _overlay_planebgimage(self): + cmd = [ + BIN_COMPOSITE, + "-compose", "Dst_Over", "-gravity", "center", + self.params.planebgimage["path"], + self.filepath, + self.filepath + ] + self._call_cmd(cmd) + + def create(self): + if self.params.bgimage: + self._prepare_gridimage(self.params.bgimage) + self._grid_command() + elif self.params.imageinstead: + self._prepare_gridimage(self.params.imageinstead) + else: + self._make_canvas() + self._grid_command() + if self.params.shadow: self._shadow_cmd() + self._threed_rotate_cmd() + if self.params.planebgimage: self._overlay_planebgimage() + if self.params.trim: self._trim_cmd() + super(PbGrid, self).create() diff --git a/lib/Pb/Grid/__init__.py b/lib/Pb/Grid/__init__.py deleted file mode 100755 index b0d731f..0000000 --- a/lib/Pb/Grid/__init__.py +++ /dev/null @@ -1,161 +0,0 @@ -import sys -import re -import os -import simplejson as json -import random -from config import DEFAULT_FINALFORMAT, DEFAULT_HEIGHT, DEFAULT_WIDTH, WORKING_DIR, OUTPUT_IMAGE_TYPES -from config import THREEDROTATE, GRID, BIN_CONVERT, BIN_COMPOSITE -import tempfile -from Pb import Pb - -_default_line_color = "silver" - -class PbGrid(Pb): - example_params = { - 'bgimage' : 'http://i.asdf.us/im/1a/imBreak_1424909483_xx_abridged___.gif', - 'planebgimage' : 'http://i.imgur.com/FICZtph.png', - 'tilt' : '30', - 'spacing' : '30', - 'hlines' : 'true', - 'roll' : '30', - 'shadow' : 'true', - 'trim' : 'true' - } - def __init__(self, **kwargs ): - super(PbGrid,self).__init__(**kwargs); - _definitions = { - 'width': { 'type':'int' }, - 'height': { 'type':'int' }, - 'linethickness': { 'type':'int', 'default': 1 }, - 'opacity': { 'type':'float', "default": 1.0 }, - 'linecolor': { 'type':'color', 'default': 'whitesmoke' }, - 'linethickness': { 'type':'int' }, - 'spacing': { 'type':'int', 'default': 10 }, - 'vlines': { 'type':'bool' }, - 'hlines': { 'type':'bool' }, - 'shadow': { 'type':'bool' }, - 'bgimage': { 'type':'img_url' }, - 'bgcolor': { 'type':'color', 'default': 'transparent' }, - 'imageinstead': { 'type':'img_url' }, - 'planebgcolor': { 'type':'color', 'default': 'transparent' }, - 'planebgimage': { 'type':'img_url' }, - 'swing': { 'type':'int' }, - 'tilt': { 'type':'int' }, - 'roll': { 'type':'int' }, - 'zoom': { 'type':'int' }, - 'skycolor': { 'type':'color', 'default': 'transparent' }, - 'transition': { 'type':'enum', 'enum_values' : ['background', 'dither', 'edge', 'mirror', 'random', 'tile'], 'default': 'background' }, - 'trim': { 'type':'bool' }, - 'finalformat': { 'type':'enum', 'enum_values' : OUTPUT_IMAGE_TYPES, 'default': DEFAULT_FINALFORMAT }, - 'username': { 'type':'string' }, - } - self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); - if self.params.imageinstead: - self.filename, self.filepath = self._filename_filepath_create(url=self.params.imageinstead['url'], extension=self.params.finalformat) - elif self.params.planebgimage: - self.filename, self.filepath = self._filename_filepath_create(url=self.params.planebgimage['url'], extension=self.params.finalformat) - else: - self.filename, self.filepath = self._filename_filepath_create(extension=self.params.finalformat) - - self._db_url_param = str(filter(lambda n: n, [ self.params.imageinstead, self.params.planebgimage, self.params.bgimage, "NULL"])[0]) - - #makes a canvas file...step 1 (if not bgimage) - def _make_canvas(self): - dimensions = "{}x{}".format( - self.params.width or DEFAULT_WIDTH, - self.params.height or DEFAULT_HEIGHT - ) - if self.params.bgimage: - return - bgcolor = "xc:{}".format(self.params.bgcolor or 'transparent') - cmd = [ BIN_CONVERT, "-size", dimensions, bgcolor, self.filepath ] - self._call_cmd(cmd) - - #2nd step-- run grid - def _grid_command(self): - cmd = [GRID] - if self.params.spacing: - if self.params.vlines: - width = 2 * int(self.params.width or DEFAULT_WIDTH) - cmd += ["-s","{},{}".format(self.params.spacing,width)] - elif self.params.hlines: - height = 2 * int(self.params.height or DEFAULT_HEIGHT) - cmd += ["-s", "{},{}".format(height,self.params.spacing)] - else: - cmd += ["-s",self.params.spacing] - cmd += [ "-c", self.params.linecolor or _default_line_color] - if self.params.linethickness: cmd += ['-t',self.params.linethickness] - if self.params.opacity: cmd += ['-o',self.params.opacity] - cmd += [ self.filepath, self.filepath ] - self._call_cmd(cmd) - - def _shadow_cmd(self): - #convert 1.png \( +clone -background black -shadow 110x1+9+9 \) +swap -background none -layers merge +repage 2.png - cmd = [ - BIN_CONVERT, - self.filepath, - "(","+clone","-background","black","-shadow","100x2+20+10",")", - "+swap","-background","none","-layers","merge","+repage" , - self.filepath - ] - self._call_cmd(cmd) - - - def _threed_rotate_cmd (self): - #3rd step--run 3Drotate - cmd = [THREEDROTATE] - if self.params.swing: cmd += ["pan={}".format(self.params.swing)] - if self.params.tilt: cmd += ["tilt={}".format(self.params.tilt)] - if self.params.roll: cmd += ["roll={}".format(self.params.roll)] - if self.params.zoom: - cmd += ["zoom={}".format(self.params.zoom)] - if cmd == [THREEDROTATE]: #if nothing has been added - return - if self.params.planebgcolor and not self.params.planebgimage: - cmd += ["bgcolor={}".format(self.params.planebgcolor)] - else: - cmd += ["bgcolor=none"] - cmd += ["skycolor={}".format(self.params.skycolor or 'none')] - if self.params.transition: cmd += ["vp={}".format(self.params.transition)] - cmd += [ self.filepath, self.filepath ] - self._call_cmd(cmd) - - - def _trim_cmd (self): - cmd = [BIN_CONVERT, self.filepath, "-trim", "+repage", self.filepath] - self._call_cmd(cmd) - - def _prepare_gridimage(self, image): - if image['mimetype'] == 'gif': - _frame = self._choose_gif_frame(image['path']) - if image['mimetype'] != 'png': - cmd = [BIN_CONVERT, image['path'], self.filepath] - else: - cmd = ['cp', image['path'], self.filepath] - self._call_cmd(cmd) - - - def _overlay_planebgimage(self): - cmd = [ - BIN_COMPOSITE, - "-compose", "Dst_Over", "-gravity", "center", - self.params.planebgimage["path"], - self.filepath, - self.filepath - ] - self._call_cmd(cmd) - - def create(self): - if self.params.bgimage: - self._prepare_gridimage(self.params.bgimage) - self._grid_command() - elif self.params.imageinstead: - self._prepare_gridimage(self.params.imageinstead) - else: - self._make_canvas() - self._grid_command() - if self.params.shadow: self._shadow_cmd() - self._threed_rotate_cmd() - if self.params.planebgimage: self._overlay_planebgimage() - if self.params.trim: self._trim_cmd() - super(PbGrid, self).create() diff --git a/lib/Pb/Landscape/landscape b/lib/Pb/Landscape/landscape deleted file mode 100755 index 10e8ede..0000000 --- a/lib/Pb/Landscape/landscape +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/python2.7 -import cgi -import sys -import os -import re -import time -import string -import urllib -from subprocess import Popen, PIPE -import sha -import simplejson as json - -import mimetypes -import s3 - -import db -DB = db.db () - -import base64 -import urlparse - - -AWS_ACCESS_KEY_ID = 'AKIAIR53VPBXKJMXZIBA' -AWS_SECRET_ACCESS_KEY = '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' -BUCKET_NAME = 'i.asdf.us' -BASE_PATH = "/var/www/asdf.us/httpdocs/imlandscape" -BASE_URL = "http://i.asdf.us/" -PARAM_LIST = "heightmap texture name imgdata filename" -BIN_IDENTIFY = "/usr/bin/identify" - -print "Content-type: text/plain" -print "" -def insert_cmd (dir, newfile, name, texture, dataobj): - if texture == "": - texture = "NULL" - try: - sql = "INSERT INTO im_cmd (date,remote_addr,name,url,dir,oldfile,newfile,cmd, dataobj, tag) VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s, %s)" - - args = (now(), "NULL", name, texture, dir, "NULL", newfile, "NULL", dataobj, "imlandscape") - DB.execute(sql, args) - except (): - return - -def hash_dir (s): - return sha.new(s).hexdigest()[:2] - -def bin_identify (filename): - ident = Popen([BIN_IDENTIFY, filename], stdout=PIPE).communicate()[0] - partz = ident.split(" ") - width,height = partz[2].split("x") - return width, height - -def get_params (paramlist): - paramkeys = paramlist.split() - form = cgi.FieldStorage() - params = {} - for key in paramkeys: - if key in form: - if key == 'heightmap': - params[key] = form[key].value - elif key == 'imgdata': - params[key] = form[key].value - elif key == 'texture': - params[key] = form[key].value - else: - params[key] = sanitize(form[key].value) - else: - params[key] = None - return params - -def error (e): - print "#@imlandscape" - print "ERROR\t"+e - sys.exit() - -def now (): - return int(time.mktime(time.localtime())) - -def sanitize (str): - return re.sub(r'\W+', '', str) - -def filename_from_url (url, name=""): - if "?" in url: - url = url.split("?")[0] - if "/" in url: - url = urllib.unquote(url).replace(" ","") - filename = url.split("/")[-1] - filetype = "png" - filename = sanitize(filename[:-4]) - else: - filename = "" - if name != "": - name = name+"_" - return "{}_{}{}_{}.{}".format("imlandscape", name, filename,now(), "png") - -def saveImgData(url, filename): - try: - up = urlparse.urlparse(url) - head, data = up.path.split(',', 1) - bits = head.split(';') - mime_type = bits[0] if bits[0] else 'text/plain' - charset, b64 = 'ASCII', False - for bit in bits[1]: - if bit.startswith('charset='): - charset = bit[8:] - elif bit == 'base64': - b64 = True - - # Do something smart with charset and b64 instead of assuming - plaindata = base64.b64decode(data) - - with open(filename, 'wb') as f: - f.write(plaindata) - except Exception as e: - error(str(e)); - -def file_size (file): - return os.stat(file)[6] - -def moveToS3(filename,objectname): - conn = s3.AWSAuthConnection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY) - sys.stderr.write( "Uploading %s" % filename) - filedata = open(filename, 'rb').read() - content_type = mimetypes.guess_type(filename)[0] - if not content_type: - content_type = 'text/plain' - conn.put(BUCKET_NAME, objectname, s3.S3Object(filedata), - {'x-amz-acl': 'public-read', 'Content-Type': content_type, 'x-amz-storage-class': 'REDUCED_REDUNDANCY'}) - -param = get_params(PARAM_LIST) -if param['imgdata'] is None: - error("no imgdata") -url = param['imgdata'] -if param['texture'] is None: - param['texture'] = ""; -if param['heightmap'] is None: - param['heightmap'] = ""; -if param['name'] is None: - param['name'] = ""; - -dataobj = json.dumps({ - 'texture' : param['texture'], - 'heightmap' : param['heightmap'], - 'name' : param['name'] -}) - -dir = hash_dir(param['imgdata']); - -filename = filename_from_url(param['texture'], param['name']); - -tag = "imlandscape" -objectname = "im/"+dir+"/"+filename - -saveImgData(param['imgdata'], filename); - -print "#@imlandscape" -#print ", ".join([k+"="+str(v) for k,v in param.iteritems()]) -print file_size (filename) -print bin_identify (filename) -print BASE_URL+objectname -insert_cmd(dir, filename, param['name'], param['texture'], dataobj); -moveToS3(filename, objectname); -os.remove(filename); diff --git a/lib/Pb/Pattern.py b/lib/Pb/Pattern.py new file mode 100755 index 0000000..6ae6eb7 --- /dev/null +++ b/lib/Pb/Pattern.py @@ -0,0 +1,86 @@ +import os +import sys +import random +import re +import urllib +from config import * +from Pb import Pb + +import simplejson as json +from PIL import Image +import uuid + +_fuse_mode="Pin_Light" + +class PbPattern(Pb): + example_params = { + # "pattern_url" : "http://asdf.us/impattern/patterns/1.png", + "pattern_data" : '{"matrix":[["0","0","0","0","0","1","0","0","0","0"],["0","0","0","0","1","1","1","0","0","0"],["0","0","1","1","1","0","1","0","0","0"],["0","1","1","0","0","0","0","0","0","0"],["0","1","0","0","1","0","0","0","0","0"],["0","1","0","0","1","0","0","0","1","0"],["0","1","0","0","1","1","0","0","1","0"],["0","1","0","0","0","1","1","1","1","0"],["0","1","1","1","1","0","0","0","0","0"],["0","0","0","0","1","0","0","0","0","0"]],"width":"10","height":"10"}', + # "username" : "garfield", + "image_url" : "http://i.asdf.us/im/be/PinkHijab_1425078647_reye.gif", + } + def __init__(self, **kwargs): + super(PbPattern,self).__init__(**kwargs); + _definitions = { + 'image_url': { 'type':'img_url' }, + 'pattern_url': { 'type':'img_url' }, + 'pattern_data': { 'type':'raw' }, + 'username': { 'type':'string' }, + } + self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); + self.filename, self.filepath = self._filename_filepath_create(url=self.params.image_url['url'], extension=self.params.image_url['mimetype']) + _pattern_filename, self._pattern_filepath = self._filename_filepath_create(namepart="pattern") + + if self.params.pattern_data: self._from_pattern_data() + elif not self.params.pattern_url: + self.err_warn("pattern must be supplied as json array or as a png url") + + self._db_url_param = str(self.params.image_url) + + def _from_pattern_data(self): + def boolToColor(boolean): + if boolean: + return (0,0,0,255); + else: + return (255,255,255,255) + specs = json.loads(str(self.params.pattern_data)); + if int(specs['width']) > 100 or int(specs['height']) > 100: + raise ValueError + sys.stderr.write("height and width need to be less than 100 px") + img = Image.new('RGBA', (int(specs['width']), int(specs['height']))); + pixels = img.load(); + for i in range(0, len(specs['matrix'])): + for j in range(0, len(specs['matrix'][i])): + pixels[j,i] = boolToColor(int(specs['matrix'][i][j])); + + img.save(self._pattern_filepath, "PNG") + + #first step + def _make_canvas(self): + _width, _height = self._dimensions(self.params.image_url['path']) # same here + cmd = [BIN_CONVERT, "-size", _width + "x" + _height, "canvas:transparent", self.filepath] + self._call_cmd(cmd) + + #second step use the Canvas as a background + def _make_mask(self): + #tile the pattern pattern on the canvas + cmd = [BIN_COMPOSITE,"-tile", self._pattern_filepath, self.filepath, self.filepath]; + self._call_cmd(cmd) + #fuse the tiled file to create a mask + #convert thebg.gif -compose Dst_In null: thefile.gif -matte -layers composite new.gif + cmd = [BIN_CONVERT, self.filepath, "-compose", "Dst_In", "null:", + self.params.image_url['path'], "-matte", "-layers", "composite", self.filepath] + self._call_cmd(cmd) + + #third step + def _fuse_mask(self, fuse_mode=_fuse_mode): + cmd = [BIN_CONVERT, "-dispose", "2", self.filepath, "null:", + self.params.image_url['path'], "-matte", "-compose", fuse_mode, "-layers", "composite", + self.filepath] + self._call_cmd(cmd) + + def create(self): + self._make_canvas(); + self._make_mask() + self._fuse_mask(); + super(PbPattern, self).create() diff --git a/lib/Pb/Pattern/__init__.py b/lib/Pb/Pattern/__init__.py deleted file mode 100755 index 6ae6eb7..0000000 --- a/lib/Pb/Pattern/__init__.py +++ /dev/null @@ -1,86 +0,0 @@ -import os -import sys -import random -import re -import urllib -from config import * -from Pb import Pb - -import simplejson as json -from PIL import Image -import uuid - -_fuse_mode="Pin_Light" - -class PbPattern(Pb): - example_params = { - # "pattern_url" : "http://asdf.us/impattern/patterns/1.png", - "pattern_data" : '{"matrix":[["0","0","0","0","0","1","0","0","0","0"],["0","0","0","0","1","1","1","0","0","0"],["0","0","1","1","1","0","1","0","0","0"],["0","1","1","0","0","0","0","0","0","0"],["0","1","0","0","1","0","0","0","0","0"],["0","1","0","0","1","0","0","0","1","0"],["0","1","0","0","1","1","0","0","1","0"],["0","1","0","0","0","1","1","1","1","0"],["0","1","1","1","1","0","0","0","0","0"],["0","0","0","0","1","0","0","0","0","0"]],"width":"10","height":"10"}', - # "username" : "garfield", - "image_url" : "http://i.asdf.us/im/be/PinkHijab_1425078647_reye.gif", - } - def __init__(self, **kwargs): - super(PbPattern,self).__init__(**kwargs); - _definitions = { - 'image_url': { 'type':'img_url' }, - 'pattern_url': { 'type':'img_url' }, - 'pattern_data': { 'type':'raw' }, - 'username': { 'type':'string' }, - } - self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); - self.filename, self.filepath = self._filename_filepath_create(url=self.params.image_url['url'], extension=self.params.image_url['mimetype']) - _pattern_filename, self._pattern_filepath = self._filename_filepath_create(namepart="pattern") - - if self.params.pattern_data: self._from_pattern_data() - elif not self.params.pattern_url: - self.err_warn("pattern must be supplied as json array or as a png url") - - self._db_url_param = str(self.params.image_url) - - def _from_pattern_data(self): - def boolToColor(boolean): - if boolean: - return (0,0,0,255); - else: - return (255,255,255,255) - specs = json.loads(str(self.params.pattern_data)); - if int(specs['width']) > 100 or int(specs['height']) > 100: - raise ValueError - sys.stderr.write("height and width need to be less than 100 px") - img = Image.new('RGBA', (int(specs['width']), int(specs['height']))); - pixels = img.load(); - for i in range(0, len(specs['matrix'])): - for j in range(0, len(specs['matrix'][i])): - pixels[j,i] = boolToColor(int(specs['matrix'][i][j])); - - img.save(self._pattern_filepath, "PNG") - - #first step - def _make_canvas(self): - _width, _height = self._dimensions(self.params.image_url['path']) # same here - cmd = [BIN_CONVERT, "-size", _width + "x" + _height, "canvas:transparent", self.filepath] - self._call_cmd(cmd) - - #second step use the Canvas as a background - def _make_mask(self): - #tile the pattern pattern on the canvas - cmd = [BIN_COMPOSITE,"-tile", self._pattern_filepath, self.filepath, self.filepath]; - self._call_cmd(cmd) - #fuse the tiled file to create a mask - #convert thebg.gif -compose Dst_In null: thefile.gif -matte -layers composite new.gif - cmd = [BIN_CONVERT, self.filepath, "-compose", "Dst_In", "null:", - self.params.image_url['path'], "-matte", "-layers", "composite", self.filepath] - self._call_cmd(cmd) - - #third step - def _fuse_mask(self, fuse_mode=_fuse_mode): - cmd = [BIN_CONVERT, "-dispose", "2", self.filepath, "null:", - self.params.image_url['path'], "-matte", "-compose", fuse_mode, "-layers", "composite", - self.filepath] - self._call_cmd(cmd) - - def create(self): - self._make_canvas(); - self._make_mask() - self._fuse_mask(); - super(PbPattern, self).create() diff --git a/lib/S3Cli.py b/lib/S3Cli.py new file mode 100644 index 0000000..70ba24c --- /dev/null +++ b/lib/S3Cli.py @@ -0,0 +1,24 @@ +from config import * +import sys +from boto.s3.connection import S3Connection +from boto.s3.key import Key +class S3Cli(object): + def __init__(self): + try: + self.conn = S3Connection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, is_secure=False) + self.bucket = self.conn.get_bucket(BUCKET_NAME) + except Exception as e: + sys.stderr.write("Could not connect to s3\n"); + sys.stderr.write(str(e)) + sys.exit(1) + + def s3move(self, filename,objectname): + try: + k = Key(self.bucket) + k.key = objectname + k.set_contents_from_filename(filename) + k.set_acl('public-read') + k.storage_class = 'REDUCED_REDUNDANCY' + except Exception as e: + sys.stderr.write(str(e)); + sys.exit(1) diff --git a/lib/S3Cli/__init__.py b/lib/S3Cli/__init__.py deleted file mode 100644 index 70ba24c..0000000 --- a/lib/S3Cli/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -from config import * -import sys -from boto.s3.connection import S3Connection -from boto.s3.key import Key -class S3Cli(object): - def __init__(self): - try: - self.conn = S3Connection(AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, is_secure=False) - self.bucket = self.conn.get_bucket(BUCKET_NAME) - except Exception as e: - sys.stderr.write("Could not connect to s3\n"); - sys.stderr.write(str(e)) - sys.exit(1) - - def s3move(self, filename,objectname): - try: - k = Key(self.bucket) - k.key = objectname - k.set_contents_from_filename(filename) - k.set_acl('public-read') - k.storage_class = 'REDUCED_REDUNDANCY' - except Exception as e: - sys.stderr.write(str(e)); - sys.exit(1) diff --git a/lib/Server.py b/lib/Server.py new file mode 100644 index 0000000..00bae9f --- /dev/null +++ b/lib/Server.py @@ -0,0 +1,73 @@ +from flask import Flask +from flask import abort, redirect, url_for, request, jsonify +import sys, os +sys.path.append("./lib") +from Pb import * + +class InvalidUsage(Exception): + status_code = 400 + + def __init__(self, message, status_code=None, payload=None): + Exception.__init__(self) + self.message = message + if status_code is not None: + self.status_code = status_code + self.payload = payload + + def to_dict(self): + rv = dict(self.payload or ()) + rv['message'] = self.message + return rv + +class Server(object): + def __init__(self): + self.app = Flask(__name__) + @self.app.route('/', methods=['POST']) + def pb(pb_classname): + return self._response_post(pb_classname, request.form.to_dict()) + + @self.app.errorhandler(InvalidUsage) + def handle_invalid_usage(error): + response = jsonify(error.to_dict()) + response.status_code = error.status_code + return response + + self._classname_aliases = { + 'generate' : 'PbGenerate', + 'imgrid' : 'PbGrid', + 'imbreak' : 'PbBreak', + 'impattern' : 'PbPattern', + 'imgradient' : 'PbGradient', + 'landscape' : 'PbLandscape', + } + + def _find_class_by_name(self, pb_classname): + pb_classname = self._classname_aliases.get(pb_classname, None) or pb_classname + try: + return filter(lambda c: c.__name__ == pb_classname, Pb.__subclasses__())[0] + except IndexError: + raise InvalidUsage('No such api', status_code=410) + + def _response_post(self, pb_classname, request_form): + pb_class = self._find_class_by_name(pb_classname) + classnames = map(lambda c: c.__name__, Pb.__subclasses__()) + try: + pb = pb_class(**request_form) + pb.create(); + pb.file_s3move() + pb.db_send(); + return jsonify(pb.file_dict()); + + #FIXME handle BadParamsError and PbError separately + except Exception as e: + sys.stderr.write("%s failure" % pb_class.__name__) + sys.stderr.write("params:\n") + sys.stderr.write(str(e)) + for i in request_form.keys(): + sys.stderr.write("{}:{}\n".format(i, request_form[i])) + raise; + return jsonify({ 'error' : 'Request could not be processed' }) + + def run(self): + self.app.run() + diff --git a/lib/Server/InvalidUsage/__init__.py b/lib/Server/InvalidUsage/__init__.py deleted file mode 100644 index e5616d4..0000000 --- a/lib/Server/InvalidUsage/__init__.py +++ /dev/null @@ -1,16 +0,0 @@ -from flask import jsonify - -class InvalidUsage(Exception): - status_code = 400 - - def __init__(self, message, status_code=None, payload=None): - Exception.__init__(self) - self.message = message - if status_code is not None: - self.status_code = status_code - self.payload = payload - - def to_dict(self): - rv = dict(self.payload or ()) - rv['message'] = self.message - return rv diff --git a/lib/Server/__init__.py b/lib/Server/__init__.py deleted file mode 100644 index 91bc880..0000000 --- a/lib/Server/__init__.py +++ /dev/null @@ -1,59 +0,0 @@ -from flask import Flask -from flask import abort, redirect, url_for, request, jsonify -import sys, os -sys.path.append("./lib") -from Pb import * -from Server.InvalidUsage import InvalidUsage - -class Server(object): - def __init__(self): - self.app = Flask(__name__) - @self.app.route('/', methods=['POST']) - def pb(pb_classname): - return self._response_post(pb_classname, request.form.to_dict()) - - @self.app.errorhandler(InvalidUsage) - def handle_invalid_usage(error): - response = jsonify(error.to_dict()) - response.status_code = error.status_code - return response - - self._classname_aliases = { - 'generate' : 'PbGenerate', - 'imgrid' : 'PbGrid', - 'imbreak' : 'PbBreak', - 'impattern' : 'PbPattern', - 'imgradient' : 'PbGradient', - 'landscape' : 'PbLandscape', - } - - def _find_class_by_name(self, pb_classname): - pb_classname = self._classname_aliases.get(pb_classname, None) or pb_classname - try: - return filter(lambda c: c.__name__ == pb_classname, Pb.__subclasses__())[0] - except IndexError: - raise InvalidUsage('No such api', status_code=410) - - def _response_post(self, pb_classname, request_form): - pb_class = self._find_class_by_name(pb_classname) - classnames = map(lambda c: c.__name__, Pb.__subclasses__()) - try: - pb = pb_class(**request_form) - pb.create(); - pb.file_s3move() - pb.db_send(); - return jsonify(pb.file_dict()); - - #FIXME handle BadParamsError and PbError separately - except Exception as e: - sys.stderr.write("%s failure" % pb_class.__name__) - sys.stderr.write("params:\n") - sys.stderr.write(str(e)) - for i in request_form.keys(): - sys.stderr.write("{}:{}\n".format(i, request_form[i])) - raise; - return jsonify({ 'error' : 'Request could not be processed' }) - - def run(self): - self.app.run() - diff --git a/run_examples.py b/run_examples.py deleted file mode 100644 index 08e45d2..0000000 --- a/run_examples.py +++ /dev/null @@ -1,11 +0,0 @@ -import sys -sys.path.append('./lib') -from Pb import * -for cls in Pb.__subclasses__(): - if cls == PbBreak: - print cls.__name__ - instance = cls.example_run() - instance.file_s3move() - print instance.file_json() - instance.db_send(); - break diff --git a/run_module_examples.py b/run_module_examples.py new file mode 100644 index 0000000..1c385b2 --- /dev/null +++ b/run_module_examples.py @@ -0,0 +1,9 @@ +import sys +sys.path.append('./lib') +from Pb import * +for cls in Pb.__subclasses__(): + print cls.__name__ + instance = cls.example_run() + instance.file_s3move() + print instance.file_dict() + instance.db_send(); diff --git a/tests/jsonptest.sh b/tests/jsonptest.sh deleted file mode 100644 index 8539853..0000000 --- a/tests/jsonptest.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -curl 'http://asdf.us/cgi-bin/im/generate?callback=jsonp1431361693303&url=http%3A%2F%2Fwww.maskworld.com%2Fpix%2Fmasks%2F025-party-face-gesicht-fasching-karneval-carnival-halloween-latex-film-movie-larp-theatre-theater-horror-rubber-gummi-mask-masks-maske-masken.jpg&name=test&transparent=true&fuzz=5' -H 'Accept-Encoding: gzip, deflate, sdch' -H 'Accept-Language: en-US,en;q=0.8' -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36' -H 'Accept: */*' -H 'Referer: http://carbonpictures.com/pb/' -H 'Cookie: imname=yo' -H 'Connection: keep-alive' --compressed diff --git a/tests/test_break.py b/tests/test_break.py deleted file mode 100644 index 6f0c710..0000000 --- a/tests/test_break.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/python2.7 -import requests, sys -import simplejson as json -URL_BASE = "http://127.0.0.1:5000" - -example_params = { - "url" : "http://i.asdf.us/im/de/HolyMountain2_1322275112_seamonkey.gif", - "breaktype" : "RGB_WASH", - "finalformat" : "png", - "breakmode" : "extreme", - "breakangle" : "10", - "username" : "donkey", - "expanded" : "false" -} - -def post_request(url, data): - r = requests.post(url, data=data) - if r.status_code != 200: - sys.stderr.write("ERROR: %s\n" % r.status_code) - sys.stderr.write("REASON: %s\n" % r.reason) - sys.exit(1) - return json.loads(r.text) - -def test(api_name, params): - return post_request("%s/%s" % (URL_BASE, api_name), params) - -if __name__ == "__main__": - print test("PbBreak", example_params) - -- cgit v1.2.3-70-g09d2