how to create bitmap in C and compile with gcc

i decided to learn C, and i try to follow this tutorial http://ricardolovelace.com/creating-bitmap-images-with-c-on-windows.html

but when i try to compile my code with gcc as this >gcc -Wall testc o app

he doesn't know type_rgb, can i define this type and how? and where in my code ?

#include <stdio.h>


struct rgb_data {
  float r, g, b;
};

void save_bitmap( const char *file_name, int width, int height, int dpi, type_rgb  *pixel_data); 
/*
 next steps of the tutorial
*/

rgb_data *pixels = new rgb_data[width * height];

for( int x = 0; x < width; x++)
  {
    for(int y = 0; y < height; y++)
        int a = y * width +x; 
          {

            if ((x > 50 && x < 350) && (y > y && y < 350))
              {
                pixels[a].r = 255;
                pixels[a].g = 255;
                pixels[a].b = 0;
              }else{
                pixels[a].r = 55;
                pixels[a].g = 55;
                pixels[a].b = 55;
              }

     }
}

save_bitmap("black_border.bmp", width, height, dpi, pixels);

Upvotes: 2

Views: 7957

Answers (1)

Barmak Shemirani
Barmak Shemirani

Reputation: 31599

Bitmap file format is rather complicated. This is not the best way to learn C. It's better to start with something much simpler.

Having said that, the bitmap format starts with a bitmap header BITMAPFILEHEADER structure which is 14 bytes long, followed by BITMAPINFOHEADER structure 40 bytes long. These structures are defined in "Windows.h"

You have to write in various information in these structures and write them to file before writing the actual pixels.

You can have 1, 4, 8, 16, 24, and 32-bit bitmap. This is an example to read a 32-bit bitmap. This code assumes sizeof(short) is 2, sizeof(int) is 4.

int main()
{
    int row, column;
    int width = 100;
    int height = 100;
    int size = width * height * 4; //for 32-bit bitmap only

    char header[54] = { 0 };
    strcpy(header, "BM");
    memset(&header[2],  (int)(54 + size), 1);
    memset(&header[10], (int)54, 1);//always 54
    memset(&header[14], (int)40, 1);//always 40
    memset(&header[18], (int)width, 1);
    memset(&header[22], (int)height, 1);
    memset(&header[26], (short)1, 1);
    memset(&header[28], (short)32, 1);//32bit
    memset(&header[34], (int)size, 1);//pixel size

    unsigned char *pixels = malloc(size);
    for(row = height - 1; row >= 0; row--) {
        for(column = 0; column < width; column++) {
            int p = (row * width + column) * 4;
            pixels[p + 0] = 64; //blue
            pixels[p + 1] = 128;//green
            pixels[p + 2] = 192;//red
        }
    }

    FILE *fout = fopen("32bit.bmp", "wb");
    fwrite(header, 1, 54, fout);
    fwrite(pixels, 1, size, fout);
    free(pixels);
    fclose(fout);
    return 0;
}

Note the first pixel is blue, followed by green and read. The last pixel is not used in 32-bit bitmap. Also the height goes from bottom to top. This is another odd feature of bitmap. 24-bit bitmaps are more complicated because they need padding. 8-bit and lower will need an additional palette.

struct rgb_data {
  float r, g, b;
};

float is not the right type for pixels. Each color goes from 0 to 255. This fits in unsigned char. You need instead

struct rgb_data {
  unsigned r, g, b, alpha;
};

The alpha is the extra byte for 32-bit bitmap (which we won't use). Notice the size of this structure is 4. You can allocate this as

struct rgb_data *rgb = malloc(size);

Now you can access the pixels as follows:

int p = (row * width + column);
rgb[p].r = 255;
rgb[p].g = 0;
rgb[p].b = 0;
...
fwrite(rgb, 4, width * height, fout);

Upvotes: 7

Related Questions