def _glitch_gif(img_in: BytesIO, glitch_amount: float, glitch_change: float, scan_lines: bool) -> BytesIO: imgfile = BytesIO() glitcher = ImageGlitcher() img_in = Image.open(img_in) img_out, dur, frame_count = glitcher.glitch_gif( img_in, glitch_amount, color_offset=True, glitch_change=glitch_change, scan_lines=scan_lines) img_out[0].save(imgfile, format="gif", save_all=True, append_images=img_out[1:], duration=dur, loop=0, disposal=2, optimize=False) imgfile.name = "dank.gif" return imgfile
def main(): glitch_min, glitch_max = 1, 10 help_text = get_help(glitch_min, glitch_max) # Add commandline arguments parser argparser = argparse.ArgumentParser(description='Glitchify images to static images and GIFs!') argparser.add_argument('src_img_path', metavar='Image_Path', type=str, help=help_text['path']) argparser.add_argument('glitch_level', metavar='Glitch_Level', type=int, help=help_text['level']) argparser.add_argument('-c', '--color', dest='color', action='store_true', help=help_text['color']) argparser.add_argument('-s', '--scan', dest='scan_lines', action='store_true', help=help_text['scan']) argparser.add_argument('-g', '--gif', dest='gif', action='store_true', help=help_text['gif']) argparser.add_argument('-fr', '--frames', dest='frames', metavar='Frames', type=int, default=23, help=help_text['frames']) argparser.add_argument('-st', '--step', dest='step', metavar='Step', type=int, default=1, help=help_text['step']) argparser.add_argument('-i', '--increment', dest='increment', metavar='Increment', type=int, default=0, help=help_text['increment']) argparser.add_argument('-cy', '--cycle', dest='cycle', action='store_true', help=help_text['cycle']) argparser.add_argument('-d', '--duration', dest='duration', metavar='Duration', type=int, default=200, help=help_text['duration']) argparser.add_argument('-rd', '--relative_duration', dest='rel_duration', metavar='Relative_Duration', type=float, help=help_text['relative_duration']) argparser.add_argument('-l', '--loop', dest='loop', metavar='Loop_Count', type=int, default=0, help=help_text['loop']) argparser.add_argument('-ig', '--inputgif', dest='input_gif', action='store_true', help=help_text['inputgif']) argparser.add_argument('-f', '--force', dest='force', action='store_true', help=help_text['force']) argparser.add_argument('-o', '--outfile', dest='outfile', metavar='Outfile_path', type=str, help=help_text['out']) args = argparser.parse_args() # Sanity check inputs if not args.duration > 0: raise ValueError('Duration must be greater than 0') if not args.loop >= 0: raise ValueError('Loop must be greater than or equal to 0') if not args.frames > 0: raise ValueError('Frames must be greater than 0') if not os.path.isfile(args.src_img_path): raise FileNotFoundError('No image found at given path') # Set up full_path, for output saving location out_path, out_file = os.path.split(Path(args.src_img_path)) out_filename, out_fileex = out_file.rsplit('.', 1) out_filename = 'glitched_' + out_filename # Output file extension should be '.gif' if output file is going to be a gif out_fileex = 'gif' if args.gif else out_fileex if args.outfile: # If output file path is already given # Overwrite the previous values out_path, out_file = os.path.split(Path(args.outfile)) if out_path != '' and not os.path.exists(out_path): raise Exception('Given outfile path, ' + out_path + ', does not exist') # The extension in user provided outfile path is ignored out_filename = out_file.rsplit('.', 1)[0] # Now create the full path full_path = os.path.join(out_path, '{}.{}'.format(out_filename, out_fileex)) if os.path.exists(full_path) and not args.force: raise Exception(full_path + ' already exists\nCannot overwrite ' 'existing file unless -f or --force is included\nProgram Aborted') # Actual work begins here glitcher = ImageGlitcher() t0 = time() if not args.input_gif: # Get glitched image or GIF (from image) glitch_img = glitcher.glitch_image(args.src_img_path, args.glitch_level, glitch_change=args.increment, cycle=args.cycle, scan_lines=args.scan_lines, color_offset=args.color, gif=args.gif, frames=args.frames, step=args.step) else: # Get glitched image or GIF (from GIF) glitch_img, src_duration, args.frames = glitcher.glitch_gif(args.src_img_path, args.glitch_level, glitch_change=args.increment, cycle=args.cycle, scan_lines=args.scan_lines, color_offset=args.color, step=args.step) # Set args.gif to true if it isn't already in this case args.gif = True # Set args.duration to src_duration * relative duration, if one was given args.duration = args.duration if not args.rel_duration else int(args.rel_duration * src_duration) t1 = time() # End of glitching t2 = time() # Save the image if not args.gif: glitch_img.save(full_path, compress_level=3) t3 = time() print('Glitched Image saved in "{}"'.format(full_path)) else: glitch_img[0].save(full_path, format='GIF', append_images=glitch_img[1:], save_all=True, duration=args.duration, loop=args.loop, compress_level=3) t3 = time() print('Glitched GIF saved in "{}"\nFrames = {}, Duration = {}, Loop = {}'.format(full_path, args.frames, args.duration, args.loop)) print('Time taken to glitch: ' + str(t1 - t0)) print('Time taken to save: ' + str(t3 - t2)) print('Total Time taken: ' + str(t3 - t0)) # Let the user know if new version is available if not islatest(ImageGlitcher.__version__): print('A new version of "glitch-this" is available. Please consider upgrading via `pip install --upgrade glitch-this`')
class Glitcher: def __init__(self, url): self.image = Image(url) @property def __glitcherWithParams(self): self.imGltch = ImageGlitcher() amount = round(random.uniform(6.0, 10.0), 2) scanlines = bool(random.getrandbits(1)) colorOffset = bool(random.getrandbits(1)) return amount, scanlines, colorOffset def __glitchGIF(self, src, dest): amount, scanlines, colorOffset = self.__glitcherWithParams # cycle = bool(random.getrandbits(1)) change = round(random.uniform(1.0, 3.0), 2) # Account for potential glitch_amount overflow while (amount + change) >= 10.0: change -= 0.1 while (amount - change) <= 0.1: change += 0.1 glitch, duration_, _ = self.imGltch.glitch_gif( src_gif=src.name, glitch_amount=amount, glitch_change=change, cycle=False, color_offset=colorOffset, scan_lines=scanlines) try: glitch[0].save(dest.name, format='GIF', append_images=glitch[1:], save_all=True, duration=duration_, loop=0) except: print(f'ERROR: Failed to save GIF glitch [{dest.name}]') def __glitchStatic(self, src, dest): amount, scanlines, colorOffset = self.__glitcherWithParams glitch = self.imGltch.glitch_image(src_img=src.name, glitch_amount=amount, color_offset=colorOffset, scan_lines=scanlines) # Save file try: glitch.save(dest.name) except: print(f'ERROR: Failed to save static glitch [{dest.name}]') def glitch(self): imgFile = self.image.asFile suffix = self.image.type glitchFile = tempfile.NamedTemporaryFile(suffix=f'.{suffix}') if suffix == 'gif': self.__glitchGIF(imgFile, glitchFile) else: self.__glitchStatic(imgFile, glitchFile) imgFile.close() return glitchFile
def main(): # Add commandline arguments parser argparser = argparse.ArgumentParser( description='Glitchify images to static images and GIFs!') argparser.add_argument( 'src_img_path', metavar='Image_Path', type=str, help='Relative or Absolute string path to source image') argparser.add_argument( 'glitch_level', metavar='Glitch_Level', type=int, help= 'Integer between 1 and 10, inclusive, representing amount of glitchiness' ) argparser.add_argument( '-c', '--color', dest='color', action='store_true', help='Whether or not to add color offset, defaults to False') argparser.add_argument( '-s', '--scan', dest='scan_lines', action='store_true', help='Whether or not to add scan lines effect, defaults to False') argparser.add_argument( '-g', '--gif', dest='gif', action='store_true', help='Include if you want a GIF instead of static image' '\nNOTE: Does nothing if input image is GIF, i.e when using `-ig`') argparser.add_argument( '-fr', '--frames', dest='frames', metavar='Frames', type=int, default=23, help='How many frames to include in GIF, defaults to 23' '\nNOTE: Does nothing if input image is GIF, i.e when using `-ig`') argparser.add_argument( '-d', '--duration', dest='duration', metavar='Duration', type=int, default=200, help='How long to display each frame (in centiseconds), defaults to 200' ) argparser.add_argument( '-l', '--loop', dest='loop', metavar='Loop_Count', type=int, default=0, help='How many times the glitched GIF should loop, defaults to 0 ' '(i.e infinite loop)') argparser.add_argument( '-ig', '--inputgif', dest='input_gif', action='store_true', help='If input image is GIF, use for glitching GIFs to GIFs! ' 'Defaults to False\nNOTE: This is a slow process') argparser.add_argument( '-f', '--force', dest='force', action='store_true', help= 'If included, overwrites existing output file of same name (if found)' '\nDefaults to False') argparser.add_argument( '-o', '--outfile', dest='outfile', metavar='Outfile_path', type=str, help='Explictly supply the full or relative `path/filename`\ \nDefaults to ./glitched_src_image_path') args = argparser.parse_args() # Sanity check inputs if not args.duration > 0: raise ValueError('Duration must be greater than 0') if not args.loop >= 0: raise ValueError('Loop must be greater than or equal to 0') if not args.frames > 0: raise ValueError('Frames must be greater than 0') if not os.path.isfile(args.src_img_path): raise FileNotFoundError('No image found at given path') # Set up full_path, for output saving location out_path, out_file = os.path.split(Path(args.src_img_path)) out_filename, out_fileex = out_file.rsplit('.', 1) out_filename = 'glitched_' + out_filename # Output file extension should be '.gif' if output file is going to be a gif out_fileex = 'gif' if args.gif else out_fileex if args.outfile: # If output file path is already given # Overwrite the previous values out_path, out_file = os.path.split(Path(args.outfile)) if out_path != '' and not os.path.exists(out_path): raise Exception('Given outfile path, ' + out_path + ', does not exist') # The extension in user provided outfile path is ignored out_filename = out_file.rsplit('.', 1)[0] # Now create the full path full_path = os.path.join(out_path, '{}.{}'.format(out_filename, out_fileex)) if os.path.exists(full_path) and not args.force: raise Exception( full_path + ' already exists\nCannot overwrite ' 'existing file unless -f or --force is included\nProgram Aborted') # Actual work begins here glitcher = ImageGlitcher() t0 = time() if not args.input_gif: # Get glitched image or GIF (from image) glitch_img = glitcher.glitch_image(args.src_img_path, args.glitch_level, scan_lines=args.scan_lines, color_offset=args.color, gif=args.gif, frames=args.frames) else: # Get glitched image or GIF (from GIF) glitch_img, src_duration, args.frames = glitcher.glitch_gif( args.src_img_path, args.glitch_level, scan_lines=args.scan_lines, color_offset=args.color) args.gif = True # Set args.gif to true if it isn't already in this case t1 = time() # End of glitching t2 = time() # Save the image if not args.gif: glitch_img.save(full_path, compress_level=3) t3 = time() print('Glitched Image saved in "{}"'.format(full_path)) else: glitch_img[0].save(full_path, format='GIF', append_images=glitch_img[1:], save_all=True, duration=args.duration, loop=args.loop, compress_level=3) t3 = time() print( 'Glitched GIF saved in "{}"\nFrames = {}, Duration = {}, Loop = {}' .format(full_path, args.frames, args.duration, args.loop)) print('Time taken to glitch: ' + str(t1 - t0)) print('Time taken to save: ' + str(t3 - t2)) print('Total Time taken: ' + str(t3 - t0)) # Let the user know if new version is available if not islatest(ImageGlitcher.__version__): print( 'A new version of "glitch-this" is available. Please consider upgrading via `pip install --upgrade glitch-this`' )