Write me a C program that emits a .bmp that's a depiction of an american flag to stdout.
Write me a C program that emits a .bmp that's a depiction of an american flag to stdout.
Okay, here is a C program that generates a 24-bit BMP image representing a simplified American flag and writes it to standard output. This version uses approximate proportions and colors, and features a solid blue union (canton) without stars for simplicity. Drawing stars accurately requires significantly more complex pixel-level logic.
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | #include <stdio.h> #include <stdint.h> // For specific width integer types like uint32_t #include <stdlib.h> // For exit() // --- BMP Header Structures --- // Ensure structs are packed tightly (no padding bytes between members) #pragma pack(push, 1) typedef struct { uint16_t bfType; // Magic identifier: 0x4D42 (ASCII 'BM') uint32_t bfSize; // Size of the BMP file in bytes uint16_t bfReserved1; // Reserved; must be 0 uint16_t bfReserved2; // Reserved; must be 0 uint32_t bfOffBits; // Offset from beginning of file to bitmap data } BITMAPFILEHEADER; typedef struct { uint32_t biSize; // Size of this header (40 bytes) int32_t biWidth; // Bitmap width in pixels int32_t biHeight; // Bitmap height in pixels (positive for bottom-up) uint16_t biPlanes; // Number of color planes (must be 1) uint16_t biBitCount; // Bits per pixel (1, 4, 8, 16, 24, or 32) uint32_t biCompression; // Compression type (0 for BI_RGB - no compression) uint32_t biSizeImage; // Size of image data in bytes (can be 0 for BI_RGB) int32_t biXPelsPerMeter;// Horizontal resolution (pixels per meter) int32_t biYPelsPerMeter;// Vertical resolution (pixels per meter) uint32_t biClrUsed; // Number of colors in the palette (0 for 24-bit) uint32_t biClrImportant; // Number of important colors (0 means all) } BITMAPINFOHEADER; #pragma pack(pop) // --- Image Parameters --- // Using dimensions somewhat close to 1.9:1 ratio, and divisible by 13 #define IMG_WIDTH 380 #define IMG_HEIGHT 260 // Divisible by 13 stripes #define BITS_PER_PIXEL 24 #define BYTES_PER_PIXEL (BITS_PER_PIXEL / 8) // --- Colors (BGR format for BMP) --- typedef struct { uint8_t blue; uint8_t green; uint8_t red; } PixelColor; const PixelColor COLOR_RED = { 52, 34, 178 }; // Approx "Old Glory Red" (BGR) const PixelColor COLOR_WHITE = { 255, 255, 255 }; const PixelColor COLOR_BLUE = { 110, 59, 60 }; // Approx "Old Glory Blue" (BGR) int main() { // --- Calculate BMP Sizes --- // Each row must be padded to a multiple of 4 bytes uint32_t row_padded_size = (IMG_WIDTH * BYTES_PER_PIXEL + 3) & (~3); uint32_t pixel_data_size = row_padded_size * IMG_HEIGHT; uint32_t file_size = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + pixel_data_size; // --- Prepare Headers --- BITMAPFILEHEADER file_header = { .bfType = 0x4D42, // 'BM' .bfSize = file_size, .bfReserved1 = 0, .bfReserved2 = 0, .bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) }; BITMAPINFOHEADER info_header = { .biSize = sizeof(BITMAPINFOHEADER), .biWidth = IMG_WIDTH, .biHeight = IMG_HEIGHT, // Positive: bottom-up DIB .biPlanes = 1, .biBitCount = BITS_PER_PIXEL, .biCompression = 0, // BI_RGB .biSizeImage = pixel_data_size, // Can be 0 for BI_RGB, but safer to set .biXPelsPerMeter = 0, // Or use a default like 2835 (72 DPI) .biYPelsPerMeter = 0, // Or use a default like 2835 (72 DPI) .biClrUsed = 0, .biClrImportant = 0 }; // --- Write Headers to stdout --- // Note: Writing binary data to stdout might require special handling // on some systems (like Windows cmd.exe) if not redirected properly. // Use redirection: ./program > flag.bmp if (fwrite(&file_header, sizeof(file_header), 1, stdout) != 1) { perror("Error writing file header"); return 1; } if (fwrite(&info_header, sizeof(info_header), 1, stdout) != 1) { perror("Error writing info header"); return 1; } // --- Generate and Write Pixel Data (Bottom-up) --- int stripe_height = IMG_HEIGHT / 13; // Height of each stripe int union_height = 7 * stripe_height; // Union covers top 7 stripes int union_width = (int)(IMG_WIDTH * 2.0 / 5.0); // Union width approx 2/5 uint8_t padding_byte = 0; int padding_size = row_padded_size - (IMG_WIDTH * BYTES_PER_PIXEL); for (int y = 0; y < IMG_HEIGHT; ++y) { // Loop rows bottom-up (0 to height-1) for (int x = 0; x < IMG_WIDTH; ++x) { // Loop columns left-to-right PixelColor current_color; // Determine if pixel is in the blue union (canton) // Remember y=0 is the bottom row, so union is at high y values if (x < union_width && y >= (IMG_HEIGHT - union_height)) { current_color = COLOR_BLUE; } else { // Determine stripe color int stripe_index_from_top = (IMG_HEIGHT - 1 - y) / stripe_height; if (stripe_index_from_top % 2 == 0) { // Even stripes (0, 2, ...) are red current_color = COLOR_RED; } else { // Odd stripes (1, 3, ...) are white current_color = COLOR_WHITE; } } // Write pixel color (BGR) if (fwrite(¤t_color, sizeof(PixelColor), 1, stdout) != 1) { perror("Error writing pixel data"); // Attempt to close stdout? Might be problematic. Exit. return 1; } } // Write row padding for (int k = 0; k < padding_size; ++k) { if (fwrite(&padding_byte, 1, 1, stdout) != 1) { perror("Error writing padding byte"); return 1; } } } // Ensure all buffered data is written fflush(stdout); // Optional: Check for errors on stdout after writing if (ferror(stdout)) { fprintf(stderr, "Error occurred during writing to stdout.\n"); // Clear error only if needed for further stdout use (unlikely here) // clearerr(stdout); return 1; // Indicate failure } return 0; // Success } |
1 2 | gcc flag_generator.c -o flag_generator -Wall -Wextra -std=c99 -lm |
1 2 | ./flag_generator > flag.bmp |
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | #include <stdio.h> #include <stdint.h> // For specific width integer types like uint32_t #include <stdlib.h> // For exit() // --- BMP Header Structures --- // Ensure structs are packed tightly (no padding bytes between members) #pragma pack(push, 1) typedef struct { uint16_t bfType; // Magic identifier: 0x4D42 (ASCII 'BM') uint32_t bfSize; // Size of the BMP file in bytes uint16_t bfReserved1; // Reserved; must be 0 uint16_t bfReserved2; // Reserved; must be 0 uint32_t bfOffBits; // Offset from beginning of file to bitmap data } BITMAPFILEHEADER; typedef struct { uint32_t biSize; // Size of this header (40 bytes) int32_t biWidth; // Bitmap width in pixels int32_t biHeight; // Bitmap height in pixels (positive for bottom-up) uint16_t biPlanes; // Number of color planes (must be 1) uint16_t biBitCount; // Bits per pixel (1, 4, 8, 16, 24, or 32) uint32_t biCompression; // Compression type (0 for BI_RGB - no compression) uint32_t biSizeImage; // Size of image data in bytes (can be 0 for BI_RGB) int32_t biXPelsPerMeter;// Horizontal resolution (pixels per meter) int32_t biYPelsPerMeter;// Vertical resolution (pixels per meter) uint32_t biClrUsed; // Number of colors in the palette (0 for 24-bit) uint32_t biClrImportant; // Number of important colors (0 means all) } BITMAPINFOHEADER; #pragma pack(pop) // --- Image Parameters --- // Using dimensions somewhat close to 1.9:1 ratio, and divisible by 13 #define IMG_WIDTH 380 #define IMG_HEIGHT 260 // Divisible by 13 stripes #define BITS_PER_PIXEL 24 #define BYTES_PER_PIXEL (BITS_PER_PIXEL / 8) // --- Colors (BGR format for BMP) --- typedef struct { uint8_t blue; uint8_t green; uint8_t red; } PixelColor; const PixelColor COLOR_RED = { 52, 34, 178 }; // Approx "Old Glory Red" (BGR) const PixelColor COLOR_WHITE = { 255, 255, 255 }; const PixelColor COLOR_BLUE = { 110, 59, 60 }; // Approx "Old Glory Blue" (BGR) int main() { // --- Calculate BMP Sizes --- // Each row must be padded to a multiple of 4 bytes uint32_t row_padded_size = (IMG_WIDTH * BYTES_PER_PIXEL + 3) & (~3); uint32_t pixel_data_size = row_padded_size * IMG_HEIGHT; uint32_t file_size = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + pixel_data_size; // --- Prepare Headers --- BITMAPFILEHEADER file_header = { .bfType = 0x4D42, // 'BM' .bfSize = file_size, .bfReserved1 = 0, .bfReserved2 = 0, .bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) }; BITMAPINFOHEADER info_header = { .biSize = sizeof(BITMAPINFOHEADER), .biWidth = IMG_WIDTH, .biHeight = IMG_HEIGHT, // Positive: bottom-up DIB .biPlanes = 1, .biBitCount = BITS_PER_PIXEL, .biCompression = 0, // BI_RGB .biSizeImage = pixel_data_size, // Can be 0 for BI_RGB, but safer to set .biXPelsPerMeter = 0, // Or use a default like 2835 (72 DPI) .biYPelsPerMeter = 0, // Or use a default like 2835 (72 DPI) .biClrUsed = 0, .biClrImportant = 0 }; // --- Write Headers to stdout --- // Note: Writing binary data to stdout might require special handling // on some systems (like Windows cmd.exe) if not redirected properly. // Use redirection: ./program > flag.bmp if (fwrite(&file_header, sizeof(file_header), 1, stdout) != 1) { perror("Error writing file header"); return 1; } if (fwrite(&info_header, sizeof(info_header), 1, stdout) != 1) { perror("Error writing info header"); return 1; } // --- Generate and Write Pixel Data (Bottom-up) --- int stripe_height = IMG_HEIGHT / 13; // Height of each stripe int union_height = 7 * stripe_height; // Union covers top 7 stripes int union_width = (int)(IMG_WIDTH * 2.0 / 5.0); // Union width approx 2/5 uint8_t padding_byte = 0; int padding_size = row_padded_size - (IMG_WIDTH * BYTES_PER_PIXEL); for (int y = 0; y < IMG_HEIGHT; ++y) { // Loop rows bottom-up (0 to height-1) for (int x = 0; x < IMG_WIDTH; ++x) { // Loop columns left-to-right PixelColor current_color; // Determine if pixel is in the blue union (canton) // Remember y=0 is the bottom row, so union is at high y values if (x < union_width && y >= (IMG_HEIGHT - union_height)) { current_color = COLOR_BLUE; } else { // Determine stripe color int stripe_index_from_top = (IMG_HEIGHT - 1 - y) / stripe_height; if (stripe_index_from_top % 2 == 0) { // Even stripes (0, 2, ...) are red current_color = COLOR_RED; } else { // Odd stripes (1, 3, ...) are white current_color = COLOR_WHITE; } } // Write pixel color (BGR) if (fwrite(¤t_color, sizeof(PixelColor), 1, stdout) != 1) { perror("Error writing pixel data"); // Attempt to close stdout? Might be problematic. Exit. return 1; } } // Write row padding for (int k = 0; k < padding_size; ++k) { if (fwrite(&padding_byte, 1, 1, stdout) != 1) { perror("Error writing padding byte"); return 1; } } } // Ensure all buffered data is written fflush(stdout); // Optional: Check for errors on stdout after writing if (ferror(stdout)) { fprintf(stderr, "Error occurred during writing to stdout.\n"); // Clear error only if needed for further stdout use (unlikely here) // clearerr(stdout); return 1; // Indicate failure } return 0; // Success } |
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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | #include <stdio.h> #include <stdint.h> // For specific width integer types like uint32_t #include <stdlib.h> // For exit() // --- BMP Header Structures --- // Ensure structs are packed tightly (no padding bytes between members) #pragma pack(push, 1) typedef struct { uint16_t bfType; // Magic identifier: 0x4D42 (ASCII 'BM') uint32_t bfSize; // Size of the BMP file in bytes uint16_t bfReserved1; // Reserved; must be 0 uint16_t bfReserved2; // Reserved; must be 0 uint32_t bfOffBits; // Offset from beginning of file to bitmap data } BITMAPFILEHEADER; typedef struct { uint32_t biSize; // Size of this header (40 bytes) int32_t biWidth; // Bitmap width in pixels int32_t biHeight; // Bitmap height in pixels (positive for bottom-up) uint16_t biPlanes; // Number of color planes (must be 1) uint16_t biBitCount; // Bits per pixel (1, 4, 8, 16, 24, or 32) uint32_t biCompression; // Compression type (0 for BI_RGB - no compression) uint32_t biSizeImage; // Size of image data in bytes (can be 0 for BI_RGB) int32_t biXPelsPerMeter;// Horizontal resolution (pixels per meter) int32_t biYPelsPerMeter;// Vertical resolution (pixels per meter) uint32_t biClrUsed; // Number of colors in the palette (0 for 24-bit) uint32_t biClrImportant; // Number of important colors (0 means all) } BITMAPINFOHEADER; #pragma pack(pop) // --- Image Parameters --- // Using dimensions somewhat close to 1.9:1 ratio, and divisible by 13 #define IMG_WIDTH 380 #define IMG_HEIGHT 260 // Divisible by 13 stripes #define BITS_PER_PIXEL 24 #define BYTES_PER_PIXEL (BITS_PER_PIXEL / 8) // --- Colors (BGR format for BMP) --- typedef struct { uint8_t blue; uint8_t green; uint8_t red; } PixelColor; const PixelColor COLOR_RED = { 52, 34, 178 }; // Approx "Old Glory Red" (BGR) const PixelColor COLOR_WHITE = { 255, 255, 255 }; const PixelColor COLOR_BLUE = { 110, 59, 60 }; // Approx "Old Glory Blue" (BGR) int main() { // --- Calculate BMP Sizes --- // Each row must be padded to a multiple of 4 bytes uint32_t row_padded_size = (IMG_WIDTH * BYTES_PER_PIXEL + 3) & (~3); uint32_t pixel_data_size = row_padded_size * IMG_HEIGHT; uint32_t file_size = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + pixel_data_size; // --- Prepare Headers --- BITMAPFILEHEADER file_header = { .bfType = 0x4D42, // 'BM' .bfSize = file_size, .bfReserved1 = 0, .bfReserved2 = 0, .bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) }; BITMAPINFOHEADER info_header = { .biSize = sizeof(BITMAPINFOHEADER), .biWidth = IMG_WIDTH, .biHeight = IMG_HEIGHT, // Positive: bottom-up DIB .biPlanes = 1, .biBitCount = BITS_PER_PIXEL, .biCompression = 0, // BI_RGB .biSizeImage = pixel_data_size, // Can be 0 for BI_RGB, but safer to set .biXPelsPerMeter = 0, // Or use a default like 2835 (72 DPI) .biYPelsPerMeter = 0, // Or use a default like 2835 (72 DPI) .biClrUsed = 0, .biClrImportant = 0 }; // --- Write Headers to stdout --- // Note: Writing binary data to stdout might require special handling // on some systems (like Windows cmd.exe) if not redirected properly. // Use redirection: ./program > flag.bmp if (fwrite(&file_header, sizeof(file_header), 1, stdout) != 1) { perror("Error writing file header"); return 1; } if (fwrite(&info_header, sizeof(info_header), 1, stdout) != 1) { perror("Error writing info header"); return 1; } // --- Generate and Write Pixel Data (Bottom-up) --- int stripe_height = IMG_HEIGHT / 13; // Height of each stripe int union_height = 7 * stripe_height; // Union covers top 7 stripes int union_width = (int)(IMG_WIDTH * 2.0 / 5.0); // Union width approx 2/5 uint8_t padding_byte = 0; int padding_size = row_padded_size - (IMG_WIDTH * BYTES_PER_PIXEL); for (int y = 0; y < IMG_HEIGHT; ++y) { // Loop rows bottom-up (0 to height-1) for (int x = 0; x < IMG_WIDTH; ++x) { // Loop columns left-to-right PixelColor current_color; // Determine if pixel is in the blue union (canton) // Remember y=0 is the bottom row, so union is at high y values if (x < union_width && y >= (IMG_HEIGHT - union_height)) { current_color = COLOR_BLUE; } else { // Determine stripe color int stripe_index_from_top = (IMG_HEIGHT - 1 - y) / stripe_height; if (stripe_index_from_top % 2 == 0) { // Even stripes (0, 2, ...) are red current_color = COLOR_RED; } else { // Odd stripes (1, 3, ...) are white current_color = COLOR_WHITE; } } // Write pixel color (BGR) if (fwrite(¤t_color, sizeof(PixelColor), 1, stdout) != 1) { perror("Error writing pixel data"); // Attempt to close stdout? Might be problematic. Exit. return 1; } } // Write row padding for (int k = 0; k < padding_size; ++k) { if (fwrite(&padding_byte, 1, 1, stdout) != 1) { perror("Error writing padding byte"); return 1; } } } // Ensure all buffered data is written fflush(stdout); // Optional: Check for errors on stdout after writing if (ferror(stdout)) { fprintf(stderr, "Error occurred during writing to stdout.\n"); // Clear error only if needed for further stdout use (unlikely here) // clearerr(stdout); return 1; // Indicate failure } return 0; // Success } |

What flag is shown in this image?
This is the Grand Union Flag, also known as the Continental Colors. It was the first national flag of the United States, used from 1775 to 1777.
Testing if the previous output contains the string America
: False
Testing if the previous output contains the string USA
: False
Testing if the previous output contains the string United States
: True