Created
July 2, 2018 20:46
-
-
Save risicle/0a8ea7dd2231fbb1c559fcc882636c0f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import png | |
from PIL import Image, ImageMath | |
import array | |
import math | |
def _planes_from_png(filename): | |
with open(filename, "rb") as png_file: | |
reader = png.Reader(filename) | |
width, height, image_array, meta = reader.read_flat() | |
image_array_32 = array.array("I", image_array) | |
for plane_index in range(meta["planes"]): | |
yield Image.frombytes("I", (width, height), image_array_32[plane_index::3].tobytes()) | |
def _rescaled_plane(image, new_width, aspect_angle_deg): | |
x_margin = abs(0.5 * image.width * (1-math.sin(math.radians(90 - aspect_angle_deg)))) | |
return image.resize( | |
size=(new_width, image.height,), | |
resample=Image.LANCZOS, | |
box=(x_margin, 0, image.width - x_margin, image.height), | |
) | |
def _get_pixel_column_mapping(n_strips, n_pixel_columns, n_frames): | |
return ((column, math.floor(frac_frame*n_frames), int(strip)) for column, (frac_frame, strip) in ( | |
(column, math.modf(float(column)*n_strips/n_pixel_columns),) | |
for column in range(n_pixel_columns) | |
)) | |
def _peek(x): | |
import pdb; pdb.set_trace() | |
return x | |
def lenticufy(filenames, combined_image_width=2550, startangle_deg=45, n_strips=108, exposure_factor=2.6): | |
combined_image = None | |
conversion_expression = "convert(float(x)*{}, 'L')".format(exposure_factor/256.0) | |
pixel_column_mapping = tuple(_get_pixel_column_mapping(n_strips, combined_image_width, len(filenames))) | |
for file_index, filename in enumerate(filenames): | |
print(f"Processing {filename!r}") | |
rescaled_image = Image.merge("RGB", tuple( | |
ImageMath.eval( | |
conversion_expression, | |
x=_rescaled_plane(plane, n_strips, startangle_deg * (1 - (2.0 * file_index)/len(filenames))), | |
) for plane in _planes_from_png(filename) | |
)) | |
combined_image = combined_image or Image.new("RGB", (combined_image_width, rescaled_image.height)) | |
for final_pixel_column, frame, source_pixel_column in pixel_column_mapping: | |
if frame == file_index: | |
combined_image.paste( | |
rescaled_image.crop( | |
(source_pixel_column, 0, source_pixel_column+1, rescaled_image.height) | |
), | |
box=(final_pixel_column, 0), | |
) | |
return combined_image |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment