Programming lesson
Run-Length Encoding for Images in Python: A Step-by-Step Guide
Learn how to implement run-length encoding (RLE) for image data in Python. This tutorial covers encoding, decoding, hex conversion, and string handling with practical examples and a menu-driven program.
Introduction to Run-Length Encoding (RLE)
Run-length encoding is a simple form of lossless compression that replaces consecutive repeated values with a count and the value. It's widely used in image compression, especially for pixel art and simple graphics. In this tutorial, you'll build Python functions to encode and decode image data using RLE, similar to what you'd do in assignments like COP3502C HW 3 and 4.
Why RLE Matters Today
From retro gaming sprites to modern AI-generated pixel art, RLE remains relevant. For example, game developers use RLE to compress tile maps in 2D games like Stardew Valley or Minecraft texture packs. Even in machine learning, RLE is used to encode segmentation masks. Understanding RLE gives you a foundation in data compression and algorithm design.
Core RLE Functions
We'll implement eight essential methods. Each one builds on the previous, so follow the order carefully.
1. to_hex_string(data)
Converts a list of integers (0-15) into a hexadecimal string. Each integer becomes a single hex digit. Example: [3, 15, 6, 4] becomes "3f64".
def to_hex_string(data):
return ''.join(format(n, 'x') for n in data)2. count_runs(flat_data)
Counts how many runs (consecutive equal values) exist in the flat data. For [15,15,15,4,4,4,4,4,4], there are 2 runs.
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 runs3. encode_rle(flat_data)
Encodes flat data into RLE format: a list where each pair is [count, value]. [15,15,15,4,4,4,4,4,4] becomes [3,15,6,4].
def encode_rle(flat_data):
if not flat_data:
return []
rle = []
count = 1
for i in range(1, len(flat_data)):
if flat_data[i] == flat_data[i-1]:
count += 1
else:
rle.extend([count, flat_data[i-1]])
count = 1
rle.extend([count, flat_data[-1]])
return rle4. get_decoded_length(rle_data)
Given RLE data, returns the total number of pixels after decoding. For [3,15,6,4], output is 9.
def get_decoded_length(rle_data):
return sum(rle_data[::2])5. decode_rle(rle_data)
Decodes RLE back to flat data. Inverse of encode_rle.
def decode_rle(rle_data):
flat = []
for i in range(0, len(rle_data), 2):
count = rle_data[i]
value = rle_data[i+1]
flat.extend([value] * count)
return flat6. string_to_data(data_string)
Converts a hex string (e.g., "3f64") back to a list of integers.
def string_to_data(data_string):
return [int(ch, 16) for ch in data_string]7. to_rle_string(rle_data)
Converts RLE list to a human-readable string with colons. Example: [15,15,6,4] gives "15f:64".
def to_rle_string(rle_data):
parts = []
for i in range(0, len(rle_data), 2):
count = rle_data[i]
value = rle_data[i+1]
parts.append(f"{count}{format(value, 'x')}")
return ':'.join(parts)8. string_to_rle(rle_string)
Inverse of to_rle_string. Parses "15f:64" into [15,15,6,4].
def string_to_rle(rle_string):
rle = []
for part in rle_string.split(':'):
count = int(part[:-1])
value = int(part[-1], 16)
rle.extend([count, value])
return rleBuilding the Interactive Menu
Your program should present a menu with options to load and display data. We'll use a ConsoleGfx class (provided by your instructor) for file I/O and image display. Below is a skeleton for the menu loop.
def main():
image_data = None
print("Welcome to RLE Image Processor!")
ConsoleGfx.test_rainbow()
while True:
print_menu()
choice = input("Select a Menu Option: ")
if choice == '1':
filename = input("Enter name of file to load: ")
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)
elif choice == '7':
if image_data:
rle_data = encode_rle(image_data)
print("RLE representation:", to_rle_string(rle_data))
elif choice == '8':
if image_data:
rle_data = encode_rle(image_data)
print("RLE hex values:", to_hex_string(rle_data))
elif choice == '9':
if image_data:
print("Flat hex values:", to_hex_string(image_data))
elif choice == '0':
break
def print_menu():
print("\nRLE Menu")
print("--------")
print("1. Load a 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 values")
print("9. Display flat hex values")
print("0. Exit")
if __name__ == "__main__":
main()Testing Your Implementation
Test with the smiley face example: flat hex 880bbbbbb0bbbbbbbbbb0bb0bbbbbbbbbbbb0bb0bbbbb00bbbbbbbbbbb0bbbbbb0. Load it as flat data (option 5), then display RLE string (option 7) and compare with expected output 28:10:6b:10:10b:10:2b:10:12b:10:2b:10:5b:20:11b:10:6b:10.
Real-World Applications and Trends
RLE isn't just for homework. In 2026, indie game development is booming, and tools like Aseprite use RLE for sprite compression. AI image generators often produce pixel art that can be efficiently stored with RLE. Even in finance, RLE is used to compress time-series data with repeating patterns. Mastering RLE gives you a skill used in data science, game dev, and system programming.
Common Pitfalls and Tips
- Off-by-one errors: Ensure your loops correctly handle the last element.
- Hex case: Use lowercase hex digits to match expected output.
- Delimiters: In
to_rle_string, no colon after the last run. - Data validation: Assume input is well-formed for this assignment, but in real code, add error handling.
Conclusion
You've now built a complete RLE image compression tool in Python. This project reinforces loops, lists, string manipulation, and modular programming. Whether you're compressing game sprites or preparing for a coding interview, RLE is a fundamental algorithm worth knowing. Happy coding!