0

I have a problem with my code which is generator of .bmp files without any library to generate ones.

Program generates a blank image, even with pixel data. I tried to change bytes, but i didn't work.

Any ideas? Thanks. Code in c++.

Code:

#include <iostream>
#include <fstream>
#include <stdio.h>

using namespace std;

#define BYTES_PER_PIXEL 3
#define FILE_HEADER_SIZE 14
#define INFO_HEADER_SIZE 40

struct BITMAPFILEHEADER {
    unsigned short bfType;
    unsigned int bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned int bfOffBits;
};
struct BITMAPINFOHEADER {
    unsigned int biSize;
    unsigned int biWidth;  
    unsigned int biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;  
    unsigned int biCompression;
    unsigned int biSizeImage;
    unsigned int biXPelsPerMeter;
    unsigned int biYPelsPerMeter;
    unsigned int biClrUsed;
    unsigned int biClrImportant;
};

struct RGB_data {
    unsigned char b;
    unsigned char g;
    unsigned char r;
};

int main() {
    size_t height = 100;
    size_t width = 50;
    size_t size = width * height * 3;
    //------------------------------------------------------------------------------
    FILE *file = fopen("./sample.bmp", "wb");
    //------------------------------------------------------------------------------
    BITMAPFILEHEADER bmfh;
    BITMAPINFOHEADER bmih;
    //------------------------------------------------------------------------------
    RGB_data buffer[height][width];
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            RGB_data data;
            data.b = 0;
            data.r = 0;
            data.b = 0;
            buffer[y][x] = data;
        }
    }
    //------------------------------------------------------------------------------
    bmfh.bfType = 0x4D42;
    bmfh.bfSize = size + FILE_HEADER_SIZE + INFO_HEADER_SIZE;
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = bmfh.bfSize - size;
    //------------------------------------------------------------------------------
    bmih.biSize = 40;
    bmih.biWidth = width;
    bmih.biHeight = height;
    bmih.biPlanes = 1;
    bmih.biBitCount = 24;
    bmih.biCompression = 0;
    bmih.biSizeImage = size;
    bmih.biXPelsPerMeter = 0;
    bmih.biYPelsPerMeter = 0;
    bmih.biClrUsed = 0;
    bmih.biClrImportant = 0;
    //------------------------------------------------------------------------------
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            buffer[y][x].b = 10; 
            buffer[y][x].r = 20;
            buffer[y][x].g = 30;  
        }
    }
    //------------------------------------------------------------------------------
    fwrite(&bmfh, 1, FILE_HEADER_SIZE, file);
    fwrite(&bmih, 1, INFO_HEADER_SIZE, file);
    fwrite(&buffer, 3, size, file);
    fclose(file);
    //------------------------------------------------------------------------------ 
    cout << "Image generated successfully!" << endl;
    return 0;
}

P.S. I checked data types which are correct. I also tried to change some varibales name, but i didn't work.

1 Answers1

0

You are not initializing g value in here

    data.b = 0;
    data.r = 0;
    data.b = 0;

And also include #pragma pack(push, 1) at the beginning of first struct and #pragma pack(pop) at the end of last struct

#include <iostream>
#include <fstream>
#include <stdio.h>

using namespace std;

#define BYTES_PER_PIXEL 3
#define FILE_HEADER_SIZE 14
#define INFO_HEADER_SIZE 40

#pragma pack(push, 1)

struct BITMAPFILEHEADER {
    unsigned short bfType;
    unsigned int bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned int bfOffBits;
};
struct BITMAPINFOHEADER {
    unsigned int biSize;
    unsigned int biWidth;  
    unsigned int biHeight;
    unsigned short biPlanes;
    unsigned short biBitCount;  
    unsigned int biCompression;
    unsigned int biSizeImage;
    unsigned int biXPelsPerMeter;
    unsigned int biYPelsPerMeter;
    unsigned int biClrUsed;
    unsigned int biClrImportant;
};

struct RGB_data {
    unsigned char b;
    unsigned char g;
    unsigned char r;
};

#pragma pack(pop)

int main() {
    size_t height = 100;
    size_t width = 50;
    size_t size = width * height * 3;
    //------------------------------------------------------------------------------
    FILE *file = fopen("./sample.bmp", "wb");
    //------------------------------------------------------------------------------
    BITMAPFILEHEADER bmfh;
    BITMAPINFOHEADER bmih;
    //------------------------------------------------------------------------------
    RGB_data buffer[height][width];
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            RGB_data data;
            data.b = 0;
            data.r = 0;
            data.b = 0;
            buffer[y][x] = data;
        }
    }
    //------------------------------------------------------------------------------
    bmfh.bfType = 0x4D42;
    bmfh.bfSize = size + FILE_HEADER_SIZE + INFO_HEADER_SIZE;
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfOffBits = bmfh.bfSize - size;
    //------------------------------------------------------------------------------
    bmih.biSize = 40;
    bmih.biWidth = width;
    bmih.biHeight = height;
    bmih.biPlanes = 1;
    bmih.biBitCount = 24;
    bmih.biCompression = 0;
    bmih.biSizeImage = size;
    bmih.biXPelsPerMeter = 0;
    bmih.biYPelsPerMeter = 0;
    bmih.biClrUsed = 0;
    bmih.biClrImportant = 0;
    //------------------------------------------------------------------------------
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            buffer[y][x].b = 10; 
            buffer[y][x].r = 20;
            buffer[y][x].g = 30;  
        }
    }
    //------------------------------------------------------------------------------
    fwrite(&bmfh, 1, FILE_HEADER_SIZE, file);
    fwrite(&bmih, 1, INFO_HEADER_SIZE, file);
    fwrite(&buffer, 3, size, file);
    fclose(file);
    //------------------------------------------------------------------------------ 
    cout << "Image generated successfully!" << endl;
    return 0;
}
Harry
  • 2,177
  • 1
  • 19
  • 33
  • I will try this. –  Nov 10 '20 at 14:47
  • check this link for more info https://stackoverflow.com/questions/3318410/pragma-pack-effect – Harry Nov 10 '20 at 14:53
  • There is still a way to write clean and portable code beyond any `#pragma pack` stuff though it might be a bit more tedious to implement it: [Create image from unsigned char buffer](https://stackoverflow.com/a/56054487/7478597). – Scheff's Cat Nov 10 '20 at 14:59
  • 1
    Marginally related but I suggest always checking file handles after calls to `fopen` or any os handles or resources. Will save you a lot of time someday. – systemcpro Nov 10 '20 at 15:04