现在的位置: 首页 > 综合 > 正文

c语言读取bmp文件格式(转载)

2013年03月09日 ⁄ 综合 ⁄ 共 5647字 ⁄ 字号 评论关闭

转自http://topameng.spaces.live.com/blog/cns!F962D4854A8233D!325.entry

c语言读取bmp文件格式

//BMP 头
typedef struct
{
    char id[2];                                   //bmp 文件标志 "BM"
    unsigned long fileSize;                    //文件大小
    unsigned long reserved0;
    unsigned long bitmapDataOffset;
    unsigned long bitmapHeaderSize;
    unsigned long width;                    //图像宽度
    unsigned long height;                   //图像高度
    unsigned short planes;
    unsigned short bitsPerPixel;            //每个像素站多少位
    unsigned long compression;            //是否压缩
    unsigned long bitmapDataSize;
    unsigned long hRes;
    unsigned long vRes;
    unsigned long colors;
    unsigned long importantColors;
    unsigned char palette[256][4];      //调色板数据,24位及以上像素没有该数据
} BMPHeader_t;

long GetFileSize(FILE* f)
{
    long pos = ftell(f);
    fseek(f,0,SEEK_END);
    long len = ftell(f);
    fseek(f,pos,SEEK_SET);
    return len;
}

void __stdcall Com_Error(const char *fmt, ... )
{
    char    com_errorMessage[4096];
    va_list        argptr;

    va_start (argptr,fmt);
    vsprintf (com_errorMessage,fmt,argptr);
    va_end (argptr);

    MessageBox(NULL,com_errorMessage,"错误提示",MB_ICONERROR);
}

//*pic 返回 RGBA 类型像素数据,width 返回修正后的宽度,height返回高度
// name 输入的文件名称
bool LoadBMP( const char *name, byte **pic, int *width, int *height )
{
    int        columns, rows, numPixels;
    byte    *pixbuf;
    int        row, column;
    byte    *buf_p;
    byte    *buffer;
    int        length;
    BMPHeader_t bmpHeader;
    byte        *bmpRGBA;
    *pic = NULL;
    // load the file
    FILE* pfile = fopen(name,"rb");
    if(pfile == NULL)
    {
        Com_Error( "LoadBMP: Load BMP files failed (%s)/n", name );
        return false;
    }
    length = GetFileSize(pfile);
    buffer = (byte*) malloc(length*sizeof(byte));
    fread(buffer,1,length,pfile);
    if (!buffer)
    {
        Com_Error( "LoadBMP: Memory alloc failed (%s)/n", name );
        return false;
    }

    buf_p = buffer;

    bmpHeader.id[0] = *buf_p++;
    bmpHeader.id[1] = *buf_p++;
    bmpHeader.fileSize = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.reserved0 = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.bitmapDataOffset = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.bitmapHeaderSize = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.width = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.height = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.planes = ( * ( short * ) buf_p );
    buf_p += 2;
    bmpHeader.bitsPerPixel = ( * ( short * ) buf_p );
    buf_p += 2;
    bmpHeader.compression = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.bitmapDataSize = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.hRes = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.vRes = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.colors = ( * ( long * ) buf_p );
    buf_p += 4;
    bmpHeader.importantColors = ( * ( long * ) buf_p );
    buf_p += 4;

    memcpy( bmpHeader.palette, buf_p, sizeof( bmpHeader.palette ) );

    if ( bmpHeader.bitsPerPixel == 8 )
        buf_p += 1024;

    if ( bmpHeader.id[0] != 'B' && bmpHeader.id[1] != 'M' )
    {
        Com_Error( "LoadBMP: only Windows-style BMP files supported (%s)/n", name );
        return false;
    }
    if ( bmpHeader.fileSize != length )
    {
        Com_Error("LoadBMP: header size does not match file size (%d vs. %d) (%s)/n", bmpHeader.fileSize, length, name );
        return false;
    }
    if ( bmpHeader.compression != 0 )
    {
        Com_Error("LoadBMP: only uncompressed BMP files supported (%s)/n", name );
        return false;
    }
    if ( bmpHeader.bitsPerPixel < 8 )
    {
        Com_Error("LoadBMP: monochrome and 4-bit BMP files not supported (%s)/n", name );
        return false;
    }

    columns = bmpHeader.width;
    rows = bmpHeader.height;

    if(bmpHeader.bitsPerPixel == 24 )
    {
        if( (columns & 3) != 0)                    //检查宽度是否为4倍数
           columns = (columns & ~3) + 4;    //修正位图宽度值,对齐到4的倍数,不然图像会变形  
    }

    if ( rows < 0 )
        rows = -rows;
    numPixels = columns * rows;

    if ( width )
        *width = columns;
    if ( height )
        *height = rows;

    bmpRGBA = (byte*)malloc( numPixels * 4 );
    *pic = bmpRGBA;
    buf_p = buffer+54;

    for ( row = rows-1; row >= 0; row--)
    {
        pixbuf = bmpRGBA + row*columns*4;

        for ( column = 0; column < columns; column++ )
        {
            unsigned char red, green, blue, alpha;
            int palIndex;
            unsigned short shortPixel;

            switch ( bmpHeader.bitsPerPixel )
            {
            case 8:
                palIndex = *buf_p++;
                *pixbuf++ = bmpHeader.palette[palIndex][2];
                *pixbuf++ = bmpHeader.palette[palIndex][1];
                *pixbuf++ = bmpHeader.palette[palIndex][0];
                *pixbuf++ = 0xff;
                break;
            case 16:
                shortPixel = * ( unsigned short * ) pixbuf;
                pixbuf += 2;
                *pixbuf++ = ( shortPixel & ( 31 << 10 ) ) >> 7;
                *pixbuf++ = ( shortPixel & ( 31 << 5 ) ) >> 2;
                *pixbuf++ = ( shortPixel & ( 31 ) ) << 3;
                *pixbuf++ = 0xff;
                break;

            case 24:
                blue = *buf_p++;
                green = *buf_p++;
                red = *buf_p++;
                *pixbuf++ = red;
                *pixbuf++ = green;
                *pixbuf++ = blue;
                *pixbuf++ = 255;
                break;
            case 32:
                blue = *buf_p++;
                green = *buf_p++;
                red = *buf_p++;
                alpha = *buf_p++;
                *pixbuf++ = red;
                *pixbuf++ = green;
                *pixbuf++ = blue;
                *pixbuf++ = alpha;
                break;
            default:
                Com_Error("LoadBMP: illegal pixel_size '%d' in file '%s'/n", bmpHeader.bitsPerPixel, name );
                return false;
            }
        }
    }

    free(buffer);
    fclose(pfile);
    return true;
}
//注意bmp文件是由左到右, 由下到上的循序存储的像素.每个像素颜色顺序为B G R (A)
//BMP的行象素是4字节对齐的,不足的补0,比如有个图像每行宽度是63象素,
//BMP文件存储时会每行存储64个字节,最后一个字节用0补齐

void CDlg::OnPaint()   //测试图像
{
CPaintDC dc(this);
static byte* pic = NULL;
static int w,h;
if(pic == NULL)
{
    char spath[MAX_PATH];
    _getcwd(spath, 200);
    strcat(spath,"//res//b0000.bmp");
    LoadBMP(spath,&pic,&w,&h);
}
int i,j;
for(j=0;j<h;j++)
{
    for(i=0;i<w;i++)
    {            
        SetPixel(dc,i,j,RGB(pic[0],pic[1],pic[2]));
        pic += 4;
    }
}
}

 

抱歉!评论已关闭.