close
close
Generating Images in C

Generating Images in C

3 min read 09-11-2024
Generating Images in C

Generating images in the C programming language can be an interesting challenge, especially for those looking to delve into graphics programming. This article will provide you with a clear understanding of how to create simple images using C.

Understanding Image Formats

Before diving into code, it's essential to understand the basics of image formats. Common formats like BMP, PNG, and JPEG each have specific structures:

  • BMP (Bitmap Image File): This format is straightforward and ideal for beginners. It has a simple header that makes it easier to write and read from binary files.
  • PNG (Portable Network Graphics): A more complex format that supports lossless compression and transparency.
  • JPEG (Joint Photographic Experts Group): Often used for photographs due to its lossy compression.

For this tutorial, we will focus on generating a BMP image since it's simpler to implement.

Creating a BMP Image

Step 1: Defining the BMP Header

A BMP file starts with a header, which includes metadata about the image. Here's a simplified structure of a BMP header:

#pragma pack(push, 1) // Ensure no padding in the structure
typedef struct {
    uint16_t bfType;      // File type
    uint32_t bfSize;      // File size in bytes
    uint16_t bfReserved1; // Reserved; must be zero
    uint16_t bfReserved2; // Reserved; must be zero
    uint32_t bfOffBits;   // Offset to start of pixel data
} BITMAPFILEHEADER;

typedef struct {
    uint32_t biSize;          // Size of this header
    int32_t  biWidth;         // Width of the bitmap in pixels
    int32_t  biHeight;        // Height of the bitmap in pixels
    uint16_t biPlanes;        // Number of color planes (must be 1)
    uint16_t biBitCount;      // Bits per pixel
    uint32_t biCompression;   // Compression method
    uint32_t biSizeImage;     // Size of the pixel data
    int32_t  biXPelsPerMeter;  // Horizontal resolution
    int32_t  biYPelsPerMeter;  // Vertical resolution
    uint32_t biClrUsed;       // Number of colors in the palette
    uint32_t biClrImportant;   // Important colors
} BITMAPINFOHEADER;
#pragma pack(pop)

Step 2: Writing the Image Data

Next, let's create a function to generate an image:

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

void createBMP(const char *filename, int width, int height) {
    BITMAPFILEHEADER bfh;
    BITMAPINFOHEADER bih;

    // Set the BMP file header
    bfh.bfType = 0x4D42; // 'BM'
    bfh.bfReserved1 = 0;
    bfh.bfReserved2 = 0;
    bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
    bfh.bfSize = bfh.bfOffBits + width * height * 3;

    // Set the BMP info header
    bih.biSize = sizeof(BITMAPINFOHEADER);
    bih.biWidth = width;
    bih.biHeight = height;
    bih.biPlanes = 1;
    bih.biBitCount = 24; // 24 bits per pixel (RGB)
    bih.biCompression = 0;
    bih.biSizeImage = 0;
    bih.biXPelsPerMeter = 2835; // 72 DPI
    bih.biYPelsPerMeter = 2835; // 72 DPI
    bih.biClrUsed = 0;
    bih.biClrImportant = 0;

    // Open file for writing
    FILE *fp = fopen(filename, "wb");
    if (!fp) {
        perror("Unable to open file");
        return;
    }

    // Write the headers
    fwrite(&bfh, sizeof(BITMAPFILEHEADER), 1, fp);
    fwrite(&bih, sizeof(BITMAPINFOHEADER), 1, fp);

    // Write pixel data (simple gradient)
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            uint8_t color[3] = {x % 256, y % 256, (x + y) % 256}; // RGB
            fwrite(color, sizeof(uint8_t), 3, fp);
        }
        // Padding to the nearest 4-byte boundary
        for (int p = 0; p < (4 - (width * 3) % 4) % 4; p++) {
            fputc(0, fp);
        }
    }

    fclose(fp);
}

Step 3: Main Function to Generate an Image

Now, let's put everything together with a main function:

int main() {
    int width = 800;
    int height = 600;
    
    createBMP("output.bmp", width, height);
    
    printf("BMP image created: output.bmp\n");
    return 0;
}

Conclusion

Generating images in C can be a straightforward process, particularly with simple formats like BMP. This example showcases how to create a basic gradient image programmatically. You can build upon this knowledge to explore more complex graphics techniques and formats. Happy coding!

Popular Posts