0

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;
}
halfer
  • 19,824
  • 17
  • 99
  • 186
odbhut.shei.chhele
  • 5,834
  • 16
  • 69
  • 109
  • For one thing, why are you calling `free (...)` when `bitmapImage` is **0**? The C stdlib is smart enough not to do anything if you try this, but it still makes no sense. – Andon M. Coleman May 12 '14 at 00:00
  • http://stackoverflow.com/questions/14279242/read-bitmap-file-into-structure – odbhut.shei.chhele May 12 '14 at 00:12
  • i have used the code written in here @AndonM.Coleman – odbhut.shei.chhele May 12 '14 at 00:13
  • If I remove the free part then it gives me a segmentation error; – odbhut.shei.chhele May 12 '14 at 00:16
  • What OS is this on? Why are you trying to read a BMP manually? There are OS routines for reading in most image formats. You shouldn't write this code yourself. Also, this has nothing to do with OpenGL or C++, so I'm going to remove those tags. – user1118321 May 12 '14 at 00:16
  • I am using linux mint. what am I supposed to do? – odbhut.shei.chhele May 12 '14 at 00:17
  • can you atleast point me to the right direction? – odbhut.shei.chhele May 12 '14 at 00:18
  • Yeah... do not do that. There are too many really bad things in that code, like freeing a pointer that has the value **0** immediately after checking to see if its value is **0** (this is safe, but completely pointless). But more importantly, it needs to `return` on failure after calling `fclose (...)`; that code is a disaster waiting to happen. – Andon M. Coleman May 12 '14 at 00:19
  • Why is this tagged C? – Crowman May 12 '14 at 00:30
  • @PaulGriffiths: Since when does C++ have `fread (...)`, `free (...)`, etc? This is a mishmash of C++ and the C standard library. And as it turns out, all of the bad things that are happening in this code are a result of misusing the C standard library. – Andon M. Coleman May 12 '14 at 00:32
  • @AndonM.Coleman: C++ has always had those things. C has never had namespaces or the `new` operator, and fails to have them to this day. – Crowman May 12 '14 at 00:33
  • @PaulGriffiths: No, those things (`fread`, `free`, etc.) are part of the C standard library, not C++. Heck, they are technically not even a part of the C language if you want to get nitpicky. – Andon M. Coleman May 12 '14 at 00:34
  • @AndonM.Coleman: I'm not going to get into pointless arguments about whether C or C++ include their respective standard libraries. To the extent the language is defined by the standard, they are included, and that's good enough for me. And the C standard library, at least the bit that contains these here functions, is included in C++. – Crowman May 12 '14 at 00:37

3 Answers3

2

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;
}
Community
  • 1
  • 1
Andon M. Coleman
  • 42,359
  • 2
  • 81
  • 106
  • Thank you very much for your answer. But how am I going to get a value for bitmapInfoHeader->biSizeImage this variable. initially it is 0. so it is not reading anything and it is not entering the loop. – odbhut.shei.chhele May 12 '14 at 00:34
  • Well, I honestly do not see why you are allocating `BITMAPINFOHEADER` dynamically in this code. You never bother to free it before the program returns. Just declare it like you do `BITMAPFILEHEADER` and pass the address of the variable to `fread (...)`. – Andon M. Coleman May 12 '14 at 00:45
0

