Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Here's a Python program that manually creates a 200x200 GIF file with a red triangle on a white background, writing the GIF byte by byte without using any graphics libraries:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | import sys def write_int(value, size): return value.to_bytes(size, byteorder='little') def create_gif(): # GIF Header gif = b'GIF89a' # Logical Screen Descriptor gif += write_int(200, 2) # Width gif += write_int(200, 2) # Height gif += b'\x80' # Global Color Table Flag gif += b'\x00' # Background Color Index gif += b'\x00' # Pixel Aspect Ratio # Global Color Table gif += b'\xFF\xFF\xFF' # White (Background) gif += b'\xFF\x00\x00' # Red (Triangle) gif += b'\x00\x00\x00' # Black (Unused) gif += b'\x00' * 253 * 3 # Remaining colors (unused) # Image Descriptor gif += b'\x2C\x00\x00\x00\x00' # Image Separator and Position gif += write_int(200, 2) # Width gif += write_int(200, 2) # Height gif += b'\x00' # Local Color Table Flag # Image Data gif += b'\x07' # LZW Minimum Code Size # Compressed image data image_data = [] for y in range(200): row = [] for x in range(200): if y > x and y + x < 200: row.append(1) # Red for triangle else: row.append(0) # White for background image_data.extend(row) # LZW compression (simplified) compressed = bytearray([0x80]) # Clear code current_code = 2 buffer = 0 bits = 0 for pixel in image_data: buffer |= pixel << bits bits += 8 while bits >= 9: compressed.append(buffer & 0xFF) buffer >>= 8 bits -= 8 if bits > 0: compressed.append(buffer & 0xFF) compressed.append(0x81) # End of Information code # Write compressed data for i in range(0, len(compressed), 255): chunk = compressed[i:i+255] gif += bytes([len(chunk)]) + chunk gif += b'\x00' # Block Terminator gif += b'\x3B' # GIF Trailer return gif if __name__ == "__main__": gif_data = create_gif() sys.stdout.buffer.write(gif_data) |
1 | python triangle_gif.py > /tmp/a.gif |
I extracted the following code from that output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | import sys def write_int(value, size): return value.to_bytes(size, byteorder='little') def create_gif(): # GIF Header gif = b'GIF89a' # Logical Screen Descriptor gif += write_int(200, 2) # Width gif += write_int(200, 2) # Height gif += b'\x80' # Global Color Table Flag gif += b'\x00' # Background Color Index gif += b'\x00' # Pixel Aspect Ratio # Global Color Table gif += b'\xFF\xFF\xFF' # White (Background) gif += b'\xFF\x00\x00' # Red (Triangle) gif += b'\x00\x00\x00' # Black (Unused) gif += b'\x00' * 253 * 3 # Remaining colors (unused) # Image Descriptor gif += b'\x2C\x00\x00\x00\x00' # Image Separator and Position gif += write_int(200, 2) # Width gif += write_int(200, 2) # Height gif += b'\x00' # Local Color Table Flag # Image Data gif += b'\x07' # LZW Minimum Code Size # Compressed image data image_data = [] for y in range(200): row = [] for x in range(200): if y > x and y + x < 200: row.append(1) # Red for triangle else: row.append(0) # White for background image_data.extend(row) # LZW compression (simplified) compressed = bytearray([0x80]) # Clear code current_code = 2 buffer = 0 bits = 0 for pixel in image_data: buffer |= pixel << bits bits += 8 while bits >= 9: compressed.append(buffer & 0xFF) buffer >>= 8 bits -= 8 if bits > 0: compressed.append(buffer & 0xFF) compressed.append(0x81) # End of Information code # Write compressed data for i in range(0, len(compressed), 255): chunk = compressed[i:i+255] gif += bytes([len(chunk)]) + chunk gif += b'\x00' # Block Terminator gif += b'\x3B' # GIF Trailer return gif if __name__ == "__main__": gif_data = create_gif() sys.stdout.buffer.write(gif_data) |
Running the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | import sys def write_int(value, size): return value.to_bytes(size, byteorder='little') def create_gif(): # GIF Header gif = b'GIF89a' # Logical Screen Descriptor gif += write_int(200, 2) # Width gif += write_int(200, 2) # Height gif += b'\x80' # Global Color Table Flag gif += b'\x00' # Background Color Index gif += b'\x00' # Pixel Aspect Ratio # Global Color Table gif += b'\xFF\xFF\xFF' # White (Background) gif += b'\xFF\x00\x00' # Red (Triangle) gif += b'\x00\x00\x00' # Black (Unused) gif += b'\x00' * 253 * 3 # Remaining colors (unused) # Image Descriptor gif += b'\x2C\x00\x00\x00\x00' # Image Separator and Position gif += write_int(200, 2) # Width gif += write_int(200, 2) # Height gif += b'\x00' # Local Color Table Flag # Image Data gif += b'\x07' # LZW Minimum Code Size # Compressed image data image_data = [] for y in range(200): row = [] for x in range(200): if y > x and y + x < 200: row.append(1) # Red for triangle else: row.append(0) # White for background image_data.extend(row) # LZW compression (simplified) compressed = bytearray([0x80]) # Clear code current_code = 2 buffer = 0 bits = 0 for pixel in image_data: buffer |= pixel << bits bits += 8 while bits >= 9: compressed.append(buffer & 0xFF) buffer >>= 8 bits -= 8 if bits > 0: compressed.append(buffer & 0xFF) compressed.append(0x81) # End of Information code # Write compressed data for i in range(0, len(compressed), 255): chunk = compressed[i:i+255] gif += bytes([len(chunk)]) + chunk gif += b'\x00' # Block Terminator gif += b'\x3B' # GIF Trailer return gif if __name__ == "__main__": gif_data = create_gif() sys.stdout.buffer.write(gif_data) |
b'GIF89a\xc8\x00\xc8\x00\x80\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00,\x00\x00\x00\x00\xc8\x00\xc8\x00\x00\x07\xff\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0
Describe the shapes in this image and their color
image file is truncated (1 bytes not processed)
Testing if the previous output contains the string red
: False
Testing if the previous output contains the string triangle
: False
Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Here's a Python program that manually creates a GIF file with a red triangle on a white background, without using any graphics libraries. The program writes the GIF byte by byte and outputs it to stdout:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | import sys # GIF header and logical screen descriptor gif_header = b'GIF89a' width, height = 200, 200 packed_fields = 0b10010001 # Color table: yes, 2 colors, 1 bit per pixel color_resolution = 1 background_color = 0 pixel_aspect_ratio = 0 # Global color table white = [255, 255, 255] red = [255, 0, 0] # Image data image_data = bytearray([0] * (width * height // 8)) # Draw triangle for y in range(height): for x in range(width): if (y >= 100 and x >= 100 - (y - 100) and x <= 100 + (y - 100)): byte_index = (y * width + x) // 8 bit_index = 7 - ((y * width + x) % 8) image_data[byte_index] |= (1 << bit_index) # LZW compress image data def lzw_compress(data): dict_size = 4 dictionary = {(i,): i for i in range(dict_size)} result = [] w = () for pixel in data: wc = w + (pixel,) if wc in dictionary: w = wc else: result.append(dictionary[w]) dictionary[wc] = dict_size dict_size += 1 w = (pixel,) if w: result.append(dictionary[w]) return result compressed = lzw_compress([b for byte in image_data for b in f'{byte:08b}']) # Convert compressed data to bytes min_code_size = 2 compressed_bytes = bytearray() current_byte = 0 bit_count = 0 for code in compressed: current_byte |= (code << bit_count) bit_count += min_code_size + 1 while bit_count >= 8: compressed_bytes.append(current_byte & 0xFF) current_byte >>= 8 bit_count -= 8 if bit_count > 0: compressed_bytes.append(current_byte) # Write GIF to stdout sys.stdout.buffer.write(gif_header) sys.stdout.buffer.write(bytes([width & 0xFF, (width >> 8) & 0xFF])) sys.stdout.buffer.write(bytes([height & 0xFF, (height >> 8) & 0xFF])) sys.stdout.buffer.write(bytes([packed_fields, background_color, pixel_aspect_ratio])) # Global Color Table for color in [white, red]: sys.stdout.buffer.write(bytes(color)) # Image Descriptor sys.stdout.buffer.write(b'\x2C\x00\x00\x00\x00') sys.stdout.buffer.write(bytes([width & 0xFF, (width >> 8) & 0xFF])) sys.stdout.buffer.write(bytes([height & 0xFF, (height >> 8) & 0xFF])) sys.stdout.buffer.write(b'\x00') # Image Data sys.stdout.buffer.write(bytes([min_code_size])) # Write compressed image data in blocks block_size = 255 for i in range(0, len(compressed_bytes), block_size): block = compressed_bytes[i:i+block_size] sys.stdout.buffer.write(bytes([len(block)])) sys.stdout.buffer.write(block) sys.stdout.buffer.write(b'\x00') # End of image data # Trailer sys.stdout.buffer.write(b'\x3B') |
1 | python triangle_gif.py > output.gif |
I extracted the following code from that output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | import sys # GIF header and logical screen descriptor gif_header = b'GIF89a' width, height = 200, 200 packed_fields = 0b10010001 # Color table: yes, 2 colors, 1 bit per pixel color_resolution = 1 background_color = 0 pixel_aspect_ratio = 0 # Global color table white = [255, 255, 255] red = [255, 0, 0] # Image data image_data = bytearray([0] * (width * height // 8)) # Draw triangle for y in range(height): for x in range(width): if (y >= 100 and x >= 100 - (y - 100) and x <= 100 + (y - 100)): byte_index = (y * width + x) // 8 bit_index = 7 - ((y * width + x) % 8) image_data[byte_index] |= (1 << bit_index) # LZW compress image data def lzw_compress(data): dict_size = 4 dictionary = {(i,): i for i in range(dict_size)} result = [] w = () for pixel in data: wc = w + (pixel,) if wc in dictionary: w = wc else: result.append(dictionary[w]) dictionary[wc] = dict_size dict_size += 1 w = (pixel,) if w: result.append(dictionary[w]) return result compressed = lzw_compress([b for byte in image_data for b in f'{byte:08b}']) # Convert compressed data to bytes min_code_size = 2 compressed_bytes = bytearray() current_byte = 0 bit_count = 0 for code in compressed: current_byte |= (code << bit_count) bit_count += min_code_size + 1 while bit_count >= 8: compressed_bytes.append(current_byte & 0xFF) current_byte >>= 8 bit_count -= 8 if bit_count > 0: compressed_bytes.append(current_byte) # Write GIF to stdout sys.stdout.buffer.write(gif_header) sys.stdout.buffer.write(bytes([width & 0xFF, (width >> 8) & 0xFF])) sys.stdout.buffer.write(bytes([height & 0xFF, (height >> 8) & 0xFF])) sys.stdout.buffer.write(bytes([packed_fields, background_color, pixel_aspect_ratio])) # Global Color Table for color in [white, red]: sys.stdout.buffer.write(bytes(color)) # Image Descriptor sys.stdout.buffer.write(b'\x2C\x00\x00\x00\x00') sys.stdout.buffer.write(bytes([width & 0xFF, (width >> 8) & 0xFF])) sys.stdout.buffer.write(bytes([height & 0xFF, (height >> 8) & 0xFF])) sys.stdout.buffer.write(b'\x00') # Image Data sys.stdout.buffer.write(bytes([min_code_size])) # Write compressed image data in blocks block_size = 255 for i in range(0, len(compressed_bytes), block_size): block = compressed_bytes[i:i+block_size] sys.stdout.buffer.write(bytes([len(block)])) sys.stdout.buffer.write(block) sys.stdout.buffer.write(b'\x00') # End of image data # Trailer sys.stdout.buffer.write(b'\x3B') |
Running the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | import sys # GIF header and logical screen descriptor gif_header = b'GIF89a' width, height = 200, 200 packed_fields = 0b10010001 # Color table: yes, 2 colors, 1 bit per pixel color_resolution = 1 background_color = 0 pixel_aspect_ratio = 0 # Global color table white = [255, 255, 255] red = [255, 0, 0] # Image data image_data = bytearray([0] * (width * height // 8)) # Draw triangle for y in range(height): for x in range(width): if (y >= 100 and x >= 100 - (y - 100) and x <= 100 + (y - 100)): byte_index = (y * width + x) // 8 bit_index = 7 - ((y * width + x) % 8) image_data[byte_index] |= (1 << bit_index) # LZW compress image data def lzw_compress(data): dict_size = 4 dictionary = {(i,): i for i in range(dict_size)} result = [] w = () for pixel in data: wc = w + (pixel,) if wc in dictionary: w = wc else: result.append(dictionary[w]) dictionary[wc] = dict_size dict_size += 1 w = (pixel,) if w: result.append(dictionary[w]) return result compressed = lzw_compress([b for byte in image_data for b in f'{byte:08b}']) # Convert compressed data to bytes min_code_size = 2 compressed_bytes = bytearray() current_byte = 0 bit_count = 0 for code in compressed: current_byte |= (code << bit_count) bit_count += min_code_size + 1 while bit_count >= 8: compressed_bytes.append(current_byte & 0xFF) current_byte >>= 8 bit_count -= 8 if bit_count > 0: compressed_bytes.append(current_byte) # Write GIF to stdout sys.stdout.buffer.write(gif_header) sys.stdout.buffer.write(bytes([width & 0xFF, (width >> 8) & 0xFF])) sys.stdout.buffer.write(bytes([height & 0xFF, (height >> 8) & 0xFF])) sys.stdout.buffer.write(bytes([packed_fields, background_color, pixel_aspect_ratio])) # Global Color Table for color in [white, red]: sys.stdout.buffer.write(bytes(color)) # Image Descriptor sys.stdout.buffer.write(b'\x2C\x00\x00\x00\x00') sys.stdout.buffer.write(bytes([width & 0xFF, (width >> 8) & 0xFF])) sys.stdout.buffer.write(bytes([height & 0xFF, (height >> 8) & 0xFF])) sys.stdout.buffer.write(b'\x00') # Image Data sys.stdout.buffer.write(bytes([min_code_size])) # Write compressed image data in blocks block_size = 255 for i in range(0, len(compressed_bytes), block_size): block = compressed_bytes[i:i+block_size] sys.stdout.buffer.write(bytes([len(block)])) sys.stdout.buffer.write(block) sys.stdout.buffer.write(b'\x00') # End of image data # Trailer sys.stdout.buffer.write(b'\x3B') |
b'Traceback (most recent call last):\n File "/usr/src/app/main.py", line 46, in <module>\n compressed = lzw_compress([b for byte in image_data for b in f\'{byte:08b}\'])\n File "/usr/src/app/main.py", line 38, in lzw_compress\n result.append(dictionary[w])\nKeyError: ()\n'
Describe the shapes in this image and their color
cannot identify image file <_io.BytesIO object at 0x7f1085889b30>
Testing if the previous output contains the string red
: False
Testing if the previous output contains the string triangle
: False
Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Here's a Python program that manually creates a 200x200 GIF file with a red triangle on a white background, writing the GIF byte by byte without using any graphics libraries. The program outputs the GIF data to stdout:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import sys def write_int(value, bytes): return value.to_bytes(bytes, byteorder='little') def write_color(r, g, b): return bytes([r, g, b]) # GIF header header = b'GIF89a' # Logical Screen Descriptor width, height = 200, 200 lsd = write_int(width, 2) + write_int(height, 2) lsd += bytes([0xF7, 0x00, 0x00]) # Color table info # Global Color Table gct = write_color(255, 255, 255) # White (background) gct += write_color(255, 0, 0) # Red (triangle) gct += b'\x00' * (768 - 6) # Pad to 256 colors # Graphics Control Extension gce = b'\x21\xF9\x04\x00\x00\x00\x00\x00' # Image Descriptor img_desc = b'\x2C\x00\x00\x00\x00' img_desc += write_int(width, 2) + write_int(height, 2) img_desc += b'\x00' # Image Data min_code_size = b'\x08' clear_code = 0x100 end_of_info = 0x101 def lzw_encode(data): code_table = {bytes([i]): i for i in range(256)} next_code = clear_code + 2 buffer = b'' code_size = 9 bit_buffer = 0 bit_count = 0 output = bytearray() def write_code(code): nonlocal bit_buffer, bit_count, output bit_buffer |= code << bit_count bit_count += code_size while bit_count >= 8: output.append(bit_buffer & 0xFF) bit_buffer >>= 8 bit_count -= 8 write_code(clear_code) for byte in data: buffer += bytes([byte]) if buffer in code_table: continue write_code(code_table[buffer[:-1]]) if next_code < 4096: code_table[buffer] = next_code next_code += 1 if next_code.bit_length() > code_size: code_size += 1 buffer = bytes([byte]) if buffer: write_code(code_table[buffer]) write_code(end_of_info) if bit_count > 0: output.append(bit_buffer & 0xFF) return output image_data = bytearray(width * height) for y in range(height): for x in range(width): if y > x and y < 200 - x: image_data[y * width + x] = 1 else: image_data[y * width + x] = 0 compressed_data = lzw_encode(image_data) block_size = 255 data_blocks = b'' for i in range(0, len(compressed_data), block_size): chunk = compressed_data[i:i+block_size] data_blocks += bytes([len(chunk)]) + chunk data_blocks += b'\x00' # Trailer trailer = b'\x3B' # Write GIF to stdout sys.stdout.buffer.write(header + lsd + gct + gce + img_desc + min_code_size + data_blocks + trailer) |
1 | python your_soln.py > /tmp/a.gif |
I extracted the following code from that output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import sys def write_int(value, bytes): return value.to_bytes(bytes, byteorder='little') def write_color(r, g, b): return bytes([r, g, b]) # GIF header header = b'GIF89a' # Logical Screen Descriptor width, height = 200, 200 lsd = write_int(width, 2) + write_int(height, 2) lsd += bytes([0xF7, 0x00, 0x00]) # Color table info # Global Color Table gct = write_color(255, 255, 255) # White (background) gct += write_color(255, 0, 0) # Red (triangle) gct += b'\x00' * (768 - 6) # Pad to 256 colors # Graphics Control Extension gce = b'\x21\xF9\x04\x00\x00\x00\x00\x00' # Image Descriptor img_desc = b'\x2C\x00\x00\x00\x00' img_desc += write_int(width, 2) + write_int(height, 2) img_desc += b'\x00' # Image Data min_code_size = b'\x08' clear_code = 0x100 end_of_info = 0x101 def lzw_encode(data): code_table = {bytes([i]): i for i in range(256)} next_code = clear_code + 2 buffer = b'' code_size = 9 bit_buffer = 0 bit_count = 0 output = bytearray() def write_code(code): nonlocal bit_buffer, bit_count, output bit_buffer |= code << bit_count bit_count += code_size while bit_count >= 8: output.append(bit_buffer & 0xFF) bit_buffer >>= 8 bit_count -= 8 write_code(clear_code) for byte in data: buffer += bytes([byte]) if buffer in code_table: continue write_code(code_table[buffer[:-1]]) if next_code < 4096: code_table[buffer] = next_code next_code += 1 if next_code.bit_length() > code_size: code_size += 1 buffer = bytes([byte]) if buffer: write_code(code_table[buffer]) write_code(end_of_info) if bit_count > 0: output.append(bit_buffer & 0xFF) return output image_data = bytearray(width * height) for y in range(height): for x in range(width): if y > x and y < 200 - x: image_data[y * width + x] = 1 else: image_data[y * width + x] = 0 compressed_data = lzw_encode(image_data) block_size = 255 data_blocks = b'' for i in range(0, len(compressed_data), block_size): chunk = compressed_data[i:i+block_size] data_blocks += bytes([len(chunk)]) + chunk data_blocks += b'\x00' # Trailer trailer = b'\x3B' # Write GIF to stdout sys.stdout.buffer.write(header + lsd + gct + gce + img_desc + min_code_size + data_blocks + trailer) |
Running the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import sys def write_int(value, bytes): return value.to_bytes(bytes, byteorder='little') def write_color(r, g, b): return bytes([r, g, b]) # GIF header header = b'GIF89a' # Logical Screen Descriptor width, height = 200, 200 lsd = write_int(width, 2) + write_int(height, 2) lsd += bytes([0xF7, 0x00, 0x00]) # Color table info # Global Color Table gct = write_color(255, 255, 255) # White (background) gct += write_color(255, 0, 0) # Red (triangle) gct += b'\x00' * (768 - 6) # Pad to 256 colors # Graphics Control Extension gce = b'\x21\xF9\x04\x00\x00\x00\x00\x00' # Image Descriptor img_desc = b'\x2C\x00\x00\x00\x00' img_desc += write_int(width, 2) + write_int(height, 2) img_desc += b'\x00' # Image Data min_code_size = b'\x08' clear_code = 0x100 end_of_info = 0x101 def lzw_encode(data): code_table = {bytes([i]): i for i in range(256)} next_code = clear_code + 2 buffer = b'' code_size = 9 bit_buffer = 0 bit_count = 0 output = bytearray() def write_code(code): nonlocal bit_buffer, bit_count, output bit_buffer |= code << bit_count bit_count += code_size while bit_count >= 8: output.append(bit_buffer & 0xFF) bit_buffer >>= 8 bit_count -= 8 write_code(clear_code) for byte in data: buffer += bytes([byte]) if buffer in code_table: continue write_code(code_table[buffer[:-1]]) if next_code < 4096: code_table[buffer] = next_code next_code += 1 if next_code.bit_length() > code_size: code_size += 1 buffer = bytes([byte]) if buffer: write_code(code_table[buffer]) write_code(end_of_info) if bit_count > 0: output.append(bit_buffer & 0xFF) return output image_data = bytearray(width * height) for y in range(height): for x in range(width): if y > x and y < 200 - x: image_data[y * width + x] = 1 else: image_data[y * width + x] = 0 compressed_data = lzw_encode(image_data) block_size = 255 data_blocks = b'' for i in range(0, len(compressed_data), block_size): chunk = compressed_data[i:i+block_size] data_blocks += bytes([len(chunk)]) + chunk data_blocks += b'\x00' # Trailer trailer = b'\x3B' # Write GIF to stdout sys.stdout.buffer.write(header + lsd + gct + gce + img_desc + min_code_size + data_blocks + trailer) |
b'GIF89a\xc8\x00\xc8\x00\xf7\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00!\xf9\x04\x00\x00\x00\x00\x00,\x00\x00\x00\x00\xc8\x00\xc8\x00\x00\x08\xff\x00\x01\x08\x1cH\xb0\xa0\xc1\x83\x08\x13*\\\xc8\xb0\xa1\xc3\x87\x10#J\x9c\xa80\x00\xc5\x8b\x183j\xdc\xc8\xb1\xe3\xc2\x00\x16=\x8a\x1cI\xb2\xa4I\x87 C\x9e\\\xc9\xb2\xa5\xcb\x87)U\xbe\x9cI\xb3&\xc9\x982m\xea\xdc\xc9\xb3!\xce\x9c=\x83\n\xdd\xf9\x13\xe8\xd0\xa3HO\x165\x9a\xb4\xa9\xd3\x8cK\x99>\x9dJ\x95aT\xa9U\xb3j\x05p\x15\xeb\xd6\xafM\xbbz\x05K6\xa8\xd8\xb1e\xd3\xd6<\x8bV\xad[\x96l\xdb\xbe\x9d;2\xae\\\xbax5\xda\xbd\x9b\xb7\xaf\xc4\xbd|\xfd\n\xb6\nx\xb0a\xbd\x80\x03\x1f^\xcc5\xb1b\xc6\x83\x1d\x83\x84L\xf9\xa3\xe4\xc7\x95\xe9^\x9e\x9c\xb9\xb3\xc0\xcd\x9c=W\x06\x1dZ4c\xd2\xa5M\x1bF\x9dZ\xb5_\xd6\xad]\xe3\x85\x1d[\xf6[\xda\xb5m\xa7\xc5\x9d[7X\xde\xbd}k\x05\x1e\\8U\xe2\xc5\x8d;E\x9e\\9R\xe6\xcd\x9d\x0b\x85\x1e]:O\xea\xd5\xad\xdb\xc4\x9e]\xfbL\xee\xdd\xbd\xb7\xff\x04\x1f^\xbcR\xf2\x98\xcd\xd7E\x9f^}G\xf6\xe5\xdd\xbf\x87\xdf^>F\xfa\xf1\xed\xdf\xc7__\x7fD\xfe\xf2\xf3\xef?\x00\xfb\x13\x900\x02\r\\\x89\xc0\x94\x124iA\x06\x1b\\\xef\xc1\x02#\x1chB\x08+\xdc\xe8B\x0c3\xdcoC\n\x1b\xfc\x90\xc3\x0e\xff\x121\xc0\nM\x1c\x91D\x94R<1\xc1\x16U\\\xb1"\x18]\xf4\x8f\xc6\x18e4\xe8F\x1cs\xb4p\xc7\x1a\xdd\xfb\x91\xc7\x1c\x85\x1cr\xc5"\x8d\xec\x10\xc9$Q\\\x12H\xeb\x9cd\xf2\xc5(\x9fT\x8eJ)m\xbc\xb2J\xdf\xb4\xc4R\xbe.\xbdT\x0f\xcc0\xc5\x1b\x93L\xed\xcc<S\xba4\xd5\xb4\x92\xcd-={\xb3M.\xe5\x84s\xb4:\xed\x84\x0c\xcf9]\xdb\x93O\xd3\xfc\xfc3\xce@\xf3\x8c\x8c\xd0B_;\x14\xd1\xbc\x14\x15T\xcfF\x17\x9d\x0bRG\x0f\x9b\x94RC-\x051\xd1L5e\x94\xd3H\xc9\xfa\xf4\xd2\xd9D\x05u\xabR;\x95TT(?E\x93S\xef^\x85\xff\xd5R\xf3f\xa5\x15\xd2 \x1b\xfdRQ\xfbv\xe5\x95\xd0,\xfd\x140P\x03\x83%\x16\xcf\x10\xeb\x8c0Ye\xdf\xcc\xb0Yg\xd3$1Zi\xc7\x94\xb1Zk\xbb\xec1[m\xaf\xec\xf13*\xbd\xfd\xd6\xc9p\xc5E\x92\xdcr\x85<\x17\xdd\x1d\xd5]\x97\xc6v\xddm\x11\xdexM\x9c\x97\xde\x0f\xed\xbd\xf7\xc2|\xf5}\x90\xdf~\x11\xfc\xb7\xb1\x14\x05\x06\x18\xbf\x82\r\x86\x0f\xe1\x84\xd1[\x98a\xf0\x1c~\x18\xbb\x88%\x86\x8e\xe2\x8a\x91\xbb\x18c\xe04\xde\x18\xb7\x8e=\x86\r\xe4\x90Q\x1b\x99d\xd0L>\xf9\xb2\x94Uv\x8c\xe5\x96\x0b{y`\xf2d\x869\xae\x9am>\x0b\xe7\x9c\xbb\xda\x99\xe7\xa8|\xfe\xb9\xa8\xa0\x85\xc6\x89\xe8\xa2G\xb5\xd7\xe2\xa3\x91f\xdaG\x8e\x9d\x16:\xea\xa7i\x9b\x9aj\xd6\xac\xbe\x9a\xb4\xac\xb5\xde\x8c\xeb\xae%\xfb\x1a\xec\xc4\xc4\x1e{\xaf\xb2\xcd\xbe\x19m\x92\xd7N[\xac\xb6\xdd\xbe\n\xee\xb8\x97\x9a\x9b\xee\x9f\xec\xbe;\xa6\xbc\xf5675\xe2\xb3\xf9\xd6;p\x82\xd4\x1e\xdc`\xc3\t\x7f\x1bq\xb7\x17O\x1c\xe8\xc6\xcd\x86\xdcq\xbc%\x07\xbb\xf2\xc9\x93v\x9a\xf2\xcb\xaf\xe6\xbc\xa0\xbd=w<\xf4\xcfS\xcd\xba\xf4\xac\x03\x02\x00;'
Describe the shapes in this image and their color
broken data stream when reading image file
Testing if the previous output contains the string red
: False
Testing if the previous output contains the string triangle
: False
Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Here's a Python program that manually creates a GIF file containing a red triangle on a white background, without using any graphics libraries. The program writes the GIF file byte by byte and outputs it to stdout:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import sys def write_int16(value): return bytes([value & 0xFF, (value >> 8) & 0xFF]) def write_color(r, g, b): return bytes([r, g, b]) # GIF header gif_header = b'GIF89a' # Logical Screen Descriptor width, height = 200, 200 packed_field = 0b10010001 # Color table present, 2 colors gif_lsd = write_int16(width) + write_int16(height) + bytes([packed_field, 0, 0]) # Global Color Table white = write_color(255, 255, 255) red = write_color(255, 0, 0) gif_gct = white + red # Image Descriptor gif_id = b'\x2C\x00\x00\x00\x00' + write_int16(width) + write_int16(height) + b'\x00' # Image Data def lzw_encode(pixels): code_size = 2 clear_code = 4 end_code = 5 next_code = 6 max_code = 7 dict_size = 6 output = bytearray([code_size]) buffer = 0 bits = 0 def output_code(code): nonlocal buffer, bits buffer |= code << bits bits += code_size while bits >= 8: output.append(buffer & 0xFF) buffer >>= 8 bits -= 8 output_code(clear_code) for pixel in pixels: output_code(pixel) if next_code == max_code and code_size < 12: code_size += 1 max_code = (1 << code_size) - 1 next_code += 1 if next_code > max_code: output_code(clear_code) code_size = 2 max_code = 7 next_code = 6 dict_size = 6 output_code(end_code) if bits > 0: output.append(buffer & 0xFF) return bytes([len(output)]) + output + b'\x00' pixels = [] for y in range(height): for x in range(width): if y > x and y < 200 - x: pixels.append(1) # Red else: pixels.append(0) # White gif_data = lzw_encode(pixels) # Trailer gif_trailer = b'\x3B' # Combine all parts and write to stdout sys.stdout.buffer.write(gif_header + gif_lsd + gif_gct + gif_id + gif_data + gif_trailer) |
1 | python triangle_gif.py > /tmp/a.gif |
I extracted the following code from that output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import sys def write_int16(value): return bytes([value & 0xFF, (value >> 8) & 0xFF]) def write_color(r, g, b): return bytes([r, g, b]) # GIF header gif_header = b'GIF89a' # Logical Screen Descriptor width, height = 200, 200 packed_field = 0b10010001 # Color table present, 2 colors gif_lsd = write_int16(width) + write_int16(height) + bytes([packed_field, 0, 0]) # Global Color Table white = write_color(255, 255, 255) red = write_color(255, 0, 0) gif_gct = white + red # Image Descriptor gif_id = b'\x2C\x00\x00\x00\x00' + write_int16(width) + write_int16(height) + b'\x00' # Image Data def lzw_encode(pixels): code_size = 2 clear_code = 4 end_code = 5 next_code = 6 max_code = 7 dict_size = 6 output = bytearray([code_size]) buffer = 0 bits = 0 def output_code(code): nonlocal buffer, bits buffer |= code << bits bits += code_size while bits >= 8: output.append(buffer & 0xFF) buffer >>= 8 bits -= 8 output_code(clear_code) for pixel in pixels: output_code(pixel) if next_code == max_code and code_size < 12: code_size += 1 max_code = (1 << code_size) - 1 next_code += 1 if next_code > max_code: output_code(clear_code) code_size = 2 max_code = 7 next_code = 6 dict_size = 6 output_code(end_code) if bits > 0: output.append(buffer & 0xFF) return bytes([len(output)]) + output + b'\x00' pixels = [] for y in range(height): for x in range(width): if y > x and y < 200 - x: pixels.append(1) # Red else: pixels.append(0) # White gif_data = lzw_encode(pixels) # Trailer gif_trailer = b'\x3B' # Combine all parts and write to stdout sys.stdout.buffer.write(gif_header + gif_lsd + gif_gct + gif_id + gif_data + gif_trailer) |
Running the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import sys def write_int16(value): return bytes([value & 0xFF, (value >> 8) & 0xFF]) def write_color(r, g, b): return bytes([r, g, b]) # GIF header gif_header = b'GIF89a' # Logical Screen Descriptor width, height = 200, 200 packed_field = 0b10010001 # Color table present, 2 colors gif_lsd = write_int16(width) + write_int16(height) + bytes([packed_field, 0, 0]) # Global Color Table white = write_color(255, 255, 255) red = write_color(255, 0, 0) gif_gct = white + red # Image Descriptor gif_id = b'\x2C\x00\x00\x00\x00' + write_int16(width) + write_int16(height) + b'\x00' # Image Data def lzw_encode(pixels): code_size = 2 clear_code = 4 end_code = 5 next_code = 6 max_code = 7 dict_size = 6 output = bytearray([code_size]) buffer = 0 bits = 0 def output_code(code): nonlocal buffer, bits buffer |= code << bits bits += code_size while bits >= 8: output.append(buffer & 0xFF) buffer >>= 8 bits -= 8 output_code(clear_code) for pixel in pixels: output_code(pixel) if next_code == max_code and code_size < 12: code_size += 1 max_code = (1 << code_size) - 1 next_code += 1 if next_code > max_code: output_code(clear_code) code_size = 2 max_code = 7 next_code = 6 dict_size = 6 output_code(end_code) if bits > 0: output.append(buffer & 0xFF) return bytes([len(output)]) + output + b'\x00' pixels = [] for y in range(height): for x in range(width): if y > x and y < 200 - x: pixels.append(1) # Red else: pixels.append(0) # White gif_data = lzw_encode(pixels) # Trailer gif_trailer = b'\x3B' # Combine all parts and write to stdout sys.stdout.buffer.write(gif_header + gif_lsd + gif_gct + gif_id + gif_data + gif_trailer) |
b'Traceback (most recent call last):\n File "/usr/src/app/main.py", line 79, in <module>\n gif_data = lzw_encode(pixels)\n File "/usr/src/app/main.py", line 69, in lzw_encode\n return bytes([len(output)]) + output + b\'\\x00\'\nValueError: bytes must be in range(0, 256)\n'
Describe the shapes in this image and their color
cannot identify image file <_io.BytesIO object at 0x7f74c3663220>
Testing if the previous output contains the string red
: False
Testing if the previous output contains the string triangle
: False
Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Write a python program that, manually, draws a red triangle on a white background and saves it as a 200x200 gif file. Do not use any graphics libraries. Write the gif byte by byte. Output the gif file to stdout. I will evaluate your program by running `python your_soln.py > /tmp/a.gif` and then view the output file.
Here's a Python program that manually creates a 200x200 GIF file with a red triangle on a white background, writing the GIF byte by byte without using any graphics libraries:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import sys def write_uint16(value): return bytes([value & 0xFF, (value >> 8) & 0xFF]) def write_color(r, g, b): return bytes([r, g, b]) # GIF header header = b'GIF89a' # Logical Screen Descriptor width, height = 200, 200 lsd = write_uint16(width) + write_uint16(height) + b'\xF7\x00\x00' # Global Color Table gct = b''.join([ write_color(255, 255, 255), # White (background) write_color(255, 0, 0), # Red (triangle color) *[write_color(0, 0, 0) for _ in range(254)] # Padding ]) # Image Descriptor img_descriptor = b'\x2C\x00\x00\x00\x00' + write_uint16(width) + write_uint16(height) + b'\x00' # Image Data def lzw_compress(data): clear_code = 4 end_code = 5 code_size = 3 next_code = 6 code_table = {(i,): i for i in range(4)} output = [clear_code] current_sequence = () for pixel in data: new_sequence = current_sequence + (pixel,) if new_sequence in code_table: current_sequence = new_sequence else: output.append(code_table[current_sequence]) code_table[new_sequence] = next_code next_code += 1 current_sequence = (pixel,) if next_code == 2**code_size: code_size += 1 if next_code == 4096: output.append(clear_code) code_size = 3 next_code = 6 code_table = {(i,): i for i in range(4)} if current_sequence: output.append(code_table[current_sequence]) output.append(end_code) return output def triangle_pixel(x, y): if y >= x and y >= -x + 199 and y <= 199: return 1 return 0 image_data = [triangle_pixel(x, y) for y in range(height) for x in range(width)] compressed_data = lzw_compress(image_data) # Convert compressed data to bytes bit_stream = ''.join(f'{code:0{max(3, (code.bit_length() + 7) // 8 * 8)}b}' for code in compressed_data) byte_stream = [int(bit_stream[i:i+8], 2) for i in range(0, len(bit_stream), 8)] # Add LZW minimum code size img_data = b'\x03' + bytes([len(byte_stream)]) + bytes(byte_stream) + b'\x00' # Trailer trailer = b'\x3B' # Combine all parts gif_data = header + lsd + gct + img_descriptor + img_data + trailer # Write to stdout sys.stdout.buffer.write(gif_data) |
1 | python triangle_gif.py > /tmp/a.gif |
I extracted the following code from that output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import sys def write_uint16(value): return bytes([value & 0xFF, (value >> 8) & 0xFF]) def write_color(r, g, b): return bytes([r, g, b]) # GIF header header = b'GIF89a' # Logical Screen Descriptor width, height = 200, 200 lsd = write_uint16(width) + write_uint16(height) + b'\xF7\x00\x00' # Global Color Table gct = b''.join([ write_color(255, 255, 255), # White (background) write_color(255, 0, 0), # Red (triangle color) *[write_color(0, 0, 0) for _ in range(254)] # Padding ]) # Image Descriptor img_descriptor = b'\x2C\x00\x00\x00\x00' + write_uint16(width) + write_uint16(height) + b'\x00' # Image Data def lzw_compress(data): clear_code = 4 end_code = 5 code_size = 3 next_code = 6 code_table = {(i,): i for i in range(4)} output = [clear_code] current_sequence = () for pixel in data: new_sequence = current_sequence + (pixel,) if new_sequence in code_table: current_sequence = new_sequence else: output.append(code_table[current_sequence]) code_table[new_sequence] = next_code next_code += 1 current_sequence = (pixel,) if next_code == 2**code_size: code_size += 1 if next_code == 4096: output.append(clear_code) code_size = 3 next_code = 6 code_table = {(i,): i for i in range(4)} if current_sequence: output.append(code_table[current_sequence]) output.append(end_code) return output def triangle_pixel(x, y): if y >= x and y >= -x + 199 and y <= 199: return 1 return 0 image_data = [triangle_pixel(x, y) for y in range(height) for x in range(width)] compressed_data = lzw_compress(image_data) # Convert compressed data to bytes bit_stream = ''.join(f'{code:0{max(3, (code.bit_length() + 7) // 8 * 8)}b}' for code in compressed_data) byte_stream = [int(bit_stream[i:i+8], 2) for i in range(0, len(bit_stream), 8)] # Add LZW minimum code size img_data = b'\x03' + bytes([len(byte_stream)]) + bytes(byte_stream) + b'\x00' # Trailer trailer = b'\x3B' # Combine all parts gif_data = header + lsd + gct + img_descriptor + img_data + trailer # Write to stdout sys.stdout.buffer.write(gif_data) |
Running the following program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | import sys def write_uint16(value): return bytes([value & 0xFF, (value >> 8) & 0xFF]) def write_color(r, g, b): return bytes([r, g, b]) # GIF header header = b'GIF89a' # Logical Screen Descriptor width, height = 200, 200 lsd = write_uint16(width) + write_uint16(height) + b'\xF7\x00\x00' # Global Color Table gct = b''.join([ write_color(255, 255, 255), # White (background) write_color(255, 0, 0), # Red (triangle color) *[write_color(0, 0, 0) for _ in range(254)] # Padding ]) # Image Descriptor img_descriptor = b'\x2C\x00\x00\x00\x00' + write_uint16(width) + write_uint16(height) + b'\x00' # Image Data def lzw_compress(data): clear_code = 4 end_code = 5 code_size = 3 next_code = 6 code_table = {(i,): i for i in range(4)} output = [clear_code] current_sequence = () for pixel in data: new_sequence = current_sequence + (pixel,) if new_sequence in code_table: current_sequence = new_sequence else: output.append(code_table[current_sequence]) code_table[new_sequence] = next_code next_code += 1 current_sequence = (pixel,) if next_code == 2**code_size: code_size += 1 if next_code == 4096: output.append(clear_code) code_size = 3 next_code = 6 code_table = {(i,): i for i in range(4)} if current_sequence: output.append(code_table[current_sequence]) output.append(end_code) return output def triangle_pixel(x, y): if y >= x and y >= -x + 199 and y <= 199: return 1 return 0 image_data = [triangle_pixel(x, y) for y in range(height) for x in range(width)] compressed_data = lzw_compress(image_data) # Convert compressed data to bytes bit_stream = ''.join(f'{code:0{max(3, (code.bit_length() + 7) // 8 * 8)}b}' for code in compressed_data) byte_stream = [int(bit_stream[i:i+8], 2) for i in range(0, len(bit_stream), 8)] # Add LZW minimum code size img_data = b'\x03' + bytes([len(byte_stream)]) + bytes(byte_stream) + b'\x00' # Trailer trailer = b'\x3B' # Combine all parts gif_data = header + lsd + gct + img_descriptor + img_data + trailer # Write to stdout sys.stdout.buffer.write(gif_data) |
b'Traceback (most recent call last):\n File "/usr/src/app/main.py", line 76, in <module>\n img_data = b\'\\x03\' + bytes([len(byte_stream)]) + bytes(byte_stream) + b\'\\x00\'\nValueError: bytes must be in range(0, 256)\n'
Describe the shapes in this image and their color
cannot identify image file <_io.BytesIO object at 0x7fdffd545450>
Testing if the previous output contains the string red
: False
Testing if the previous output contains the string triangle
: False