render.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #!/usr/bin/env python3
  2. import matplotlib.pyplot as plt
  3. import struct
  4. from PIL import Image
  5. IMG_WIDTH = 640
  6. SYNC_LENGTH = 105
  7. SYNC_THRESH = 100
  8. PORCH_LENGTH = 10
  9. LINE_LENGTH = SYNC_LENGTH + PORCH_LENGTH + 4 * IMG_WIDTH
  10. MAX_DEV = 600
  11. CENTER = 1750
  12. MIN_FREQ = 1200
  13. MAX_FREQ = 2300
  14. COLOR_LOW = 1500
  15. COLOR_HIGH = MAX_FREQ
  16. def to_freq(sample):
  17. freq = CENTER + sample * MAX_DEV
  18. freq = max(MIN_FREQ, freq)
  19. freq = min(MAX_FREQ, freq)
  20. return freq
  21. def to_color(sample):
  22. sample = (sample - 1500) / (COLOR_HIGH - COLOR_LOW)
  23. sample = int(sample * 255)
  24. sample = max(sample, 0)
  25. sample = min(sample, 255)
  26. return sample
  27. def ycbcr_to_rgb(y, cb, cr):
  28. #https://stackoverflow.com/questions/4041840/function-to-convert-ycbcr-to-rgb/15333019#15333019
  29. cr = cr - 128 ;
  30. cb = cb - 128 ;
  31. r = y + 45 * cr / 32 ;
  32. g = y - (11 * cb + 23 * cr) / 32 ;
  33. b = y + 113 * cb / 64 ;
  34. return (int(r), int(g), int(b))
  35. last_sync = False
  36. def is_sync(backlog):
  37. global last_sync
  38. count = 0
  39. for sample in backlog:
  40. if sample < COLOR_LOW:
  41. count += 1
  42. res = False
  43. if count > SYNC_THRESH and not last_sync:
  44. res = True
  45. last_sync = count > SYNC_THRESH
  46. return res
  47. def render_lines(line):
  48. pixels = [[(0,0,0)] * IMG_WIDTH, [(0,0,0)] * IMG_WIDTH]
  49. # Strip porch
  50. porch = len(line) - SYNC_LENGTH - 4 * IMG_WIDTH
  51. if porch < 0:
  52. return pixels
  53. line = line[PORCH_LENGTH:]
  54. for i in range(0, IMG_WIDTH):
  55. y0 = to_color(line[i])
  56. cr = to_color(line[IMG_WIDTH + i])
  57. cb = to_color(line[2 * IMG_WIDTH + i])
  58. y1 = to_color(line[3 * IMG_WIDTH + i])
  59. pixels[0][i] = ycbcr_to_rgb(y0, cb, cr)
  60. pixels[1][i] = ycbcr_to_rgb(y1, cb, cr)
  61. return pixels
  62. def main():
  63. data_file = open("demod.dat", 'rb')
  64. samples = []
  65. syncs = []
  66. pixels = []
  67. backlog = [0.0] * SYNC_LENGTH
  68. line = []
  69. bytes = data_file.read(4)
  70. while len(bytes) == 4:
  71. sample = struct.unpack('f', bytes)[0]
  72. sample = to_freq(sample)
  73. samples += [sample]
  74. backlog = backlog[1:] + [sample]
  75. line += [sample]
  76. if is_sync(backlog) or len(line) > LINE_LENGTH:
  77. if len(line) > SYNC_LENGTH + 4 * IMG_WIDTH:
  78. syncs += [1000]
  79. print("%d \t %d" % (len(line), len(line) - LINE_LENGTH))
  80. pixels += render_lines(line)
  81. else:
  82. print("Short line dropped")
  83. line = []
  84. else:
  85. syncs += [0]
  86. bytes = data_file.read(4)
  87. plt.plot(samples)
  88. plt.plot(syncs)
  89. plt.show()
  90. img = Image.new('RGB', (IMG_WIDTH, len(pixels)))
  91. img_pix = img.load()
  92. for x in range(0, IMG_WIDTH):
  93. for y in range(0, len(pixels)):
  94. img_pix[x,y] = pixels[y][x]
  95. img.save('output.png')
  96. if __name__ == '__main__':
  97. main()