#!/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