129 lines
2.8 KiB
Python
129 lines
2.8 KiB
Python
#!/usr/bin/env python3
|
|
|
|
import matplotlib.pyplot as plt
|
|
import struct
|
|
|
|
from PIL import Image
|
|
|
|
IMG_WIDTH = 640
|
|
|
|
SYNC_LENGTH = 105
|
|
SYNC_THRESH = 100
|
|
PORCH_LENGTH = 10
|
|
|
|
LINE_LENGTH = SYNC_LENGTH + PORCH_LENGTH + 4 * IMG_WIDTH
|
|
|
|
MAX_DEV = 600
|
|
CENTER = 1750
|
|
MIN_FREQ = 1200
|
|
MAX_FREQ = 2300
|
|
|
|
COLOR_LOW = 1500
|
|
COLOR_HIGH = MAX_FREQ
|
|
|
|
def to_freq(sample):
|
|
freq = CENTER + sample * MAX_DEV
|
|
freq = max(MIN_FREQ, freq)
|
|
freq = min(MAX_FREQ, freq)
|
|
return freq
|
|
|
|
def to_color(sample):
|
|
sample = (sample - 1500) / (COLOR_HIGH - COLOR_LOW)
|
|
sample = int(sample * 255)
|
|
sample = max(sample, 0)
|
|
sample = min(sample, 255)
|
|
return sample
|
|
|
|
def ycbcr_to_rgb(y, cb, cr):
|
|
#https://stackoverflow.com/questions/4041840/function-to-convert-ycbcr-to-rgb/15333019#15333019
|
|
cr = cr - 128 ;
|
|
cb = cb - 128 ;
|
|
r = y + 45 * cr / 32 ;
|
|
g = y - (11 * cb + 23 * cr) / 32 ;
|
|
b = y + 113 * cb / 64 ;
|
|
|
|
return (int(r), int(g), int(b))
|
|
|
|
last_sync = False
|
|
def is_sync(backlog):
|
|
global last_sync
|
|
count = 0
|
|
for sample in backlog:
|
|
if sample < COLOR_LOW:
|
|
count += 1
|
|
|
|
res = False
|
|
if count > SYNC_THRESH and not last_sync:
|
|
res = True
|
|
|
|
last_sync = count > SYNC_THRESH
|
|
return res
|
|
|
|
|
|
def render_lines(line):
|
|
pixels = [[(0,0,0)] * IMG_WIDTH, [(0,0,0)] * IMG_WIDTH]
|
|
|
|
# Strip porch
|
|
porch = len(line) - SYNC_LENGTH - 4 * IMG_WIDTH
|
|
if porch < 0:
|
|
return pixels
|
|
line = line[PORCH_LENGTH:]
|
|
|
|
for i in range(0, IMG_WIDTH):
|
|
y0 = to_color(line[i])
|
|
cr = to_color(line[IMG_WIDTH + i])
|
|
cb = to_color(line[2 * IMG_WIDTH + i])
|
|
y1 = to_color(line[3 * IMG_WIDTH + i])
|
|
|
|
pixels[0][i] = ycbcr_to_rgb(y0, cb, cr)
|
|
pixels[1][i] = ycbcr_to_rgb(y1, cb, cr)
|
|
|
|
return pixels
|
|
|
|
def main():
|
|
data_file = open("demod.dat", 'rb')
|
|
|
|
samples = []
|
|
syncs = []
|
|
|
|
pixels = []
|
|
|
|
backlog = [0.0] * SYNC_LENGTH
|
|
line = []
|
|
|
|
bytes = data_file.read(4)
|
|
while len(bytes) == 4:
|
|
sample = struct.unpack('f', bytes)[0]
|
|
sample = to_freq(sample)
|
|
samples += [sample]
|
|
|
|
backlog = backlog[1:] + [sample]
|
|
|
|
line += [sample]
|
|
|
|
if is_sync(backlog) or len(line) > LINE_LENGTH:
|
|
if len(line) > SYNC_LENGTH + 4 * IMG_WIDTH:
|
|
syncs += [1000]
|
|
print("%d \t %d" % (len(line), len(line) - LINE_LENGTH))
|
|
pixels += render_lines(line)
|
|
else:
|
|
print("Short line dropped")
|
|
line = []
|
|
else:
|
|
syncs += [0]
|
|
|
|
bytes = data_file.read(4)
|
|
|
|
|
|
img = Image.new('RGB', (IMG_WIDTH, len(pixels)))
|
|
img_pix = img.load()
|
|
for x in range(0, IMG_WIDTH):
|
|
for y in range(0, len(pixels)):
|
|
img_pix[x,y] = pixels[y][x]
|
|
|
|
img.save('output.png')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|