Skip to content

Instantly share code, notes, and snippets.

@risicle
Created July 2, 2018 20:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save risicle/0a8ea7dd2231fbb1c559fcc882636c0f to your computer and use it in GitHub Desktop.
Save risicle/0a8ea7dd2231fbb1c559fcc882636c0f to your computer and use it in GitHub Desktop.
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