def main(): # Get directory of this file directory = os.path.dirname(os.path.realpath(__file__)) # The name of the file to use for the test filename = 'lena.jpg' # Open the image convert it to RGB and get the height and width image = Image.open(os.path.join(directory, filename)).convert("RGB") image_width = image.size[0] image_height = image.size[1] # The canvas should be able to contain both the image and the decoding # state. Note the decoding state is the same width as the image height. canvas_width = image_width + image_height # Create the canvas canvas = kodo_helpers.CanvasScreenEngine(width=canvas_width, height=image_height) # Create the image viewer image_viewer = kodo_helpers.ImageViewer(width=image_width, height=image_height, canvas=canvas) # Create the decoding coefficient viewer state_viewer = kodo_helpers.DecodeStateViewer(size=image_height, canvas=canvas, canvas_position=(image_width, 0)) # Pick a symbol size (image_width * 3 will create a packet for each # horizontal line of the image) symbol_size = image_width * 3 # Based on the size of the image and the symbol size, calculate the number # of symbols needed for containing the image in a single generation. symbols = int(math.ceil(image_width * image_height * 3.0 / symbol_size)) # Create encoder factory and encoder encoder_factory = kodo.FullVectorEncoderFactoryBinary8( max_symbols=symbols, max_symbol_size=symbol_size) encoder = encoder_factory.build() # Create decoder factory and decoder decoder_factory = kodo.FullVectorDecoderFactoryBinary8Trace( max_symbols=symbols, max_symbol_size=symbol_size) decoder = decoder_factory.build() # Connect the tracing callback to the decode state viewer def callback(zone, msg): state_viewer.trace_callback(zone, msg) decoder.trace(callback) # Create a byte array from the image to use in the encoding data_in = image.tobytes() # Set the converted image data encoder.set_symbols(data_in) # Create an image viwer and run the following code in a try catch; # this prevents the program from locking up, as the finally clause will # close down the image viewer. canvas.start() try: packets = 0 while not decoder.is_complete(): packet = encoder.encode() packets += 1 # Drop some packets if random.choice([True, False]): decoder.decode(packet) image_viewer.set_image(decoder.copy_symbols()) # Let the user see the photo before closing the application time.sleep(1) finally: canvas.stop() # The decoder is complete, now copy the symbols from the decoder data_out = decoder.copy_symbols() # Check we properly decoded the data if data_out[:len(data_in)] == data_in: print("Data decoded correctly") else: print("Unexpected failure to decode please file a bug report :)") sys.exit(1)
def main(): # Get directory of this file directory = os.path.dirname(os.path.realpath(__file__)) # The name of the file to use for the test filename = 'lena.jpg' # Open the image convert it to RGB and get the height and width image = Image.open(os.path.join(directory, filename)).convert("RGB") image_width = image.size[0] image_height = image.size[1] # The canvas should be able to contain both the image and the decoding # state. Note the decoding state is the same width as the image height. canvas_width = image_height + image_width + image_height # Create the canvas canvas = kodo_helpers.CanvasScreenEngine(width=canvas_width, height=image_height) # Create the decoding coefficient viewer encoding_state_viewer = kodo_helpers.EncodeStateViewer(size=image_height, canvas=canvas) # Create the image viewer image_viewer = kodo_helpers.ImageViewer(width=image_width, height=image_height, canvas=canvas, canvas_position=(image_width, 0)) # Create the decoding coefficient viewer decoding_state_viewer = kodo_helpers.DecodeStateViewer( size=image_height, canvas=canvas, canvas_position=(image_width * 2, 0)) # Pick a symbol size (image_width * 3 will create a packet for each # horizontal line of the image, that is three bytes per pixel (RGB)) symbol_size = image_width * 3 # Based on the size of the image and the symbol size, calculate the number # of symbols needed for containing the image in a single generation. symbols = int(math.ceil(image_width * image_height * 3.0 / symbol_size)) field = kodo.field.binary8 encoder_factory = kodo.RLNCEncoderFactory(field, symbols, symbol_size) encoder = encoder_factory.build() decoder_factory = kodo.RLNCDecoderFactory(field, symbols, symbol_size) decoder = decoder_factory.build() # Connect the tracing callback to the decode state viewer def encoding_callback(zone, msg): encoding_state_viewer.trace_callback(zone, msg) encoding_state_viewer.set_symbols(encoder.symbols()) encoder.set_trace_callback(encoding_callback) def decoding_callback(zone, msg): decoding_state_viewer.trace_callback(zone, msg) decoder.set_trace_callback(decoding_callback) # Create a bytearray from the image to use in the encoding (only pick the # data we have room for). data_in = bytearray(image.tobytes()[-encoder.block_size():]) # Set the converted image data encoder.set_const_symbols(data_in) # Define the data_out bytearray where the symbols should be decoded # This bytearray must not go out of scope while the encoder exists! data_out = bytearray(decoder.block_size()) decoder.set_mutable_symbols(data_out) # Create an image viwer and run the following code in a try catch; # this prevents the program from locking up, as the finally clause will # close down the image viewer. canvas.start() try: while not decoder.is_complete(): packet = encoder.write_payload() # Drop some packets if random.choice([True, False]): decoder.read_payload(packet) # The data_out buffer is continuously updated image_viewer.set_image(data_out) # Let the user see the complete photo before closing the application for i in range(100): image_viewer.set_image(data_out) finally: canvas.stop() # Check we properly decoded the data if data_out[:len(data_in)] == data_in: print("Data decoded correctly") else: print("Unexpected failure to decode please file a bug report :)") sys.exit(1)
def main(): # Setup canvas and viewer size = 512 canvas = kodo_helpers.CanvasScreenEngine(size * 2, size) encoder_viewer = kodo_helpers.EncodeStateViewer( size=size, canvas=canvas) decoder_viewer = kodo_helpers.DecodeStateViewer( size=size, canvas=canvas, canvas_position=(size, 0)) canvas.start() try: field = kodo.field.binary8 symbols = 64 symbol_size = 16 encoder_factory = kodo.RLNCEncoderFactory(field, symbols, symbol_size) encoder = encoder_factory.build() decoder_factory = kodo.RLNCDecoderFactory(field, symbols, symbol_size) decoder = decoder_factory.build() data_in = bytearray(os.urandom(encoder.block_size())) encoder.set_const_symbols(data_in) data_out = bytearray(decoder.block_size()) decoder.set_mutable_symbols(data_out) def decoder_callback(zone, msg): decoder_viewer.trace_callback(zone, msg) decoder.set_trace_callback(decoder_callback) def encoder_callback(zone, msg): encoder_viewer.trace_callback(zone, msg) encoder_viewer.set_symbols(encoder.symbols()) encoder.set_trace_callback(encoder_callback) while not decoder.is_complete(): # Encode a packet into the payload buffer packet = encoder.write_payload() # Here we "simulate" a packet loss of approximately 50% # by dropping half of the encoded packets. # When running this example you will notice that the initial # symbols are received systematically (i.e. uncoded). After # sending all symbols once uncoded, the encoder will switch # to full coding, in which case you will see the full encoding # vectors being sent and received. if random.choice([True, False]): continue # Pass that packet to the decoder decoder.read_payload(packet) time.sleep(1) finally: # What ever happens, make sure we stop the viewer. canvas.stop() # Check we properly decoded the data if data_out == data_in: print("Data decoded correctly") else: print("Unexpected failure to decode please file a bug report :)") sys.exit(1)
def main(): # Setup canvas and viewer size = 512 canvas = kodo_helpers.CanvasScreenEngine(size * 2, size) encoder_viewer = kodo_helpers.EncodeStateViewer(size=size, canvas=canvas) decoder_viewer = kodo_helpers.DecodeStateViewer(size=size, canvas=canvas, canvas_position=(size, 0)) canvas.start() try: # Set the number of symbols (i.e. the generation size in RLNC # terminology) and the size of a symbol in bytes symbols = 64 symbol_size = 16 # In the following we will make an encoder/decoder factory. # The factories are used to build actual encoders/decoders encoder_factory = kodo.FullVectorEncoderFactoryBinary8( max_symbols=symbols, max_symbol_size=symbol_size) encoder = encoder_factory.build() decoder_factory = kodo.FullVectorDecoderFactoryBinary8( max_symbols=symbols, max_symbol_size=symbol_size) decoder = decoder_factory.build() # Create some data to encode. In this case we make a buffer # with the same size as the encoder's block size (the max. # amount a single encoder can encode) # Just for fun - fill the input data with random data data_in = os.urandom(encoder.block_size()) def decoder_callback(zone, msg): decoder_viewer.trace_callback(zone, msg) decoder.set_trace_callback(decoder_callback) def encoder_callback(zone, msg): encoder_viewer.trace_callback(zone, msg) encoder.set_trace_callback(encoder_callback) # Assign the data buffer to the encoder so that we may start # to produce encoded symbols from it encoder.set_const_symbols(data_in) while not decoder.is_complete(): # Encode a packet into the payload buffer packet = encoder.write_payload() # Here we "simulate" a packet loss of approximately 50% # by dropping half of the encoded packets. # When running this example you will notice that the initial # symbols are received systematically (i.e. uncoded). After # sending all symbols once uncoded, the encoder will switch # to full coding, in which case you will see the full encoding # vectors being sent and received. if random.choice([True, False]): continue # Pass that packet to the decoder decoder.read_payload(packet) time.sleep(1) finally: # What ever happens, make sure we stop the viewer. canvas.stop() # The decoder is complete, now copy the symbols from the decoder data_out = decoder.copy_from_symbols() # Check we properly decoded the data if data_out == data_in: print("Data decoded correctly") else: print("Unexpected failure to decode please file a bug report :)") sys.exit(1)