def setUp(self): """Run before the test.""" # Create an image in memory from PIL import Image from flask_iiif.api import MultimediaImage tmp_file = BytesIO() # create a new image image = Image.new("RGBA", (1280, 1024), (255, 0, 0, 0)) image.save(tmp_file, 'png') # create a new gif image self.image_gif = MultimediaImage( create_gif_from_frames([ Image.new("RGB", (1280, 1024), color) for color in ['blue', 'yellow', 'red', 'black', 'white'] ])) # Initialize it for our object and create and instance for # each test tmp_file.seek(0) self.image_resize = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_crop = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_rotate = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_errors = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_convert = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_save = MultimediaImage.from_string(tmp_file) # NOT RGBA tmp_file = BytesIO() # create a new image image = Image.new("RGB", (1280, 1024), (255, 0, 0, 0)) image.save(tmp_file, 'jpeg') tmp_file.seek(0) self.image_not_rgba = MultimediaImage.from_string(tmp_file) # Image in P Mode tmp_file = BytesIO() image = Image.new("P", (1280, 1024)) image.save(tmp_file, 'gif') tmp_file.seek(0) self.image_p_mode = MultimediaImage.from_string(tmp_file) # TIFF Image tmp_file = BytesIO() image = Image.new("RGBA", (1280, 1024), (255, 0, 0, 0)) image.save(tmp_file, 'tiff') tmp_file.seek(0) self.image_tiff = MultimediaImage.from_string(tmp_file)
def setUp(self, width=1280, height=1024): """Run before the test.""" # Create an image in memory tmp_file = BytesIO() # create a new image image = Image.new("RGBA", (width, height), (255, 0, 0, 0)) image.save(tmp_file, 'png') # create a new gif image self.image_gif = MultimediaImage(create_gif_from_frames([ Image.new("RGB", (width, height), color) for color in ['blue', 'yellow', 'red', 'black', 'white'] ])) self.width, self.height = width, height # Initialize it for our object and create and instance for # each test tmp_file.seek(0) self.image_resize = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_crop = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_rotate = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_errors = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_convert = MultimediaImage.from_string(tmp_file) tmp_file.seek(0) self.image_save = MultimediaImage.from_string(tmp_file) # NOT RGBA tmp_file = BytesIO() # create a new image image = Image.new("RGB", (width, height), (255, 0, 0, 0)) image.save(tmp_file, 'jpeg') tmp_file.seek(0) self.image_not_rgba = MultimediaImage.from_string(tmp_file) # Image in P Mode tmp_file = BytesIO() image = Image.new("P", (width, height)) image.save(tmp_file, 'gif') tmp_file.seek(0) self.image_p_mode = MultimediaImage.from_string(tmp_file) # TIFF Image tmp_file = BytesIO() image = Image.new("RGBA", (width, height), (255, 0, 0, 0)) image.save(tmp_file, 'tiff') tmp_file.seek(0) self.image_tiff = MultimediaImage.from_string(tmp_file)
def _create_gif(cls, bucket, frames, output_dir, master_id): """Generate a gif image.""" gif_filename = 'frames.gif' bucket = as_bucket(bucket) images = [] for f in frames: image = Image.open(file_opener_xrootd(f, 'rb')) # Convert image for better quality im = image.convert('RGB').convert( 'P', palette=Image.ADAPTIVE, colors=255 ) images.append(im) gif_image = create_gif_from_frames(images) gif_fullpath = os.path.join(output_dir, gif_filename) gif_image.save(gif_fullpath, save_all=True) cls._create_object(bucket=bucket, key=gif_filename, stream=open(gif_fullpath, 'rb'), size=os.path.getsize(gif_fullpath), media_type='image', context_type='frames-preview', master_id=master_id)
def run(self, frames_start=5, frames_end=95, frames_gap=10, *args, **kwargs): """Extract images from some frames of the video. Each of the frame images generates an ``ObjectVersion`` tagged as "frame" using ``ObjectVersionTags``. :param self: reference to instance of task base class :param frames_start: start percentage, default 5. :param frames_end: end percentage, default 95. :param frames_gap: percentage between frames from start to end, default 10. """ output_folder = tempfile.mkdtemp() in_output = partial(os.path.join, output_folder) # Remove temporary directory on abrupt execution halts. self.set_revoke_handler( lambda: shutil.rmtree(output_folder, ignore_errors=True)) # Calculate time positions duration = float(self._base_payload['tags']['duration']) time_step = duration * frames_gap / 100 start_time = duration * frames_start / 100 end_time = (duration * frames_end / 100) + 0.01 number_of_frames = ((frames_end - frames_start) / frames_gap) + 1 def progress_updater(current_frame): """Progress reporter.""" meta = dict( payload=dict( size=duration, percentage=current_frame / number_of_frames * 100, ), message='Extracting frames [{0} out of {1}]'.format( current_frame, number_of_frames), ) self.update_state(state=STARTED, meta=meta) def create_object(key, media_type, context_type, **tags): """Create object versions with given type and tags.""" obj = ObjectVersion.create(bucket=self.object.bucket, key=key, stream=open(in_output(key), 'rb')) ObjectVersionTag.create(obj, 'master', self.obj_id) ObjectVersionTag.create(obj, 'media_type', media_type) ObjectVersionTag.create(obj, 'context_type', context_type) [ObjectVersionTag.create(obj, k, tags[k]) for k in tags] try: # Generate frames ff_frames(input_file=self.object.file.uri, start=start_time, end=end_time, step=time_step, duration=duration, progress_callback=progress_updater, output=os.path.join(output_folder, 'frame-{:d}.jpg')) except Exception as exc: db.session.rollback() shutil.rmtree(output_folder, ignore_errors=True) raise self.retry(max_retries=5, countdown=5, exc=exc) frames = sorted( os.listdir(output_folder), key=lambda f: int(f.rsplit('-', 1)[1].split('.', 1)[0])) [ create_object(filename, 'image', 'frame', timestamp=start_time + (i + 1) * time_step) for i, filename in enumerate(frames) ] # Generate GIF images gif_filename = 'frames.gif' images = [] for f in frames: image = Image.open(in_output(f)) # Convert image for better quality im = image.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255) images.append(im) gif_image = create_gif_from_frames(images) gif_image.save(in_output(gif_filename), save_all=True) create_object(gif_filename, 'image', 'frames-preview') # Cleanup shutil.rmtree(output_folder) db.session.commit()