I would like to play a video (with python) on my HP Prime G2. I know this sounds stupid but please.
So, I already converted the video to a list of pixels but I realise that drawing the pixels one by one on the screen is VERY VERY slow. So I'm wondering if there is any faster way of drawing a whole image (best solution but less probable) or a method, function or something like that to speedup the drawing process. I can draw a single pixel or a rectangle.
Here are my encode/decode python scripts if anyone is interested:
encode.py
import cv2
import numpy as np
COLOR_THRESHOLD = 60
PIXEL_SIZE = 2
WIDTH, HEIGHT = 320 // PIXEL_SIZE, 240 // PIXEL_SIZE
video = cv2.VideoCapture(r'./video.mp4')
def is_close_to_black(pixel, threshold=20):
# Check if any of the RGB values are below the threshold
return all(component < threshold for component in pixel)
def ColorDistance(rgb1, rgb2):
return np.linalg.norm(np.array(rgb1) - np.array(rgb2))
def rgb_to_hex(rgb):
hex_color = f'{rgb[0]:02x}{rgb[1]:02x}{rgb[2]:02x}'
return hex_color.upper()
with open('video.txt', 'w') as file: # Use 'w' for writing text data
currentframe = 0
lastframe = np.zeros((HEIGHT, WIDTH, 3), dtype=int)
while True:
ret, frame = video.read()
if not ret:
break
# Resize frame to match the defined WIDTH and HEIGHT
frame = cv2.resize(frame, (WIDTH, HEIGHT))
lines = []
for i, row in enumerate(frame):
filtered_pixels = [pixel for pixel in row if not is_close_to_black(pixel)]
if not filtered_pixels:
lines.append('0')
else:
row_result = []
for ii, pixel in enumerate(row):
if ColorDistance(lastframe[i][ii], pixel) < COLOR_THRESHOLD:
row_result.append('?')
else:
row_result.append(rgb_to_hex(pixel))
# Format the line for the current row
line = ','.join(row_result)
lines.append(line)
# Write the lines to the file
file.write(';'.join(lines) + '\n')
# Update the lastframe with the current frame
lastframe = frame.copy()
currentframe += 1
print('Done with frame ' + str(currentframe))
video.release()
decode.py
# PYTHON EXPORT giffer()
from graphic import draw_rectangle
PIXEL_SIZE = 2
WIDTH, HEIGHT = 320 // PIXEL_SIZE, 240 // PIXEL_SIZE
def hex_to_rgb(hex_color):
rgb = tuple(int(hex_color[i:i+2], 16) for i in (0, 2, 4))
return rgb
def process_line(line, y):
if line.strip() == '0':
draw_rectangle(0, 0, WIDTH * PIXEL_SIZE, PIXEL_SIZE, [0, 0, 0])
return
colors = line.strip().split(',')
x = 0
while x < len(colors):
if colors[x] == '?':
x += 1
continue
current_color = hex_to_rgb(colors[x])
start_x = x
# Find the length of the current run of the same color or '?'
while x < len(colors) and (colors[x] == '?' or colors[x] == colors[start_x]):
x += 1
end_x = x
# Draw the combined rectangle
draw_rectangle(start_x * PIXEL_SIZE, y * PIXEL_SIZE, (end_x - start_x) * PIXEL_SIZE, PIXEL_SIZE, [current_color[2], current_color[1], current_color[0]])
def process_frame(frame):
y = 0
for line in frame.split(';'):
process_line(line, y)
if y == HEIGHT:
y = 0
else:
y += 1
FILENAME = 'video' # input('File ID: ')
# Open the video file for reading in text mode ('r')
draw_rectangle(0, 0, WIDTH * PIXEL_SIZE, HEIGHT * PIXEL_SIZE, [0, 0, 0])
with open('../videos.hpappdir/' + FILENAME + '.txt', 'r', encoding='utf-8') as f:
for line in f:
process_frame(line)
# end
You can store files (like images) inside applications on the HP Prime.
Using the command AFiles(filename)
inside of an application script lets you access those files.
By using G1
(or G2-G9) = AFiles(filename)
and then P_BLIT
ing the image you stored in G1 to G0, you will have the entire image instantly drawn for you.
So, pass your video through the encode.py
script you've written, write a script to go through each frame and display it, and you should be good.
I highly recommend looking through your calculator's help system - there's a lot of useful information there.
Note - I do have a script that turns MP4s into videos for the calculator, but it is partially AI written (the encoding part) and so I cannot put it here.