Skip to content

Instantly share code, notes, and snippets.

@possan
Last active February 12, 2026 16:56
Show Gist options
  • Select an option

  • Save possan/15b45a13d640608d90dbb643ef394025 to your computer and use it in GitHub Desktop.

Select an option

Save possan/15b45a13d640608d90dbb643ef394025 to your computer and use it in GitHub Desktop.
import time
import cv2
#
# Terribly slow converter from video to proprietary undocumented hologram file format.
#
# Input file, square video in any format opencv can read, recommended > 256x256.
#
# Installation:
# python -m venv pyenv
# . pyenvbin/activate
# pip3 install opencv-python
# python3 testvideo2.py
#
MODEL_ID = 224
LINE_PIXEL_NUM = 112
ANGLE_NUM = 450
FRAMESKIP = 1
def chunks(lst, n):
"""Yield successive n-sized chunks from lst."""
for i in range(0, len(lst), n):
yield lst[i:i + n]
def writeHeaders(f, numframes):
arr = []
# Header
for k in range(4096):
arr.append(ord('h'))
arr[0] = MODEL_ID
arr[1] = 0
arr[2] = 0
arr[3] = 1 if numframes > 0 else 60 # framerate mayhaps?
arr[4] = MODEL_ID
# Random encryption thing, 0 = 0x61
arr[888] = 0
for k in range(0x61 * 4):
arr.append(ord('e'))
f.write(bytearray(arr))
def bitArrayToByte(bits):
bitsstr = ''.join(map(lambda bit: str(bit), bits))
return int(bitsstr, 2)
# This is the slow part, converting the colors to individual bitmasks
def writeFrame(f, img):
arr = []
height, width, channels = img.shape
for r in range(height):
for bp in range(6):
bpb = []
bpv = 1 << (5 - bp)
for c in range(width):
cb, cg, cr = img[r, c]
bpb.append(1 if ((cb >> 2) & bpv) == bpv else 0) # blue bit
bpb.append(1 if ((cg >> 2) & bpv) == bpv else 0) # green bit
bpb.append(1 if ((cr >> 2) & bpv) == bpv else 0) # red bit
bytechunks = list(map(bitArrayToByte, list(chunks(bpb, 8))))
arr += bytechunks
# Pad frame
pad = 114688 - len(arr)
for k in range(pad):
arr.append(0)
f.write(bytearray(arr))
def processFrame(cap, img, f, idx):
t0 = time.time()
height, width, channels = img.shape
print( "img size: %d x %d x %d channels" % (width, height, channels))
print (img[int(width/2), int(height/2), 0]) #B Channel Value
# if idx == 0:
# cv2.imshow("input", img)
squaresize = min(width, height)
ox = int((width - squaresize) / 2)
oy = int((height - squaresize) / 2)
print ("Square size: %d (offset %d, %d)" % (squaresize, ox, oy))
cropped_image = img[oy:oy+squaresize, ox:ox+squaresize]
cropped_image = cv2.flip(cropped_image, 0)
t1 = time.time()
polar = cv2.linearPolar(cropped_image, (squaresize/2, squaresize/2), squaresize/2, cv2.WARP_FILL_OUTLIERS)
output = cv2.resize(polar, (112, 450));
output = cv2.flip(output, 1)
t2 = time.time()
# if idx == 0:
# cv2.imshow("output", output)
# cv2.waitKey(0)
writeFrame(f, output)
t3 = time.time()
print("timing: %f, %f, %f" % (t1 - t0, t2 - t1, t3 - t2))
def processVideo(infn, outfn):
f = open(outfn, 'wb')
cap = cv2.VideoCapture(infn)
totalFrames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
print ("Total frames: %d" % totalFrames)
framesToWrite = int(totalFrames / FRAMESKIP)
writeHeaders(f, framesToWrite)
# res, frame = cap.read()
# processFrame(cap, frame, f)
for fr in range(framesToWrite):
print ("Processing frame %d / %d" % (fr, framesToWrite))
res, frame = cap.read()
processFrame(cap, frame, f, fr)
# while True:
# ch = 0xFF & cv2.waitKey(1)
# if ch == 27:
# break
f.close()
# cv2.destroyAllWindows()
#
# Start conversion by specifying input and output paths
#
processVideo('video/yodaspin[0001-0100].mp4', 'temp/yodaspin.bin')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment