【问题标题】:I am unable to load a .BMP image我无法加载 .BMP 图像
【发布时间】:2026-01-01 07:05:01
【问题描述】:

我是opengl的新手。我正在尝试使用 opengl 加载图像。但我无法这样做。它给了我这个错误:

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

我不知道我做错了什么。我的代码已在下面给出。实际上这不是我的代码。我在另一个名叫 Ollo 的人的 Stack Overflow 帖子中看到了它。

#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;
}

【问题讨论】:

  • 一方面,当bitmapImage0 时,你为什么要调用free (...)?如果你尝试这个,C 标准库足够聪明,不会做任何事情,但它仍然没有任何意义。
  • 我已经使用了这里写的代码@AndonM.Coleman
  • 如果我删除了空闲部分,那么它会给我一个分段错误;
  • 这是什么操作系统?为什么要手动读取 BMP?有用于读取大多数图像格式的操作系统例程。您不应该自己编写此代码。另外,这与OpenGL或C++无关,所以我要删除那些标签。

标签: c++ graphics


【解决方案1】:

您从 * 上的 another answer 获得的这段代码存在一些尴尬的问题。

  1. 它检查bitmapImage 是否为0,如果是,它立即在bitmapImage 上调用free (...)
  2. 它需要在失败时返回以防止崩溃。
  3. 无论bitmapImage 是否为NULLfread (...) 都不会改变

以下是您需要进行的一些最低限度的更改:

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;
}

【讨论】:

  • 非常感谢您的回答。但是我将如何获得 bitmapInfoHeader->biSizeImage 这个变量的值。最初它是 0。所以它没有读取任何内容,也没有进入循环。
  • 好吧,老实说,我不明白你为什么在这段代码中动态分配BITMAPINFOHEADER。在程序返回之前,您永远不会费心释放它。只需像 BITMAPFILEHEADER 一样声明它并将变量的地址传递给 fread (...)
【解决方案2】:

正如我在评论中提到的,您不应该编写自己的代码来读取 .bmp 文件(除非它用于分配或类似的事情)。你说你在 mint linux 上,所以你可以试试FreeImageImageMagick。例如,您使用的代码不处理索引彩色图像,可能还有许多其他的东西。

【讨论】:

    【解决方案3】:

    这就是我如何加载每像素 24 位的 BMP 文件,而不是用于索引颜色位图,从这里下载 winbgim:http://www.mediafire.com/file/z9wnl0c70tiacqn/winbgim_DevCpp.zip/file,在 dev-c++ 中,您可能需要为链接器加载几个参数,路径是:项目,项目选项,参数,然后写:-lbgi -lgdi32 -luser32 -lcomdlg32 -luuid -loleaut32 -lole32 -mwindows -lwinmm,还有一件事,安装winbgim后,进入dev c并创建新项目为控制台图形应用程序,如果正确安装了winbgim,此项必须在项目列表中, 我写了“写入共享内存”,因为我也将文件写在内存中,虽然我没有以这种方式访问​​文件,而是从同一个文件中访问

     #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();
    }
    

    【讨论】:

      最近更新 更多