您的位置:首页 > 其它

VC下2、4、8、16、24、32位位图的数据解析与显示

2017-05-14 18:15 316 查看
在VC中,位图显示一般有现成的方式,如使用picture控件、GetDC()->StretchBlt、::BitBlt等,但这些方式都是高层的封装,让你不清楚一副位图是如何解析并显示到DC上的。实际应用中,比如图像处理,视频显示等,需要操作到位图中的像素,这需要弄明白位图文件如何组成,网上有太多的位图文件格式说明,下面借助实例和SetPixel函数完成解析与显示。

读入一幅位图,结合位图文档说明,按着F5、F10把程序走一遍,你就会把位图弄的明明白白。

源码打包放在:http://download.csdn.net/detail/dijkstar/7014189

[cpp]
view plain
copy





void CTestDlg::OnButton1()   
{  
    //读入位图文件名  
    char *filename = "720bmp16.bmp";  
    CDC *pDC = GetDC();  
  
    //  
    // 一次性将位图文件读入到内容中,待处理  
    //  
    CFile f;  
    f.Open(filename, CFile::modeRead);  
    char* buff = (char*)malloc(f.GetLength());  
    f.SeekToBegin();  
    f.Read(buff, f.GetLength());  
      
    //  
    BITMAPFILEHEADER    *fileheader = NULL; //数据结构大小为14  
    BITMAPINFO          *info = NULL;       //数据结构大小为40  
  
    fileheader = (BITMAPFILEHEADER*)buff;  
  
    if(fileheader->bfType!=0x4D42)  
    {  
        AfxMessageBox("不是BMP文件");  
        f.Close();  
        return ;  
    }  
  
    //位图信息区域,在偏移14处  
    info = (BITMAPINFO*)(buff+(sizeof(BITMAPFILEHEADER)));  
  
  
    //位图的宽和高  
    int width = info->bmiHeader.biWidth;  
    int height= info->bmiHeader.biHeight;  
  
    //指向位图像素区域  
    char* buffer = buff+fileheader->bfOffBits;  
  
    //  
    //  显示位图的一些基本信息  
    //  
    CString str;  
    str.Format("位图大小= %d\n"  
                "位图数据起始偏移 = %d\n"  
                "BITMAPINFOHEADER.biSize = %d\n"  
                "宽=%d, 高=%d\n"  
                "颜色位数=%d\n"  
                "压缩=%d\n"  
                "biSizeImage=%d\n"  
                "biClrUsed=%d\n"  
                "biClrImportant=%d",  
  
  
                fileheader->bfSize,      //位图大小  
                fileheader->bfOffBits,   //位图数据起始偏移  
                info->bmiHeader.biSize,  
                info->bmiHeader.biWidth,  
                info->bmiHeader.biHeight,  
                info->bmiHeader.biBitCount,  
                info->bmiHeader.biCompression,  
                info->bmiHeader.biSizeImage,  
                info->bmiHeader.biClrUsed,  
                info->bmiHeader.biClrImportant  
  
        );  
    AfxMessageBox(str);  
  
    int i,j;  
    //  
    // 单色图的解析  
    //  
    if(info->bmiHeader.biBitCount==1)  
    {  
        int n=0;  
        int color[500][500];  
  
        if(height>0)  
        {  
            //height>0 表示图片颠倒  
            for(i=0; i<height; i++)  
                for(j=0; j<width; j=j+8)  
                {  
                    int k=7;  
                    while(k>=0)  
                    {  
                        color[i][k+j]=buffer
%2;  
                        buffer
=buffer
/2;  
                        k--;  
                    }  
                    n++;  
                }  
  
            for(i=0; i<height; i++)  
                for(j=0; j<width; j++)  
                {  
                    if(color[i][j] == 0)  
                    {  
                        pDC->SetPixel(j,height-i,RGB(0,0,0));  
                    }  
                    if(color[i][j] == 1)  
                    {  
                        pDC->SetPixel(j,height-i,RGB(255,255,255));  
                    }  
                }  
        }  
        else  
        {  
            for(i=0; i<0-height; i++)  
                for(j=0; j<width; j=j+8)  
                {  
                    int k=7;  
                    while(k>=0)  
                    {  
                        color[i][k+j]=buffer
%2;  
                        buffer
=buffer
/2;  
                        k--;  
                    }  
                    n++;  
                }  
  
            for(i=0; i<0-height; i++)  
                for(j=0; j<width; j++)  
                {  
                    if(color[i][j] == 0)  
                    {  
                        pDC->SetPixel(j,i,RGB(0,0,0));  
                    }  
                    if(color[i][j] == 1)  
                    {  
                        pDC->SetPixel(j,i,RGB(255,255,255));  
                    }  
                }  
        }  
    }  
    //  
    // 16色图的解析  
    //  
    else if(info->bmiHeader.biBitCount==4)  
    {  
        int pitch;  
        if(width%8==0)  
            pitch=width;  
        else  
            pitch=width+8-width%8;  
  
        //调色板数据  
        RGBQUAD quad[16];  
        memcpy(quad, buff+fileheader->bfOffBits-sizeof(quad), sizeof(quad));  
  
        //指向真正的像素数据  
        buffer = buff+fileheader->bfOffBits;  
  
        if(height>0)  
        {  
            //height>0 表示图片颠倒  
            for(i=0; i<height; i++)  
                for(j=0; j<width; j++)  
                {  
                    int index;  
                    if(j%2==0)  
                        index = buffer[(i*pitch+j)/2]/16;  
                  
                    if(j%2==1)  
                        index = buffer[(i*pitch+j)/2]%16;  
  
                    unsigned char r=quad[index].rgbRed;  
                    unsigned char g=quad[index].rgbGreen;  
                    unsigned char b=quad[index].rgbBlue;  
                    pDC->SetPixel(j,height-i,RGB(r,g,b));  
                }  
        }  
        else  
        {  
            for(i=0; i<0-height; i++)  
                for(j=0; j<width; j++)  
                {  
                    int index;  
                    if(j%2==0)  
                        index = buffer[(i*pitch+j)/2]/16;  
                  
                    if(j%2==1)  
                        index = buffer[(i*pitch+j)/2]%16;  
  
                    unsigned char r=quad[index].rgbRed;  
                    unsigned char g=quad[index].rgbGreen;  
                    unsigned char b=quad[index].rgbBlue;  
                    pDC->SetPixel(j,i,RGB(r,g,b));  
                }  
        }  
    }  
    //  
    // 256色(8位)图的解析  
    //  
    else if(info->bmiHeader.biBitCount==8)  
    {  
        int pitch;  
        if(width%4==0)  
        {  
            pitch=width;  
        }  
        else  
        {  
            pitch=width+4-width%4;  
        }  
  
        //8位位图,有调试板数据  
        RGBQUAD quad[256] = {0};  
        memcpy(quad, buff+fileheader->bfOffBits-sizeof(quad), sizeof(quad));  
  
        //  指向像素数据的起始偏移(其实并不是像素,8位位图的“像素”值代入调色板的下标,  
        //      得到的值才是真正的像素)  
        buffer = buff+fileheader->bfOffBits;  
  
        //显示  
        if(height>0)  
        {  
            //height>0 表示图片颠倒  
            for(int i=0;i<height;i++)  
            {  
                for(int j=0;j<width;j++)  
                {  
                    int index=buffer[i*pitch+j];  
                    UCHAR r=quad[index].rgbRed;  
                    UCHAR g=quad[index].rgbGreen;  
                    UCHAR b=quad[index].rgbBlue;  
                    pDC->SetPixel(j, height-i, RGB(r,g,b));  
                }  
            }  
        }  
        else  
        {  
            for(int i=0;i<0-height;i++)  
            {  
                for(int j=0;j<width;j++)  
                {  
                    int index=buffer[i*pitch+j];  
                    UCHAR r=quad[index].rgbRed;  
                    UCHAR g=quad[index].rgbGreen;  
                    UCHAR b=quad[index].rgbBlue;  
                    pDC->SetPixel(j,i,RGB(r,g,b));  
                }  
            }  
        }  
    }  
  
    //  
    // 65536色(16位)图解析  
    //  
    else if(info->bmiHeader.biBitCount==16)  
    {  
        int pitch=width+width%2;  
  
        if(height>0)  
        {  
            //height>0 表示图片颠倒  
            if(info->bmiHeader.biCompression==BI_RGB)  
            {  
                //该模式只有555  
                for(int i=0;i<height;i++)  
                {  
                    for(int j=0;j<width;j++)  
                    {  
                        // 555 格式  
                        unsigned char b=buffer[(i*pitch+j)*2]&0x1F;  
                        unsigned char g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);  
                        unsigned char r=(buffer[(i*pitch+j)*2+1]<<1)>>3;  
                        pDC->SetPixel(j,height-i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));  
                    }  
                }  
            }  
  
            if(info->bmiHeader.biCompression==BI_BITFIELDS)  
            {  
                //该模式在bitmapinfoheader之后存在RGB掩码 每个掩码1 DWORD  
                //fseek(fp,fileheader.bfOffBits-sizeof(DWORD )*3,0);  
                DWORD  rMask;  
                //fread(&rMask,sizeof(DWORD ),1,fp);  
                memcpy(&rMask, buff+fileheader->bfOffBits-sizeof(DWORD )*3, sizeof(DWORD ));  
                if(rMask==0x7C00)  
                {  
                    // 5 5 5 格式  
                    //MessageBeep(0);  
                    for(int i=0;i<height;i++)  
                    {  
                        for(int j=0;j<width;j++)  
                        {  
                            unsigned char b=buffer[(i*pitch+j)*2]&0x1F;  
                            unsigned char g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);  
                            unsigned char r=(buffer[(i*pitch+j)*2+1]<<1)>>3;  
                            pDC->SetPixel(j,height-i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));  
                        }  
                    }  
                }  
  
                if(rMask==0xF800)  
                {  
                    //5 6 5 格式  
                    for(int i=0;i<height;i++)  
                    {  
                        for(int j=0;j<width;j++)  
                        {  
                            UCHAR b=buffer[(i*pitch+j)*2]&0x1F;  
                            UCHAR g=(((buffer[(i*pitch+j)*2+1]<<5)&0xFF)>>2)+(buffer[(i*pitch+j)*2]>>5);  
                            UCHAR r=buffer[(i*pitch+j)*2+1]>>3;  
                            pDC->SetPixel(j,height-i,RGB(r*0xFF/0x1F,g*0xFF/0x3F,b*0xFF/0x1F));  
                        }  
                    }  
                }  
            }  
  
        }  
        else  
        {  
            if(info->bmiHeader.biCompression==BI_RGB)  
            {  
                //该模式只有555  
                for(int i=0;i<0-height;i++){  
                    for(int j=0;j<width;j++){              
                        //5 5 5 格式  
                        UCHAR b=buffer[(i*pitch+j)*2]&0x1F;  
                        UCHAR g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);  
                        UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;  
                        pDC->SetPixel(j,i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));  
                    }  
                }  
            }  
  
            if(info->bmiHeader.biCompression==BI_BITFIELDS)  
            {  
                //该模式在bitmapinfoheader之后存在RGB掩码 每个掩码1 DWORD  
                //fseek(fp,fileheader.bfOffBits-sizeof(DWORD )*3,0);  
                DWORD  rMask;  
                //fread(&rMask,sizeof(DWORD ),1,fp);  
                memcpy(&rMask, buff+fileheader->bfOffBits-sizeof(DWORD )*3, sizeof(DWORD ));  
                if(rMask==0x7C00)  
                {  
                    // 5 5 5 格式  
                    MessageBeep(0);  
                    for(int i=0;i<0-height;i++)  
                    {  
                        for(int j=0;j<width;j++)  
                        {  
                            UCHAR b=buffer[(i*pitch+j)*2]&0x1F;  
                            UCHAR g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);  
                            UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;  
                            pDC->SetPixel(j,i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));  
                        }  
                    }  
                }  
  
                if(rMask==0xF800)  
                {  
                    //565 格式  
                    for(int i=0;i<0-height;i++)  
                    {  
                        for(int j=0;j<width;j++)  
                        {  
                            UCHAR b=buffer[(i*pitch+j)*2]&0x1F;  
                            UCHAR g=(((buffer[(i*pitch+j)*2+1]<<5)&0xFF)>>2)+(buffer[(i*pitch+j)*2]>>5);  
                            UCHAR r=buffer[(i*pitch+j)*2+1]>>3;  
                            pDC->SetPixel(j,i,RGB(r*0xFF/0x1F,g*0xFF/0x3F,b*0xFF/0x1F));  
                        }  
                    }  
                }  
            }  
        }  
    }  
    //  
    // 24位图解析  
    //  
    else if(info->bmiHeader.biBitCount==24)  
    {  
        int pitch=width%4;  
        // bgr  
        int i,j;  
        if(height>0)  
        {  
            //height>0 表示图片颠倒              
            for(i=0;i<height;i++)  
            {  
                int realPitch=i*pitch;  
                for(j=0;j<width;j++)  
                {  
                    unsigned char b=buffer[(i*width+j)*3+realPitch];  
                    unsigned char g=buffer[(i*width+j)*3+1+realPitch];  
                    unsigned char r=buffer[(i*width+j)*3+2+realPitch];  
                    pDC->SetPixel(j,height-i,RGB(r,g,b));  
                }  
            }  
        }  
        else  
        {  
            for(i=0;i<0-height;i++)  
            {  
                int realPitch=i*pitch;  
                for(j=0;j<width;j++)  
                {  
                    unsigned char r=buffer[(i*width+j)*3+realPitch];  
                    unsigned char g=buffer[(i*width+j)*3+1+realPitch];  
                    unsigned char b=buffer[(i*width+j)*3+2+realPitch];  
                    pDC->SetPixel(j,i,RGB(r,g,b));  
                }  
            }  
        }  
    }  
    //  
    // 32位图进行解析  
    //  
    else if(info->bmiHeader.biBitCount==32)  
    {  
        // bgra  
        if(height>0)  
        {  
            //height>0 表示图片颠倒  
            for(i=0;i<height;i++)  
            {  
                for(j=0;j<width;j++)  
                {  
                    unsigned char b=buffer[(i*width+j)*4];  
                    unsigned char g=buffer[(i*width+j)*4+1];  
                    unsigned char r=buffer[(i*width+j)*4+2];  
                    pDC->SetPixel(j,height-i, RGB(r,g,b));  
                }  
            }  
  
  
        }  
        else  
        {  
            for(i=0;i<0-height;i++)  
            {  
                for(j=0;j<width;j++)  
                {  
                    unsigned char b=buffer[(i*width+j)*4];  
                    unsigned char g=buffer[(i*width+j)*4+1];  
                    unsigned char r=buffer[(i*width+j)*4+2];  
                    pDC->SetPixel(j, i, RGB(r,g,b));  
                }  
            }  
        }  
    }  
  
    f.Close();  
    buff = NULL;  
    free(buff);  
    ReleaseDC(pDC);  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: