Assignment Chef icon Assignment Chef
All English tutorials

Programming lesson

Mastering Run-Length Encoding in Python: A Step-by-Step Guide for Image Data Compression

Learn how to implement run-length encoding (RLE) in Python for image data compression. This tutorial covers encoding, decoding, string conversion, and more, with practical examples and a menu-driven program.

run-length encoding Python RLE image compression Python Python image encoding tutorial COP3502C homework help RLE encoding decoding Python Python data compression project pixel art compression Python lossless compression Python Python list manipulation hexadecimal conversion Python Python menu-driven program RLE string conversion Python functions for RLE image data processing Python game development compression Python coding assignment help

Introduction to Run-Length Encoding

Run-length encoding (RLE) is a simple form of lossless data compression where runs of consecutive identical data elements are stored as a single value and a count. It is widely used in image compression, especially for pixel art, icons, and simple graphics. For example, in the classic game Minecraft, terrain textures often have long runs of the same color, making RLE an efficient choice.

Understanding the Assignment

In this project, you will develop Python functions to encode and decode image data using RLE. The image data is represented as a list of integers (0-15 for colors), with the first two numbers being width and height. You will implement methods for converting between raw data, RLE data, and human-readable strings. This tutorial will guide you through each method step-by-step.

Prerequisites

  • Basic knowledge of Python loops, lists, and string manipulation
  • Understanding of hexadecimal and decimal number systems
  • Familiarity with functions and type casting

Key Methods Explained

1. to_hex_string(data)

This function converts a list of integers (each 0-15) into a hexadecimal string without delimiters. For example, [3, 15, 6, 4] becomes "3f64".

def to_hex_string(data):
    return ''.join(f'{x:x}' for x in data)

2. count_runs(flat_data)

Returns the number of runs in the raw data. For [15,15,15,4,4,4,4,4,4], there are two runs: three 15s and six 4s, so output is 2.

def count_runs(flat_data):
    if not flat_data:
        return 0
    runs = 1
    for i in range(1, len(flat_data)):
        if flat_data[i] != flat_data[i-1]:
            runs += 1
    return runs

3. encode_rle(flat_data)

Encodes raw data into RLE format: a list where each pair is [count, value]. For [15,15,15,4,4,4,4,4,4], output is [3,15,6,4].

def encode_rle(flat_data):
    if not flat_data:
        return []
    encoded = []
    count = 1
    for i in range(1, len(flat_data)):
        if flat_data[i] == flat_data[i-1]:
            count += 1
        else:
            encoded.extend([count, flat_data[i-1]])
            count = 1
    encoded.extend([count, flat_data[-1]])
    return encoded

4. get_decoded_length(rle_data)

Given RLE data (e.g., [3,15,6,4]), returns the length of the decoded flat data: 3+6=9.

def get_decoded_length(rle_data):
    return sum(rle_data[i] for i in range(0, len(rle_data), 2))

5. decode_rle(rle_data)

Decodes RLE data back into flat data. For [3,15,6,4], output is [15,15,15,4,4,4,4,4,4].

def decode_rle(rle_data):
    decoded = []
    for i in range(0, len(rle_data), 2):
        count = rle_data[i]
        value = rle_data[i+1]
        decoded.extend([value] * count)
    return decoded

6. string_to_data(data_string)

Converts a hexadecimal string (e.g., "3f64") into a list of integers: [3,15,6,4].

def string_to_data(data_string):
    return [int(ch, 16) for ch in data_string]

7. to_rle_string(rle_data)

Converts RLE data into a human-readable string with decimal lengths and hex values separated by colons. For [15,15,6,4], output "15f:64".

def to_rle_string(rle_data):
    parts = []
    for i in range(0, len(rle_data), 2):
        length = rle_data[i]
        value = rle_data[i+1]
        parts.append(f'{length}{value:x}')
    return ':'.join(parts)

8. string_to_rle(rle_string)

Inverse of to_rle_string. For "15f:64", returns [15,15,6,4].

def string_to_rle(rle_string):
    rle_data = []
    for part in rle_string.split(':'):
        length = int(part[:-1])
        value = int(part[-1], 16)
        rle_data.extend([length, value])
    return rle_data

Building the Menu-Driven Program

Your program must present a menu with options to load data (from file, test image, RLE string, RLE hex string, flat hex string) and display data (image, RLE string, RLE hex, flat hex). Below is a sample implementation.

def main():
    image_data = None
    while True:
        print("\nMenu:")
        print("1. Load file")
        print("2. Load test image")
        print("3. Read RLE string")
        print("4. Read RLE hex string")
        print("5. Read flat hex string")
        print("6. Display image")
        print("7. Display RLE string")
        print("8. Display RLE hex")
        print("9. Display flat hex")
        print("0. Exit")
        choice = input("Select a menu option: ")
        if choice == '1':
            filename = input("Enter name of file to load: ")
            # Assume ConsoleGfx.load_file exists
            image_data = ConsoleGfx.load_file(filename)
        elif choice == '2':
            image_data = ConsoleGfx.test_image
            print("Test image data loaded.")
        elif choice == '3':
            rle_string = input("Enter an RLE string to be decoded: ")
            rle_data = string_to_rle(rle_string)
            image_data = decode_rle(rle_data)
        elif choice == '4':
            hex_string = input("Enter the hex string holding RLE data: ")
            rle_data = string_to_data(hex_string)
            image_data = decode_rle(rle_data)
        elif choice == '5':
            hex_string = input("Enter the hex string holding flat data: ")
            image_data = string_to_data(hex_string)
        elif choice == '6':
            if image_data:
                ConsoleGfx.display_image(image_data)
            else:
                print("No image data loaded.")
        elif choice == '7':
            if image_data:
                rle_data = encode_rle(image_data)
                print("RLE representation:", to_rle_string(rle_data))
            else:
                print("No image data loaded.")
        elif choice == '8':
            if image_data:
                rle_data = encode_rle(image_data)
                print("RLE hex values:", to_hex_string(rle_data))
            else:
                print("No image data loaded.")
        elif choice == '9':
            if image_data:
                print("Flat hex values:", to_hex_string(image_data))
            else:
                print("No image data loaded.")
        elif choice == '0':
            break
        else:
            print("Invalid option.")

if __name__ == "__main__":
    main()

Real-World Applications and Trends

RLE is not just for school projects. It's used in image compression for web graphics, fax machines, and even video game sprite storage. For instance, the popular game Stardew Valley uses RLE to compress its pixel art tilesets. In 2026, with the rise of AI-generated pixel art and retro-style indie games, understanding RLE can give you an edge in game development and data compression fields.

Tips for Success

  • Test each function individually with small examples before integrating.
  • Pay attention to data types: lengths are decimal, values are hexadecimal.
  • Ensure your output matches the expected format exactly for full credit.
  • Use the ConsoleGfx class provided to display images correctly.

Conclusion

By completing this assignment, you'll gain hands-on experience with loops, lists, string manipulation, and type casting in Python. RLE is a fundamental compression technique that appears in many real-world applications. Master it now, and you'll be ready for more advanced topics like Huffman coding or LZW compression.