Search code examples
c++openglglutbmp

I am unable to load a .BMP image


I am new to opengl. I am trying to load an image using opengl. But I am unable to do so. It gives me this error:

*** Error in `./lena': double free or corruption (top) : 0x0000000001353070 ***

I don't know what I am doing wrong. My code has been given below. Actually it is not my code. I have seen it in another post in Stack Overflow by someone named Ollo.

#include <bits/stdc++.h>
#include <GL/glut.h>

using namespace std;

struct BITMAPFILEHEADER
{
    int bfType;  //specifies the file type
    long long bfSize;  //specifies the size in bytes of the bitmap file
    int bfReserved1;  //reserved; must be 0
    int bfReserved2;  //reserved; must be 0
    long long bOffBits;  //species the offset in bytes from the bitmapfileheader to the bitmap bits
};

struct BITMAPINFOHEADER
{
    long long biSize;  //specifies the number of bytes required by the struct
    long long biWidth;  //specifies width in pixels
    long long biHeight;  //species height in pixels
    int biPlanes; //specifies the number of color planes, must be 1
    int biBitCount; //specifies the number of bit per pixel
    long long biCompression;//spcifies the type of compression
    long long biSizeImage;  //size of image in bytes
    long long biXPelsPerMeter;  //number of pixels per meter in x axis
    long long biYPelsPerMeter;  //number of pixels per meter in y axis
    long long biClrUsed;  //number of colors used by th ebitmap
    long long biClrImportant;  //number of colors that are important
};

int main(void){
    FILE *filePtr;
    BITMAPFILEHEADER bitmapFileHeader;
    BITMAPINFOHEADER *bitmapInfoHeader = new BITMAPINFOHEADER;
    unsigned char *bitmapImage;  //store image data
    int imageIdx=0;  //image index counter
    unsigned char tempRGB;  //our swap variable

    filePtr = fopen("lena.bmp","rb");
    if (filePtr == NULL)
        cout << "ERROR!!! 1" << endl;
    fread(&bitmapFileHeader, sizeof(BITMAPFILEHEADER),1,filePtr);

    fread(bitmapInfoHeader, sizeof(BITMAPINFOHEADER),1,filePtr); // small edit. forgot to add the closing bracket at sizeof

    //move file point to the begging of bitmap data
    fseek(filePtr, bitmapFileHeader.bOffBits, SEEK_SET);

    //allocate enough memory for the bitmap image data
    bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);

    //verify memory allocation
    if (!bitmapImage)
    {
        free(bitmapImage);
        fclose(filePtr);
    }

    //read in the bitmap image data
    fread(bitmapImage, bitmapInfoHeader->biSizeImage, 1, filePtr);

    //make sure bitmap image data was read
    if (bitmapImage == NULL)
    {
        fclose(filePtr);
    }

    //swap the r and b values to get RGB (bitmap is BGR)
    for (imageIdx = 0;imageIdx < bitmapInfoHeader->biSizeImage;imageIdx+=3)
    {
        tempRGB = bitmapImage[imageIdx];
        bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
        bitmapImage[imageIdx + 2] = tempRGB;
    }

    return 0;
}

Solution

  • This code that you got from another answer on StackOverflow has some awkward issues.

    1. It checks to see if bitmapImage is 0 and if it is, it immediately calls free (...) on bitmapImage
    2. It needs to return on failure in order to prevent crashing.
    3. fread (...) does not change whether or not bitmapImage is NULL

    Here are some minimum changes that you need to make:

    if (filePtr == NULL) {
        cout << "ERROR!!! 1" << endl;
        return -1; // FAILURE, so return!
    }
    
    [...]
    
    //allocate enough memory for the bitmap image data
    bitmapImage = (unsigned char*)malloc(bitmapInfoHeader->biSizeImage);
    
    //verify memory allocation
    if (!bitmapImage)
    {
        //free(bitmapImage); // This does not belong here!
        fclose(filePtr);
        return -2; // FAILURE, so return!
    }
    
    //read in the bitmap image data
    fread(bitmapImage, bitmapInfoHeader->biSizeImage, 1, filePtr);
    
    // THIS IS POINTLESS TOO, fread (...) is not going to change the address of
    //                          bitmapImage.
    /*
    //make sure bitmap image data was read
    if (bitmapImage == NULL)
    {
        fclose(filePtr);
    }
    */
    
    //swap the r and b values to get RGB (bitmap is BGR)
    for (imageIdx = 0;imageIdx < bitmapInfoHeader->biSizeImage;imageIdx+=3)
    {
        tempRGB = bitmapImage[imageIdx];
        bitmapImage[imageIdx] = bitmapImage[imageIdx + 2];
        bitmapImage[imageIdx + 2] = tempRGB;
    }