diff options
Diffstat (limited to 'pb/breaker.py')
| -rwxr-xr-x | pb/breaker.py | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/pb/breaker.py b/pb/breaker.py new file mode 100755 index 0000000..c982b14 --- /dev/null +++ b/pb/breaker.py @@ -0,0 +1,268 @@ +#!/usr/bin/python2.7 +import os +import sys +import random +import re +import pb.lib.utils as utils +import urllib +from pb.config import * + +DEFAULT_FINALFORMAT = "png"; +SUBTLE_BREAK_MARK = 'pron' +EXTREME_BREAK_MARK = 'sugar' + +HEADER_OFFSET = 2000 + +# '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', + +class Breaker(): + def __init__(self, **kwargs): + self.params = {} + self.tag = "imBreak" + self.commands = []; + self._required_keys = [ + "url", + "breaktype", + "finalformat", + "breakmode", + "breakangle", + "username", + "expanded" + ] + self.now = utils.now() + self.files_created = [] + for k in self._required_keys: + if k in kwargs: + if k == 'breaktype': + self.params['breaktype'] = self._get_breaktype(kwargs[k]) + elif k == 'url': + self.params[k] = kwargs[k] + else: + self.params[k] = utils.bool_correct(utils.sanitize(kwargs[k])) + else: + self.params[k] = False; + + + self.params = utils.dotdict(self.params) + + self.basename, self._first_format = self._get_filename(); + self._downloaded_file = os.path.join(WORKING_DIR, "IMBREAKTMP{}.{}".format(self.basename, self._first_format)) # same here + + try: + utils.download(self.params.url, self._downloaded_file) + self.files_created.append(self._downloaded_file) + except Exception as e: + sys.stderr.write(str(e)) + raise; + self._gif_frames = utils.gif_frames(self._downloaded_file) + self._gif_frames = self._gif_frames if len(self._gif_frames) > 1 else False + self.width, self.height = utils.dimensions(self._downloaded_file) # same here + + if not self.params.finalformat: + self.params.finalformat = DEFAULT_FINALFORMAT + if 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(WORKING_DIR, self.filename) + self._conversion_file = os.path.join(WORKING_DIR, "IMBREAKTMP{}.{}".format(self.basename, self.params.breaktype)) # this + + + def _call_cmd(self, cmd, error=""): + try: + utils.call_cmd(cmd) + self.commands.append(" ".join(cmd)); + except Exception: + raise Exception("Unable to call cmd {}".format(str(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] + + def _get_filename (self): + url = self.params.url + name_part = ""; + file_format = ""; + if "?" in url: + url = url.split("?")[0] + if "/" in url: + url = urllib.unquote(url).replace(" ","") + name_part = url.split("/")[-1] + try: + parts = name_part.split(".") + name_part = utils.sanitize(parts[-2]) + file_format = utils.sanitize(parts[-1]) + if not name_part or not file_format: + sys.stderr.write( "Incompatible input file type") + raise; + except Exception as e: + sys.stderr.write( "Incompatible input file type") + raise; + else: + sys.stderr.write( "Incompatible url") + raise; + if (len(name_part) > 20): + name_part = name_part[:-20] + return "{}{}_{}_{}".format(self.tag, name_part, self.now, self.params.username or ""), file_format + +#{{{#########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 = "" + newfile = self.file_data[0:breakpoint]; + newfile += SUBTLE_BREAK_MARK; + newfile += 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) + cmd = [BIN_CONVERT, frame, self._downloaded_file] + self._call_cmd(cmd) + + 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 = os.path.join(WORKING_DIR, "{}.{}".format(self.basename, "jpg")) + cmd = [BIN_CONVERT,self._downloaded_file,jpg_file] + self._call_cmd(cmd) + cmd = ["rm",self._downloaded_file] + self._call_cmd(cmd) + + + def _first_conversion(self): + if self._first_format == self.params.breaktype: + self._downloaded_file = self._conversion_file + return + cmd = [BIN_CONVERT, self._downloaded_file, self._conversion_file] + self._call_cmd(cmd) + self.files_created.append(self._conversion_file) + + def _read_data(self, filepath): + f = open(filepath, 'r'); + data = f.read() + f.close() + return data + + 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._read_data(self._conversion_file) + if not self.file_data: + sys.stderr.write("Unable to get file_data") + raise; + + 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(); + +#{{{ SHRINK (UNUSED) + def _shrink(self): + cmd = [ BIN_CONVERT, "-resize", "500x500", self._downloaded_file, self._downloaded_file ]; + self._call_cmd(cmd) +#}}} + + def _final_conversion(self): + cmd = [BIN_CONVERT, self._conversion_file, self.filepath] + self._call_cmd(cmd) + def psd_psbfilepath(num): + return os.path.join(WORKING_DIR, "{}-{}.{}".format(self.basename, num, self.params.finalformat)) + if self.params.breaktype == 'psd': + cmd = ['mv', psd_psbfilepath(1), self.filepath] + self._call_cmd(cmd) + self.files_created.append(psd_psbfilepath(0)) + if self.params.breaktype == 'psb': + cmd = ['mv', psd_psbfilepath(0), self.filepath] + self._call_cmd(cmd) + 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() + +if __name__ == "__main__": + 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 = Breaker(**TEST_PARAMS) + b.create(); + print b.filepath |
