From 4ebeb643da6419835e9ac3adb731e38a8ec9c7b4 Mon Sep 17 00:00:00 2001 From: Pepper Date: Sat, 26 Sep 2015 04:14:44 -0400 Subject: reworked some more --- lib/param/enum.py | 2 +- lib/param/json.py | 3 +- lib/param/raw.py | 2 +- lib/params.py | 2 +- lib/pb/__init__.py | 347 ++++++++++++++++++++++++++--------------------------- lib/pb/breaker.py | 112 +++++++++-------- lib/pb/generate.py | 255 +++++++++++++++++++++------------------ lib/pb/gradient.py | 186 ++++++++++++++-------------- lib/pb/grid.py | 127 ++++++++++++-------- lib/pb/pattern.py | 30 +++-- lib/server.py | 38 ++++-- 11 files changed, 587 insertions(+), 517 deletions(-) (limited to 'lib') diff --git a/lib/param/enum.py b/lib/param/enum.py index 067e0cd..49e11f6 100644 --- a/lib/param/enum.py +++ b/lib/param/enum.py @@ -3,6 +3,6 @@ import sys class Enum(Param): def __init__(self, value, enum_values=[], classname=""): super(Enum,self).__init__(classname=classname) - if value not in enum_values: + if value and 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/json.py b/lib/param/json.py index 8d1a66e..af9b775 100644 --- a/lib/param/json.py +++ b/lib/param/json.py @@ -4,5 +4,4 @@ import simplejson as json class Json(Param): def __init__(self, value, classname=""): super(Json, self).__init__(classname=classname) - self.value = json.parse(value) - + self.value = json.loads(value) diff --git a/lib/param/raw.py b/lib/param/raw.py index 839f7e5..3d2f93f 100644 --- a/lib/param/raw.py +++ b/lib/param/raw.py @@ -3,4 +3,4 @@ from param import Param class Raw(Param): def __init__(self, value, classname=""): super(Raw, self).__init__(classname=classname) - self.value = value + self.value = value or None diff --git a/lib/params.py b/lib/params.py index 6db17d2..78a65eb 100644 --- a/lib/params.py +++ b/lib/params.py @@ -38,7 +38,7 @@ class Params(object): try: value = None if key in classkwargs: - value = classkwargs[key] + value = classkwargs[key] or def_dict[key].get('default', None) elif 'default' in def_dict[key]: value = def_dict[key]['default'] if def_dict[key]['type'] == "bool": diff --git a/lib/pb/__init__.py b/lib/pb/__init__.py index 29569c6..41b9155 100644 --- a/lib/pb/__init__.py +++ b/lib/pb/__init__.py @@ -1,10 +1,10 @@ import re from config import * -import time +import time import urllib, urllib2 import sys, os import random -from subprocess import Popen,PIPE,call +from subprocess import Popen, PIPE, call from params import Params import sha import simplejson as json @@ -16,182 +16,181 @@ Request = urllib2.Request urlencode = urllib.urlencode urlopen = urllib2.urlopen -_max_filename_length = 20; +_max_filename_length = 20 class PbProcessError(Exception): - pass + pass class Pb(object): - def __init__(self, **kwargs): - self._input_kwargs = kwargs - self._now = str(int(time.time())); - self.params = Params(classname=self.__class__.__name__, now=self._now); - self._files_created = [] - self.commands = []; - self._working_dir = WORKING_DIR - self._tag = self.__class__.__name__ - self._hashdir = None - self._db_url_param = None - - def _filename_create(self, url=None, namepart="", extension=""): - if url: - _basename = os.path.basename(url) - namepart = re.split(r'\.', _basename)[0] - namepart = self._url_sanitize(namepart)[0:_max_filename_length] - name = "" - if namepart: name += "%s-" % namepart - name += "%s_%s" % (self.__class__.__name__, self._now) - if self.params.username : name += "_%s" % self.params.username - if extension: name += ".%s" % extension - return name - - def _filepath_create(self, filename, directory=WORKING_DIR): - return os.path.join(directory, filename) - - def _filename_filepath_create(self, url=None, namepart="", directory=WORKING_DIR, extension=""): - _filename = self._filename_create(url=url, namepart=namepart, extension=extension); - _filepath = self._filepath_create(_filename, directory=directory); - return _filename, _filepath - - def _tempfilepath_create(self, namepart="temp", directory=WORKING_DIR, extension=""): - _filename = self._filename_create(namepart=namepart, extension=extension) - return self._filepath_create(_filename, directory=directory) - - def _hashdir_create(self): - self._hashdir = sha.new(self.filename).hexdigest()[:2] - - def _url_sanitize (self, s): - return re.sub(r'\W+', '', s) - - def _call_cmd(self, cmd): - try: - cmd = map(lambda i: str(i), cmd) - call(cmd) - self.commands.append(" ".join(cmd)); - except Exception: - raise Exception("Unable to call cmd {}".format(str(cmd))) - - def _dimensions(self, filepath): - try: - ident = (Popen([BIN_IDENTIFY, filepath], stdout=PIPE).communicate()[0]).split(" ") - return ident[2].split("x") - except Exception as e: - self.err_warn("Unable to get file dimensions:\n") - self.err_ward(str(e)) - - def _file_dimensions (self): - self.file_width, self.file_height = self._dimensions(self.filepath) - - def _width_and_height_set(self, filepath=None, width=DEFAULT_WIDTH, height=DEFAULT_HEIGHT): - if filepath: - self.width, self.height = self._dimensions(filepath) - return - self.width = width - self.height = height - - def _file_size_get(self): - try: - self.file_size = os.stat(self.filepath)[6] - except Exception as e: - self.err_warn("Couldn't determine filesize of %s\n" % self.filepath) - self.err_warn(str(e)) - - def _file_read(self, filepath): - f = open(filepath, 'r'); - data = f.read() - f.close() - return data - - def err_warn(self, s): - sys.stderr.write("ERROR:{} - {}\n".format(self.__class__.__name__, s)) - raise PbProcessError - - def _cleanup(self): - if not self._files_created: return - map(lambda n: os.remove(n), self._files_created) - - def _file_clean_local(self): - os.remove(self.filepath) - - def err_fatal(self, s): - sys.stderr.write("ERROR[FATAL]:%s - %s\n".format(self.__class__.__name__, s)) - sys.exit(1); - - @classmethod - def example_run(cls, params=None, verbose=True): - example_params = params or cls.example_params - if not example_params: - raise AttributeError ("Must supply test params to test %s" % cls.__name__) - b = cls(**example_params) - b.create(); - if verbose: - sys.stderr.write("generated %s\n" % b.filepath) - sys.stderr.write("files created %s\n" % b._files_created) - sys.stderr.write("commands:\n %s\n" % ";\n ".join(b.commands)) - return b - - @staticmethod - def gif_frames(filepath): - try: - info = Popen([BIN_IDENTIFY,filepath], stdout=PIPE).communicate()[0] - frames = filter((lambda x: x), map( - (lambda x: x.split(" ")[0]), - (info).split('\n') - )) - return frames - except Exception as e: - self.err_warn("couldn't get gif frames") - raise e; - - def _choose_gif_frame(self, filepath): - _gif_frames = Pb.gif_frames(filepath) - frame = random.choice(_gif_frames) - self._call_cmd([BIN_CONVERT, frame, filepath]) - - def db_send(self, remote_addr=None, db_connection=None): - try: - db = db_connection or Db(); - except Exception as e: - sys.stderr.write("Could not connect to db:\n{}".format(e)) - sys.exit(1); - try: - - _insert_data = { - 'date' : self._now, - 'remote_addr' : remote_addr, - 'username' : str(self.params.username), - 'url' : self._db_url_param, - 'directory' : self._hashdir, - 'oldfile' : None, - 'newfile' : self.filename, - 'dataobj' : json.dumps(dict(self._input_kwargs)), - 'cmd' : "; ".join(self.commands), - 'tag' : self._tag, - } - db.insert_cmd(**_insert_data) - except Exception as e: - self.err_warn("Problem sending to database:\n %s" % str(e)) - - def file_s3move(self): - self._hashdir_create() - s3cli = S3Cli() - s3cli.s3move(self.filepath, "im/{}/{}".format(self._hashdir, self.filename)) - self._file_clean_local(); - - def file_dict(self): - return { - 'url' : "%s/im/%s/%s" % (BASE_URL, self._hashdir, self.filename), - 'size' : self.file_size, - 'width' : "%spx" % self.file_width, - 'height' : "%spx" % self.file_height, - } - - def create(self): - #base methods FIXME move into File class - - self._file_dimensions() - self._file_size_get() - self._cleanup(); + def __init__(self, **kwargs): + self._input_kwargs = kwargs + self._now = str(int(time.time())) + self.params = Params(classname=self.__class__.__name__, now=self._now) + self._files_created = [] + self.commands = [] + self._working_dir = WORKING_DIR + self._tag = self.__class__.__name__ + self._hashdir = None + self._db_url_param = None + + def _filename_create(self, url=None, namepart="", extension=""): + if url: + _basename = os.path.basename(url) + namepart = re.split(r'\.', _basename)[0] + namepart = self._url_sanitize(namepart)[0:_max_filename_length] + name = "" + if namepart: name += "%s-" % namepart + name += "%s_%s" % (self.__class__.__name__, self._now) + if self.params.username: name += "_%s" % self.params.username + if extension: name += ".%s" % extension + return name + + def _filepath_create(self, filename, directory=WORKING_DIR): + return os.path.join(directory, filename) + + def _filename_filepath_create(self, url=None, namepart="", directory=WORKING_DIR, extension=""): + _filename = self._filename_create(url=url, namepart=namepart, extension=extension) + _filepath = self._filepath_create(_filename, directory=directory) + return _filename, _filepath + + def _tempfilepath_create(self, namepart="temp", directory=WORKING_DIR, extension=""): + _filename = self._filename_create(namepart=namepart, extension=extension) + return self._filepath_create(_filename, directory=directory) + + def _hashdir_create(self): + self._hashdir = sha.new(self.filename).hexdigest()[:2] + + def _url_sanitize(self, s): + return re.sub(r'\W+', '', s) + + def _call_cmd(self, cmd): + try: + cmd = map(lambda i: str(i), cmd) + call(cmd) + self.commands.append(" ".join(cmd)) + except Exception: + raise Exception("Unable to call cmd {}".format(str(cmd))) + + def _dimensions(self, filepath): + try: + ident = (Popen([BIN_IDENTIFY, filepath], stdout=PIPE).communicate()[0]).split(" ") + return ident[2].split("x") + except Exception as e: + self.err_warn("Unable to get file dimensions:\n") + self.err_ward(str(e)) + + def _file_dimensions(self): + self.file_width, self.file_height = self._dimensions(self.filepath) + + def _width_and_height_set(self, filepath=None, width=DEFAULT_WIDTH, height=DEFAULT_HEIGHT): + if filepath: + self.width, self.height = self._dimensions(filepath) + return + self.width = width + self.height = height + + def _file_size_get(self): + try: + self.file_size = os.stat(self.filepath)[6] + except Exception as e: + self.err_warn("Couldn't determine filesize of %s\n" % self.filepath) + self.err_warn(str(e)) + + def _file_read(self, filepath): + f = open(filepath, 'r') + data = f.read() + f.close() + return data + + def err_warn(self, s): + sys.stderr.write("ERROR:{} - {}\n".format(self.__class__.__name__, s)) + raise PbProcessError + + def _cleanup(self): + if not self._files_created: return + map(lambda n: os.remove(n), self._files_created) + + def _file_clean_local(self): + os.remove(self.filepath) + + def err_fatal(self, s): + sys.stderr.write("ERROR[FATAL]:%s - %s\n".format(self.__class__.__name__, s)) + sys.exit(1) + + @classmethod + def example_run(cls, params=None, verbose=True): + example_params = params or cls.example_params + if not example_params: + raise AttributeError("Must supply test params to test %s" % cls.__name__) + b = cls(**example_params) + b.create() + if verbose: + sys.stderr.write("generated %s\n" % b.filepath) + sys.stderr.write("files created %s\n" % b._files_created) + sys.stderr.write("commands:\n %s\n" % ";\n ".join(b.commands)) + return b + + @staticmethod + def gif_frames(filepath): + try: + info = Popen([BIN_IDENTIFY, filepath], stdout=PIPE).communicate()[0] + frames = filter((lambda x: x), map( + (lambda x: x.split(" ")[0]), + (info).split('\n') + )) + return frames + except Exception as e: + self.err_warn("couldn't get gif frames") + raise e + + def _choose_gif_frame(self, filepath): + _gif_frames = Pb.gif_frames(filepath) + frame = random.choice(_gif_frames) + self._call_cmd([BIN_CONVERT, frame, filepath]) + + def db_send(self, remote_addr=None, db_connection=None): + try: + db = db_connection or Db() + except Exception as e: + sys.stderr.write("Could not connect to db:\n{}".format(e)) + sys.exit(1) + try: + + _insert_data = { + 'date' : self._now, + 'remote_addr' : remote_addr, + 'username' : str(self.params.username), + 'url' : self._db_url_param, + 'directory' : self._hashdir, + 'oldfile' : None, + 'newfile' : self.filename, + 'dataobj' : json.dumps(dict(self._input_kwargs)), + 'cmd' : "; ".join(self.commands), + 'tag' : self._tag, + } + db.insert_cmd(**_insert_data) + except Exception as e: + self.err_warn("Problem sending to database:\n %s" % str(e)) + + def file_s3move(self): + self._hashdir_create() + s3cli = S3Cli() + s3cli.s3move(self.filepath, "im/{}/{}".format(self._hashdir, self.filename)) + self._file_clean_local() + + def file_dict(self): + return { + 'url' : "%s/im/%s/%s" % (BASE_URL, self._hashdir, self.filename), + 'size' : self.file_size, + 'width' : "%spx" % self.file_width, + 'height' : "%spx" % self.file_height, + } + + def create(self): + #base methods FIXME move into File class + self._file_dimensions() + self._file_size_get() + self._cleanup() from pb.grid import PbGrid from pb.breaker import PbBreaker diff --git a/lib/pb/breaker.py b/lib/pb/breaker.py index a38030a..a6f6c92 100755 --- a/lib/pb/breaker.py +++ b/lib/pb/breaker.py @@ -1,15 +1,11 @@ #!/usr/bin/python2.7 import os -import sys import random import re -import urllib -import inspect -from config import * +from config import BIN_CONVERT from pb import Pb -from params import Params -DEFAULT_FINALFORMAT = "png"; +DEFAULT_FINALFORMAT = "png" _subtle_break_mark = 'pron' _extreme_break_mark = 'sugar' @@ -17,7 +13,7 @@ _extreme_break_mark = 'sugar' _header_offset = 2000 _default_breakmode = "subtle" -class PbBreaker(Pb): #FIXME in db gallery +class PbBreaker(Pb): example_params = { "url" : "http://i.asdf.us/im/de/HolyMountain2_1322275112_seamonkey.gif", "breaktype" : "RGB_WASH", @@ -28,36 +24,42 @@ class PbBreaker(Pb): #FIXME in db gallery "expanded" : "false" } def __init__(self, **kwargs): - super(PbBreaker,self).__init__(**kwargs); + super(PbBreaker, 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' ] } + '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.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") + self.params.finalformat.set_val("gif") elif self.params.breaktype == 'miff': - self.params.finalformat.set_val("jpg") - self.params.breakmode.set_val("subtle") + 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.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']) @@ -81,19 +83,23 @@ class PbBreaker(Pb): #FIXME in db gallery #}}} return breaktypeTranslate[key] -#{{{#########rotatefunctions####################################### +#{{{#########rotatefunctions###################################### def _rotate(self): - cmd = [BIN_CONVERT,self.params.url.path,"-rotate",self.params.breakangle,"+repage",self.params.url.path] - self._call_cmd(cmd) + 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) + 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) + 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): @@ -105,21 +111,21 @@ class PbBreaker(Pb): #FIXME in db gallery self._file_data = newfile[0:len(self._file_data)] def _extreme_break(self): - increment = len(self._file_data)/10; + increment = len(self._file_data)/10 i = 0 - newfile = ""; + newfile = "" for b in self._file_data: - if i > _header_offset and not (i % increment): + 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): + 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._call_cmd([BIN_CONVERT, self.params.url.path, jpg_file]) self._files_created.append(jpg_file) self._conversion_file = jpg_file @@ -131,16 +137,16 @@ class PbBreaker(Pb): #FIXME in db gallery 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' ]: + 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._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"); - + self.err_warn("Unable to get file data") + def _add_false_data(self): if self.params.breakmode == "subtle": self._subtle_break() @@ -148,10 +154,10 @@ class PbBreaker(Pb): #FIXME in db gallery self._extreme_break() f = open(self._conversion_file, 'w') f.write(self._file_data) - f.close(); + f.close() def _final_conversion(self): - self._call_cmd( [BIN_CONVERT, self._conversion_file, self.filepath]) + 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': @@ -164,8 +170,8 @@ class PbBreaker(Pb): #FIXME in db gallery self._rotate_back() def create(self): - self._prepare_filedata(); - self._add_false_data(); - self._final_conversion() + self._prepare_filedata() + self._add_false_data() + self._final_conversion() super(PbBreaker, self).create() diff --git a/lib/pb/generate.py b/lib/pb/generate.py index 088ca3c..12e3de1 100755 --- a/lib/pb/generate.py +++ b/lib/pb/generate.py @@ -5,136 +5,155 @@ from config import * from pb import Pb _default_tag = "im" -_gravity_params = ["NorthWest","North","NorthEast","West","Center","East","SouthWest","South","SouthEast"] +_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"] +_compose_params = [ + "Over", "ATop", "Dst_Over", "Dst_In", "Dst_Out", "Multiply", + "Screen", "Divide", "Plus", "Difference", "Exclusion", "Pin_Light", + "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' -#}}} + example_params = { + """Example params. Used with the classmethod Pb.run_example""" + 'nearest': 'true', + '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', + 'name': 'yo', + '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" }, +#}}} + def __init__(self, **kwargs): + super(PbGenerate, self).__init__(**kwargs) + _definitions = { + """ + Used to assert the value-types of the incoming parameters. + Types are defined as in their individual params classes. + """ + #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"}, - #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"}, - #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"}, - #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 }, + #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 + #STRINGS + "username": {'type': "string"}, + "callback": {'type': "string"}, + } - 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']) + + """Definitions and arguments are merged into attributes of the params object""" + self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__) + + """Used for the database tag column. Allows for tracking of the type + of overlay method used.""" + self.tag = _default_tag + 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); + """Imagemagick composite command""" + 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); - + """Imagemagick convert command""" + 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() + self._convert() + if self.params.background: + self._composite() + super(PbGenerate, self).create() diff --git a/lib/pb/gradient.py b/lib/pb/gradient.py index 22fe561..02d57d3 100755 --- a/lib/pb/gradient.py +++ b/lib/pb/gradient.py @@ -1,18 +1,11 @@ #!/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"; +_default_bevel_percent = "12" _halftone_values = { "checkeredfade": "h6x6a", @@ -25,67 +18,71 @@ _halftone_values = { 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" + "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); + 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' } + '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':[ + 'gradient', 'canvas', 'radial', 'colorspace', + 'mirrored', 'plasmawash', 'gradientwash', 'noise' + ], 'default': 'gradient'}, + 'username': {'type':'string'} } - self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__); + self.params.definitions_import(_definitions, kwargs, classname=self.__class__.__name__) self.filename, self.filepath = self._filename_filepath_create() - def _filename_create(self, **kwargs): + def _filename_create(self): _base = "{}{}-{}_{}".format( - self.__class__.__name__, - str(self.params.color1).replace('#','').replace('(','-').replace(')','-'), - str(self.params.color2).replace('#','').replace('(','-').replace(')','-'), - self._now, + 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 @@ -95,20 +92,20 @@ class PbGradient(Pb): cmd = [BIN_CONVERT] cmd.extend([ '-size', - "{}x{}".format(self.params.width,self.params.height) + "{}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.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), + "gradient" : ["gradient:{}-{}".format(self.params.color1, self.params.color2)], "canvas" : ["canvas:{}".format(self.params.color1)], "radial" : [ - "radial-gradient:{}-{}".format( self.params.color1, self.params.color2) - ], + "radial-gradient:{}-{}".format(self.params.color1, self.params.color2) + ], "colorspace" : [ "-colorspace", "Gray", @@ -116,7 +113,7 @@ class PbGradient(Pb): ], "mirrored" : [ "plasma:{}-{}".format(self.params.color1, self.params.color2), - "\(","+clone","-flop","\)", + "\(", "+clone", "-flop", "\)", "append" ], "plasmawash" : [ @@ -125,34 +122,35 @@ class PbGradient(Pb): ], "gradientwash" : [ "gradient:{}-{}".format(self.params.color1, self.params.color2), - "-set","colorspace","HSB" + "-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.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)) + 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: + if str(self.params.halftone) in _halftone_values: cmd.extend([ - "-ordered-dither", + "-ordered-dither", _halftone_values[str(self.params.halftone)] ]) - cmd += [ - '-modulate', + cmd += [ + '-modulate', "{},{},{}".format( - self.params.brightness or "100", - self.params.saturation or "100", - self.params.hue or "100") + self.params.brightness or "100", + self.params.saturation or "100", + self.params.hue or "100" + ) ] - cmd.append(self.filepath); + cmd.append(self.filepath) self._call_cmd(cmd) if self.params.bevel: self._make_bevel() @@ -163,19 +161,19 @@ class PbGradient(Pb): 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"], + "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] + cmd += self._get_bevelvalue() + cmd += [self.filepath, self.filepath] self._call_cmd(cmd) def create(self): diff --git a/lib/pb/grid.py b/lib/pb/grid.py index 53d31df..0fafd1c 100755 --- a/lib/pb/grid.py +++ b/lib/pb/grid.py @@ -3,7 +3,8 @@ 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 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 @@ -22,53 +23,75 @@ class PbGrid(Pb): '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' }, + 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__); + 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) + 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) + 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.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]) + 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.width or DEFAULT_WIDTH, self.params.height or DEFAULT_HEIGHT ) if self.params.bgimage: - return + return bgcolor = "xc:{}".format(self.params.bgcolor or 'transparent') - cmd = [ BIN_CONVERT, "-size", dimensions, bgcolor, self.filepath ] + cmd = [BIN_CONVERT, "-size", dimensions, bgcolor, self.filepath] self._call_cmd(cmd) #2nd step-- run grid @@ -77,18 +100,18 @@ class PbGrid(Pb): if self.params.spacing: if self.params.vlines: width = 2 * int(self.params.width or DEFAULT_WIDTH) - cmd += ["-s","{},{}".format(self.params.spacing,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)] + cmd += ["-s", "{},{}".format(height, self.params.spacing)] else: - cmd += ["-s",self.params.spacing] + 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] + 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 = [ @@ -99,15 +122,15 @@ class PbGrid(Pb): 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: + if self.params.zoom: cmd += ["zoom={}".format(self.params.zoom)] if cmd == [THREEDROTATE]: #if nothing has been added return @@ -124,27 +147,27 @@ class PbGrid(Pb): 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']) + _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 = [ + cmd = [ BIN_COMPOSITE, - "-compose", "Dst_Over", "-gravity", "center", - self.params.planebgimage["path"], + "-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) @@ -157,5 +180,5 @@ class PbGrid(Pb): 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() + if self.params.trim: self._trim_cmd() super(PbGrid, self).create() diff --git a/lib/pb/pattern.py b/lib/pb/pattern.py index 040eb18..a9ab879 100755 --- a/lib/pb/pattern.py +++ b/lib/pb/pattern.py @@ -19,23 +19,33 @@ class PbPattern(Pb): # "username" : "garfield", "image_url" : "http://i.asdf.us/im/be/PinkHijab_1425078647_reye.gif", } + example_params = { + "username":"pepper", + "pattern_data":"", + "pattern_url":"http://asdf.us/impattern/patterns/63.png", + "image_url":"http://i.asdf.us/im/b4/PbGradientwhiteblack-PbGrid_1443161086_pepper.png", + + } 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' }, + 'image_url': { 'type':'img_url' }, + 'pattern_url': { 'type':'img_url' }, + 'pattern_data': { 'type':'json' }, + '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() + if self.params.pattern_data: + _pattern_filename, self._pattern_filepath = self._filename_filepath_create(namepart="pattern") + 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") + else: + self._pattern_filepath = self.params.pattern_url['path'] + + self._db_url_param = str(self.params.image_url.url) - self._db_url_param = str(self.params.image_url) def _from_pattern_data(self): def boolToColor(boolean): @@ -43,7 +53,7 @@ class PbPattern(Pb): return (0,0,0,255); else: return (255,255,255,255) - specs = json.loads(str(self.params.pattern_data)); + specs = self.params.pattern_data.value; 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") @@ -51,7 +61,7 @@ class PbPattern(Pb): 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])); + pixels[j,i] = boolToColor(int(specs['matrix'][i][j])); img.save(self._pattern_filepath, "PNG") diff --git a/lib/server.py b/lib/server.py index e0f3140..8506c7a 100644 --- a/lib/server.py +++ b/lib/server.py @@ -1,10 +1,14 @@ from flask import Flask from flask import abort, redirect, url_for, request, jsonify -from cherrypy import wsgiserver + import sys, os +import cherrypy +from paste.translogger import TransLogger + sys.path.append("./lib") from pb import * from config import SERVER_HOST, SERVER_PORT +#http://flask.pocoo.org/docs/0.10/deploying/fastcgi/ this should be the one class InvalidUsage(Exception): status_code = 400 @@ -28,7 +32,7 @@ class Server(object): @self.app.route('/test', methods=['GET']) def test(): return "HELLO WORLD!" - @self.app.route('/', methods=['POST']) + @self.app.route('/im/api/', methods=['POST']) def pb(pb_classname): return self._response_post(pb_classname, request.form.to_dict()) @@ -41,7 +45,7 @@ class Server(object): self._classname_aliases = { 'generate' : 'PbGenerate', 'imgrid' : 'PbGrid', - 'imbreak' : 'PbBreak', + 'imbreak' : 'PbBreaker', 'impattern' : 'PbPattern', 'imgradient' : 'PbGradient', 'landscape' : 'PbLandscape', @@ -74,19 +78,31 @@ class Server(object): raise; return jsonify({ 'error' : 'Request could not be processed' }) - def run(self): - self.app.run() + def run(self, host=SERVER_HOST, port=SERVER_PORT): + self.app.run(host=host, port=port) + +#http://fgimian.github.io/blog/2012/12/08/setting-up-a-rock-solid-python-development-web-server/ def run_wsgi(self, server_port=SERVER_PORT, host=SERVER_HOST): - d = wsgiserver.WSGIPathInfoDispatcher({'/': self.app}) - sys.stderr.write("Starting a wsgi server on %s port %s\n" % (host, server_port)) - self._wsgi_server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', server_port), d) - self._wsgi_server.start() + # Enable WSGI access logging via Paste + app_logged = TransLogger(self.app) + + # Mount the WSGI callable object (app) on the root directory + cherrypy.tree.graft(app_logged, '/') + + # Set the configuration of the web server + cherrypy.config.update({ + 'engine.autoreload_on': True, + 'log.screen': True, + 'server.socket_port': server_port, + 'server.socket_host': host + }) + cherrypy.engine.start() + cherrypy.engine.block() + def stop(self): if self._wsgi_server: - self._wsgi_server.stop() - self._wsgi_server = None return else: return -- cgit v1.2.3-70-g09d2