As mentioned in my comment, you should not be writing your own code to read in a .bmp file (unless it's for an assignment, or something like that). You say you're on mint linux, so you might try either FreeImage or ImageMagick. The code you're using doesn't handle index color images, for example, and probably a host of other things.

user1118321
  • 25,567
  • 4
  • 55
  • 86
0

that's how I load a BMP file of 24 bits per pixel, not for indexed colour bitmaps, download winbgim from here: http://www.mediafire.com/file/z9wnl0c70tiacqn/winbgim_DevCpp.zip/file, is in dev-c++, you probably have to load a couple of parameters for the linker, the path is: project, project options, parameters, and write: -lbgi -lgdi32 -luser32 -lcomdlg32 -luuid -loleaut32 -lole32 -mwindows -lwinmm, one thing more, after installing winbgim, go to dev c and create new project as console graphics application, this item must be in the project list if winbgim is properly installed, I wrote "write to shared memory", because I wrote the file also in memory although I did not access the file this way, but from the same file

 #include <winbgim.h>
 #include <string.h>
 #include<windows.h>
 #include<stdio.h>
 #include <stdlib.h>

 const char *Filename;

 BITMAPFILEHEADER FileHeader;
 BITMAPINFOHEADER InfoHeader;
 int k;
 typedef struct{
 BYTE colorr;
 BYTE colorg;
 BYTE colorb;
 }cine;

 cine color;

 HANDLE hArch, hProy;
 LPSTR base,puntero;
 DWORD tam;
 int main()
 {
 int gdriver=9;
 int gmode=2;
 // initgraph(&gdriver,&gmode, "");
 cleardevice();

 UnmapViewOfFile(base);
 CloseHandle(hProy);
 CloseHandle(hArch);
 char *p;
 char *base;
 DWORD buf;
 Filename="D:\\music\\IMSLP00795-BWV0971\\01.bmp";
 int gd = DETECT, gm;
 int x = 320, y = 240, radius;
 k=0;

 int i;
 int j;




 FILE *File=NULL;
 if(!Filename)
 {
 MessageBox(NULL,"Konnte Filename nicht  finden!","Error",MB_OK|MB_ICONERROR);
 }
 else
 {
 File=fopen("D:\\music\\IMSLP00795-BWV0971\\01.bmp","rb");
 }

 fread(&FileHeader,sizeof(BITMAPFILEHEADER),1,File);
 if(FileHeader.bfType != 0x4D42)
 {
 MessageBox(NULL,"Ungültiges Bildformat!","Error",MB_OK|MB_ICONERROR);
 exit(1); 
 }
 printf("tamaño total del archivo %d\n",FileHeader.bfSize);
 printf("comienzo del mapa de bits (imagen en pixels) en bits         %d\n",FileHeader.bfOffBits);

 buf=FileHeader.bfOffBits/8; //offset from the begining of BMP file (pixel array)
 printf("comienzo del mapa de bits en bytes desde el origen del archivo      %d\n",buf);
 fread(&InfoHeader,sizeof(BITMAPINFOHEADER),1,File);

 printf("horizontal resolution in pixels por metro %li\n",InfoHeader.biWidth);
 printf("vertical resolution in pixels por metro %li\n",InfoHeader.biHeight);
 printf("numero de bits por pixel %d", InfoHeader.biBitCount);
 initwindow(InfoHeader.biWidth,InfoHeader.biHeight);


 hArch = CreateFile("D:\\music\\IMSLP00795-BWV0971\\01.bmp", /* file  name */
 GENERIC_ALL , /* read/write access */
 0, /* no sharing of the file */
 NULL, /* default security */
 OPEN_ALWAYS, /* open new or existing file */
 FILE_ATTRIBUTE_NORMAL, /* routine file attributes */
 NULL); /* no file template */
 if (hArch==INVALID_HANDLE_VALUE){

 fprintf(stderr,"no puede abrirse el archivo");

 }

 hProy = CreateFileMapping(hArch, /* file handle */
 NULL, /* default security */
 PAGE_READWRITE, /* read/write access to mapped pages */
 0, /* map entire file */
 0,
 TEXT("SharedObject")); /* named shared memory object */

 /* write to shared memory */
 base=(LPSTR)MapViewOfFile(hProy,FILE_MAP_ALL_ACCESS,0,0,0);
 tam=GetFileSize(hArch,NULL);
 int cont=0;
 puntero=base;
 p=base+FileHeader.bfOffBits;
 k=0;int t=0,v,l;
 fseek(File,FileHeader.bfOffBits,SEEK_SET );
 int read=0,read2=0;
 k=0;
 for( i=0; i<InfoHeader.biWidth; i++ ) {
       fread(&color,sizeof(cine),1,File);
        read += sizeof(cine);
        printf( "Pixel %d: %3d %3d %3d\n", i+1, int(color.colorb),         int(color.colorg), int(color.colorr) );
    }
    if( read % 4 != 0 ) {
        read2 = 4 - (read%4);
        printf( "Padding: %d bytes\n", read2 );
        //fread( &color, read2, 1, File );

    }
    fseek(File,FileHeader.bfOffBits,SEEK_SET );
    for (i=0;i<InfoHeader.biHeight;i++)
 for(j=0;j<InfoHeader.biWidth ;j++)

{
 fread(&color,sizeof(cine),1,File);

 putpixel(j,InfoHeader.biHeight-  i,COLOR(int(color.colorb),int(color.colorg),int(color.colorr)));
 if(j==InfoHeader.biWidth-1&&read2!=0)fseek(File,read2,SEEK_CUR);
} 
 fclose(File);

 UnmapViewOfFile(base);
 CloseHandle(hProy);
 CloseHandle(hArch);
 getch();
}