From 8ecf7226706c8cf53480042317d95cb080d79cc4 Mon Sep 17 00:00:00 2001 From: colaclanth Date: Mon, 15 Jul 2019 17:46:41 +0100 Subject: [PATCH] Improved formatting --- sstv/__init__.py | 2 ++ sstv/__main__.py | 3 +++ sstv/command.py | 10 +++++--- sstv/common.py | 13 ++++++---- sstv/decode.py | 64 ++++++++++++++++++++++++++---------------------- sstv/spec.py | 5 +++- 6 files changed, 58 insertions(+), 39 deletions(-) diff --git a/sstv/__init__.py b/sstv/__init__.py index 8b6dd13..7ce99e2 100644 --- a/sstv/__init__.py +++ b/sstv/__init__.py @@ -1,2 +1,4 @@ +#!/usr/bin/env python + from .command import SSTVCommand from .decode import SSTVDecoder diff --git a/sstv/__main__.py b/sstv/__main__.py index 8f402f7..6e97269 100644 --- a/sstv/__main__.py +++ b/sstv/__main__.py @@ -1,9 +1,12 @@ #!/usr/bin/env python + import sstv + def main(): with sstv.SSTVCommand() as prog: prog.start() + if __name__ == "__main__": main() diff --git a/sstv/command.py b/sstv/command.py index 02e0e43..5209e1c 100644 --- a/sstv/command.py +++ b/sstv/command.py @@ -1,9 +1,10 @@ #!usr/bin/env python + from sys import exit -from os import path from .decode import SSTVDecoder import argparse + class SSTVCommand(object): """ Main class to handle the command line features """ @@ -48,7 +49,8 @@ examples: help="desination of output file", default="result.png", dest="output_file") - parser.add_argument("-V", "--version", action="version", version=version) + parser.add_argument("-V", "--version", action="version", + version=version) parser.add_argument("-v", "--verbose", action="count", default=1, help="increase output to the terminal") parser.add_argument("--list-modes", action="store_true", @@ -69,7 +71,7 @@ examples: self._audio_file = args.audio_file self._output_file = args.output_file - + if args.list_modes: self.list_supported_modes() exit(0) @@ -93,7 +95,7 @@ examples: img.save(self._output_file) except KeyError: img.save("result.png") - + def close(self): """ Closes any input/output files if they exist """ if self._output_file is not None and not self._output_file.closed: diff --git a/sstv/common.py b/sstv/common.py index 10d628e..355f8f2 100644 --- a/sstv/common.py +++ b/sstv/common.py @@ -1,7 +1,9 @@ #!usr/bin/env python + from sys import stderr, stdout from os import get_terminal_size + def log_message(message="", show=True, err=False, recur=False, prefix=True): if not show: return @@ -18,7 +20,8 @@ def log_message(message="", show=True, err=False, recur=False, prefix=True): message = ' '.join(["[SSTV]", message]) print(message, file=out, end=end) - + + def progress_bar(progress, complete, message="", show=True): if not show: return @@ -38,8 +41,8 @@ def progress_bar(progress, complete, message="", show=True): percent = "" if percent_on: percent = "{:4.0f}%".format(level * 100) - - align_size = cols - len(message) - len(percent) + + align = cols - len(message) - len(percent) not_end = not progress == complete - log_message("{}{:>{width}}{}".format(message, bar, percent, - width=align_size), recur=not_end, prefix=False) + log_message("{}{:>{width}}{}".format(message, bar, percent, width=align), + recur=not_end, prefix=False) diff --git a/sstv/decode.py b/sstv/decode.py index fb05104..12a659f 100644 --- a/sstv/decode.py +++ b/sstv/decode.py @@ -1,7 +1,8 @@ #!usr/bin/env python + from . import spec from .common import log_message, progress_bar -from PIL import Image, ImageDraw +from PIL import Image from scipy.signal.windows import hann import soundfile import numpy as np @@ -12,7 +13,7 @@ class SSTVDecoder(object): def __init__(self, audio_file): """ Initialise SSTV decoder - + audio_data - Can be a path to an audio file OR a tuple containing samples and the sampling rate of audio data """ @@ -39,7 +40,7 @@ class SSTVDecoder(object): def decode(self, skip=0): """ Attempts to decode the audio data as an SSTV signal - + Returns a PIL image on success, and None on error """ @@ -61,7 +62,7 @@ class SSTVDecoder(object): return None return self._draw_image(image_data) - + def close(self): """ Closes any input files if they exist """ if self._audio_file is not None and not self._audio_file.closed: @@ -149,7 +150,8 @@ class SSTVDecoder(object): for bit_idx in range(8): bit_offset = bit_idx * bit_size - freq = self._peak_fft_freq(vis_section[bit_offset:bit_offset+bit_size]) + section = vis_section[bit_offset:bit_offset+bit_size] + freq = self._peak_fft_freq(section) vis_bits.append(int(freq <= 1200)) # check for even parity in last bit @@ -182,14 +184,6 @@ class SSTVDecoder(object): else: return lum - #def _yuv_to_rgb(y, ry, by): - # red = 0.003906 * ((298.082 * (y - 16.0)) + (408.583 * (ry - 128.0))) - # green = 0.003906 * ((298.082 * (y - 16.0)) + (-100.291 * (by - 128.0)) \ - # + (-208.12 * (ry - 128.0))) - # blue = 0.003906 * ((298.082 * (y - 16.0)) + (516.411 * (by - 128.0))) - # rgb = round(red), round(green), round(blue) - # return rgb - def _align_sync(self, align_section, start_of_sync=True): # Returns sample where the beginning of the sync pulse was found sync_window = round(self.mode.SYNC_PULSE * 1.4 * self._sample_rate) @@ -197,7 +191,8 @@ class SSTVDecoder(object): current_sample = 0 while current_sample < search_end: - freq = self._peak_fft_freq(align_section[current_sample:current_sample+sync_window]) + section = align_section[current_sample:current_sample+sync_window] + freq = self._peak_fft_freq(section) if freq > 1350: break current_sample += 1 @@ -219,7 +214,8 @@ class SSTVDecoder(object): if self.mode == spec.R36: window_factor = 7.83 - pixel_window = round(self.mode.PIXEL_TIME * window_factor * self._sample_rate) + pixel_window = round(self.mode.PIXEL_TIME * window_factor * + self._sample_rate) centre_window_time = (self.mode.PIXEL_TIME * window_factor) / 2 image_data = [] @@ -234,16 +230,18 @@ class SSTVDecoder(object): image_data.append([]) if self.mode.CHAN_SYNC > 0 and line == 0: - # align seq_start to the beginning of the sync pulse in the past - seq_start -= round((self.mode.CHAN_OFFSETS[self.mode.CHAN_SYNC] \ - + self.mode.SCAN_TIME) * self._sample_rate) + # align seq_start to the beginning of the previous sync pulse + sync_offset = self.mode.CHAN_OFFSETS[self.mode.CHAN_SYNC] + seq_start -= round((sync_offset + self.mode.SCAN_TIME) + * self._sample_rate) for chan in range(self.mode.CHAN_COUNT): image_data[line].append([]) if chan == self.mode.CHAN_SYNC: if line > 0 or chan > 0: - seq_start += round(self.mode.LINE_TIME * self._sample_rate) + seq_start += round(self.mode.LINE_TIME * + self._sample_rate) # align to start of sync pulse seq_start += self._align_sync(transmission[seq_start:]) @@ -253,20 +251,22 @@ class SSTVDecoder(object): if chan % 2 == 1: pixel_time = self.mode.MERGE_PIXEL_TIME - pixel_window = round(pixel_time * window_factor * self._sample_rate) + pixel_window = round(pixel_time * window_factor * + self._sample_rate) centre_window_time = (pixel_time * window_factor) / 2 for px in range(self.mode.LINE_WIDTH): chan_offset = self.mode.CHAN_OFFSETS[chan] - px_sample = round(seq_start + (chan_offset + px * pixel_time \ - - centre_window_time) * self._sample_rate) - freq = self._peak_fft_freq(transmission[px_sample:px_sample+pixel_window]) + px_sample = round(seq_start + (chan_offset + px * + pixel_time - centre_window_time) * + self._sample_rate) + section = transmission[px_sample:px_sample+pixel_window] + freq = self._peak_fft_freq(section) image_data[line][chan].append(SSTVDecoder._calc_lum(freq)) - progress_bar(line, self.mode.LINE_COUNT - 1, "Decoding image... ", self.log_basic) @@ -281,7 +281,8 @@ class SSTVDecoder(object): else: col_mode = "RGB" - image = Image.new(col_mode, (self.mode.LINE_WIDTH, self.mode.LINE_COUNT)) + image = Image.new(col_mode, + (self.mode.LINE_WIDTH, self.mode.LINE_COUNT)) pixel_data = image.load() for y in range(self.mode.LINE_COUNT): @@ -290,12 +291,17 @@ class SSTVDecoder(object): for x in range(self.mode.LINE_WIDTH): if self.mode.COLOR == spec.COL_FMT.GBR: - pixel = image_data[y][2][x], image_data[y][0][x], image_data[y][1][x] + pixel = (image_data[y][2][x], + image_data[y][0][x], + image_data[y][1][x]) elif self.mode.COLOR == spec.COL_FMT.YUV: - pixel = (image_data[y][0][x], image_data[y-ryby][1][x], - image_data[y-(ryby-1)][1][x]) + pixel = (image_data[y][0][x], + image_data[y-ryby][1][x], + image_data[y-(ryby-1)][1][x]) else: - pixel = image_data[y][0][x], image_data[y][1][x], image_data[y][2][x] + pixel = (image_data[y][0][x], + image_data[y][1][x], + image_data[y][2][x]) pixel_data[x, y] = pixel if self.mode.COLOR == spec.COL_FMT.YUV: diff --git a/sstv/spec.py b/sstv/spec.py index cd1678e..0bd0efc 100644 --- a/sstv/spec.py +++ b/sstv/spec.py @@ -1,4 +1,5 @@ #!usr/bin/env python + from enum import Enum BREAK_OFFSET = 0.300 @@ -10,17 +11,20 @@ HDR_WINDOW_SIZE = 0.010 VIS_BIT_SIZE = 0.030 + class COL_FMT(Enum): RGB = 1 GBR = 2 YUV = 3 BW = 4 + class SSTV(object): HAS_START_SYNC = False HAS_MERGE_SCAN = False CHAN_SYNC = 0 + class M1(SSTV): NAME = "Martin 1" VIS_CODE = 44 @@ -35,7 +39,6 @@ class M1(SSTV): CHAN_COUNT = 3 CHAN_TIME = SEP_PULSE + SCAN_TIME - # CHAN_OFFSETS = [SYNC_PULSE + SYNC_PORCH + c * CHAN_TIME for c in range(CHAN_COUNT)] CHAN_OFFSETS = [SYNC_PULSE + SYNC_PORCH] CHAN_OFFSETS.append(CHAN_OFFSETS[0] + CHAN_TIME) CHAN_OFFSETS.append(CHAN_OFFSETS[1] + CHAN_TIME)