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

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

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

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

  1. void CTestDlg::OnButton1()   
  2. {  
  3.     //读入位图文件名  
  4.     char *filename = "720bmp16.bmp";  
  5.     CDC *pDC = GetDC();  
  6.   
  7.     //  
  8.     // 一次性将位图文件读入到内容中,待处理  
  9.     //  
  10.     CFile f;  
  11.     f.Open(filename, CFile::modeRead);  
  12.     char* buff = (char*)malloc(f.GetLength());  
  13.     f.SeekToBegin();  
  14.     f.Read(buff, f.GetLength());  
  15.       
  16.     //  
  17.     BITMAPFILEHEADER    *fileheader = NULL; //数据结构大小为14  
  18.     BITMAPINFO          *info = NULL;       //数据结构大小为40  
  19.   
  20.     fileheader = (BITMAPFILEHEADER*)buff;  
  21.   
  22.     if(fileheader->bfType!=0x4D42)  
  23.     {  
  24.         AfxMessageBox("不是BMP文件");  
  25.         f.Close();  
  26.         return ;  
  27.     }  
  28.   
  29.     //位图信息区域,在偏移14处  
  30.     info = (BITMAPINFO*)(buff+(sizeof(BITMAPFILEHEADER)));  
  31.   
  32.   
  33.     //位图的宽和高  
  34.     int width = info->bmiHeader.biWidth;  
  35.     int height= info->bmiHeader.biHeight;  
  36.   
  37.     //指向位图像素区域  
  38.     char* buffer = buff+fileheader->bfOffBits;  
  39.   
  40.     //  
  41.     //  显示位图的一些基本信息  
  42.     //  
  43.     CString str;  
  44.     str.Format("位图大小= %d\n"  
  45.                 "位图数据起始偏移 = %d\n"  
  46.                 "BITMAPINFOHEADER.biSize = %d\n"  
  47.                 "宽=%d, 高=%d\n"  
  48.                 "颜色位数=%d\n"  
  49.                 "压缩=%d\n"  
  50.                 "biSizeImage=%d\n"  
  51.                 "biClrUsed=%d\n"  
  52.                 "biClrImportant=%d",  
  53.   
  54.   
  55.                 fileheader->bfSize,      //位图大小  
  56.                 fileheader->bfOffBits,   //位图数据起始偏移  
  57.                 info->bmiHeader.biSize,  
  58.                 info->bmiHeader.biWidth,  
  59.                 info->bmiHeader.biHeight,  
  60.                 info->bmiHeader.biBitCount,  
  61.                 info->bmiHeader.biCompression,  
  62.                 info->bmiHeader.biSizeImage,  
  63.                 info->bmiHeader.biClrUsed,  
  64.                 info->bmiHeader.biClrImportant  
  65.   
  66.         );  
  67.     AfxMessageBox(str);  
  68.   
  69.     int i,j;  
  70.     //  
  71.     // 单色图的解析  
  72.     //  
  73.     if(info->bmiHeader.biBitCount==1)  
  74.     {  
  75.         int n=0;  
  76.         int color[500][500];  
  77.   
  78.         if(height>0)  
  79.         {  
  80.             //height>0 表示图片颠倒  
  81.             for(i=0; i<height; i++)  
  82.                 for(j=0; j<width; j=j+8)  
  83.                 {  
  84.                     int k=7;  
  85.                     while(k>=0)  
  86.                     {  
  87.                         color[i][k+j]=buffer[n]%2;  
  88.                         buffer[n]=buffer[n]/2;  
  89.                         k--;  
  90.                     }  
  91.                     n++;  
  92.                 }  
  93.   
  94.             for(i=0; i<height; i++)  
  95.                 for(j=0; j<width; j++)  
  96.                 {  
  97.                     if(color[i][j] == 0)  
  98.                     {  
  99.                         pDC->SetPixel(j,height-i,RGB(0,0,0));  
  100.                     }  
  101.                     if(color[i][j] == 1)  
  102.                     {  
  103.                         pDC->SetPixel(j,height-i,RGB(255,255,255));  
  104.                     }  
  105.                 }  
  106.         }  
  107.         else  
  108.         {  
  109.             for(i=0; i<0-height; i++)  
  110.                 for(j=0; j<width; j=j+8)  
  111.                 {  
  112.                     int k=7;  
  113.                     while(k>=0)  
  114.                     {  
  115.                         color[i][k+j]=buffer[n]%2;  
  116.                         buffer[n]=buffer[n]/2;  
  117.                         k--;  
  118.                     }  
  119.                     n++;  
  120.                 }  
  121.   
  122.             for(i=0; i<0-height; i++)  
  123.                 for(j=0; j<width; j++)  
  124.                 {  
  125.                     if(color[i][j] == 0)  
  126.                     {  
  127.                         pDC->SetPixel(j,i,RGB(0,0,0));  
  128.                     }  
  129.                     if(color[i][j] == 1)  
  130.                     {  
  131.                         pDC->SetPixel(j,i,RGB(255,255,255));  
  132.                     }  
  133.                 }  
  134.         }  
  135.     }  
  136.     //  
  137.     // 16色图的解析  
  138.     //  
  139.     else if(info->bmiHeader.biBitCount==4)  
  140.     {  
  141.         int pitch;  
  142.         if(width%8==0)  
  143.             pitch=width;  
  144.         else  
  145.             pitch=width+8-width%8;  
  146.   
  147.         //调色板数据  
  148.         RGBQUAD quad[16];  
  149.         memcpy(quad, buff+fileheader->bfOffBits-sizeof(quad), sizeof(quad));  
  150.   
  151.         //指向真正的像素数据  
  152.         buffer = buff+fileheader->bfOffBits;  
  153.   
  154.         if(height>0)  
  155.         {  
  156.             //height>0 表示图片颠倒  
  157.             for(i=0; i<height; i++)  
  158.                 for(j=0; j<width; j++)  
  159.                 {  
  160.                     int index;  
  161.                     if(j%2==0)  
  162.                         index = buffer[(i*pitch+j)/2]/16;  
  163.                   
  164.                     if(j%2==1)  
  165.                         index = buffer[(i*pitch+j)/2]%16;  
  166.   
  167.                     unsigned char r=quad[index].rgbRed;  
  168.                     unsigned char g=quad[index].rgbGreen;  
  169.                     unsigned char b=quad[index].rgbBlue;  
  170.                     pDC->SetPixel(j,height-i,RGB(r,g,b));  
  171.                 }  
  172.         }  
  173.         else  
  174.         {  
  175.             for(i=0; i<0-height; i++)  
  176.                 for(j=0; j<width; j++)  
  177.                 {  
  178.                     int index;  
  179.                     if(j%2==0)  
  180.                         index = buffer[(i*pitch+j)/2]/16;  
  181.                   
  182.                     if(j%2==1)  
  183.                         index = buffer[(i*pitch+j)/2]%16;  
  184.   
  185.                     unsigned char r=quad[index].rgbRed;  
  186.                     unsigned char g=quad[index].rgbGreen;  
  187.                     unsigned char b=quad[index].rgbBlue;  
  188.                     pDC->SetPixel(j,i,RGB(r,g,b));  
  189.                 }  
  190.         }  
  191.     }  
  192.     //  
  193.     // 256色(8位)图的解析  
  194.     //  
  195.     else if(info->bmiHeader.biBitCount==8)  
  196.     {  
  197.         int pitch;  
  198.         if(width%4==0)  
  199.         {  
  200.             pitch=width;  
  201.         }  
  202.         else  
  203.         {  
  204.             pitch=width+4-width%4;  
  205.         }  
  206.   
  207.         //8位位图,有调试板数据  
  208.         RGBQUAD quad[256] = {0};  
  209.         memcpy(quad, buff+fileheader->bfOffBits-sizeof(quad), sizeof(quad));  
  210.   
  211.         //  指向像素数据的起始偏移(其实并不是像素,8位位图的“像素”值代入调色板的下标,  
  212.         //      得到的值才是真正的像素)  
  213.         buffer = buff+fileheader->bfOffBits;  
  214.   
  215.         //显示  
  216.         if(height>0)  
  217.         {  
  218.             //height>0 表示图片颠倒  
  219.             for(int i=0;i<height;i++)  
  220.             {  
  221.                 for(int j=0;j<width;j++)  
  222.                 {  
  223.                     int index=buffer[i*pitch+j];  
  224.                     UCHAR r=quad[index].rgbRed;  
  225.                     UCHAR g=quad[index].rgbGreen;  
  226.                     UCHAR b=quad[index].rgbBlue;  
  227.                     pDC->SetPixel(j, height-i, RGB(r,g,b));  
  228.                 }  
  229.             }  
  230.         }  
  231.         else  
  232.         {  
  233.             for(int i=0;i<0-height;i++)  
  234.             {  
  235.                 for(int j=0;j<width;j++)  
  236.                 {  
  237.                     int index=buffer[i*pitch+j];  
  238.                     UCHAR r=quad[index].rgbRed;  
  239.                     UCHAR g=quad[index].rgbGreen;  
  240.                     UCHAR b=quad[index].rgbBlue;  
  241.                     pDC->SetPixel(j,i,RGB(r,g,b));  
  242.                 }  
  243.             }  
  244.         }  
  245.     }  
  246.   
  247.     //  
  248.     // 65536色(16位)图解析  
  249.     //  
  250.     else if(info->bmiHeader.biBitCount==16)  
  251.     {  
  252.         int pitch=width+width%2;  
  253.   
  254.         if(height>0)  
  255.         {  
  256.             //height>0 表示图片颠倒  
  257.             if(info->bmiHeader.biCompression==BI_RGB)  
  258.             {  
  259.                 //该模式只有555  
  260.                 for(int i=0;i<height;i++)  
  261.                 {  
  262.                     for(int j=0;j<width;j++)  
  263.                     {  
  264.                         // 555 格式  
  265.                         unsigned char b=buffer[(i*pitch+j)*2]&0x1F;  
  266.                         unsigned char g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);  
  267.                         unsigned char r=(buffer[(i*pitch+j)*2+1]<<1)>>3;  
  268.                         pDC->SetPixel(j,height-i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));  
  269.                     }  
  270.                 }  
  271.             }  
  272.   
  273.             if(info->bmiHeader.biCompression==BI_BITFIELDS)  
  274.             {  
  275.                 //该模式在bitmapinfoheader之后存在RGB掩码 每个掩码1 DWORD  
  276.                 //fseek(fp,fileheader.bfOffBits-sizeof(DWORD )*3,0);  
  277.                 DWORD  rMask;  
  278.                 //fread(&rMask,sizeof(DWORD ),1,fp);  
  279.                 memcpy(&rMask, buff+fileheader->bfOffBits-sizeof(DWORD )*3, sizeof(DWORD ));  
  280.                 if(rMask==0x7C00)  
  281.                 {  
  282.                     // 5 5 5 格式  
  283.                     //MessageBeep(0);  
  284.                     for(int i=0;i<height;i++)  
  285.                     {  
  286.                         for(int j=0;j<width;j++)  
  287.                         {  
  288.                             unsigned char b=buffer[(i*pitch+j)*2]&0x1F;  
  289.                             unsigned char g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);  
  290.                             unsigned char r=(buffer[(i*pitch+j)*2+1]<<1)>>3;  
  291.                             pDC->SetPixel(j,height-i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));  
  292.                         }  
  293.                     }  
  294.                 }  
  295.   
  296.                 if(rMask==0xF800)  
  297.                 {  
  298.                     //5 6 5 格式  
  299.                     for(int i=0;i<height;i++)  
  300.                     {  
  301.                         for(int j=0;j<width;j++)  
  302.                         {  
  303.                             UCHAR b=buffer[(i*pitch+j)*2]&0x1F;  
  304.                             UCHAR g=(((buffer[(i*pitch+j)*2+1]<<5)&0xFF)>>2)+(buffer[(i*pitch+j)*2]>>5);  
  305.                             UCHAR r=buffer[(i*pitch+j)*2+1]>>3;  
  306.                             pDC->SetPixel(j,height-i,RGB(r*0xFF/0x1F,g*0xFF/0x3F,b*0xFF/0x1F));  
  307.                         }  
  308.                     }  
  309.                 }  
  310.             }  
  311.   
  312.         }  
  313.         else  
  314.         {  
  315.             if(info->bmiHeader.biCompression==BI_RGB)  
  316.             {  
  317.                 //该模式只有555  
  318.                 for(int i=0;i<0-height;i++){  
  319.                     for(int j=0;j<width;j++){              
  320.                         //5 5 5 格式  
  321.                         UCHAR b=buffer[(i*pitch+j)*2]&0x1F;  
  322.                         UCHAR g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);  
  323.                         UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;  
  324.                         pDC->SetPixel(j,i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));  
  325.                     }  
  326.                 }  
  327.             }  
  328.   
  329.             if(info->bmiHeader.biCompression==BI_BITFIELDS)  
  330.             {  
  331.                 //该模式在bitmapinfoheader之后存在RGB掩码 每个掩码1 DWORD  
  332.                 //fseek(fp,fileheader.bfOffBits-sizeof(DWORD )*3,0);  
  333.                 DWORD  rMask;  
  334.                 //fread(&rMask,sizeof(DWORD ),1,fp);  
  335.                 memcpy(&rMask, buff+fileheader->bfOffBits-sizeof(DWORD )*3, sizeof(DWORD ));  
  336.                 if(rMask==0x7C00)  
  337.                 {  
  338.                     // 5 5 5 格式  
  339.                     MessageBeep(0);  
  340.                     for(int i=0;i<0-height;i++)  
  341.                     {  
  342.                         for(int j=0;j<width;j++)  
  343.                         {  
  344.                             UCHAR b=buffer[(i*pitch+j)*2]&0x1F;  
  345.                             UCHAR g=(((buffer[(i*pitch+j)*2+1]<<6)&0xFF)>>3)+(buffer[(i*pitch+j)*2]>>5);  
  346.                             UCHAR r=(buffer[(i*pitch+j)*2+1]<<1)>>3;  
  347.                             pDC->SetPixel(j,i,RGB((r*0xFF)/0x1F,(g*0xFF)/0x1F,(b*0xFF)/0x1F));  
  348.                         }  
  349.                     }  
  350.                 }  
  351.   
  352.                 if(rMask==0xF800)  
  353.                 {  
  354.                     //565 格式  
  355.                     for(int i=0;i<0-height;i++)  
  356.                     {  
  357.                         for(int j=0;j<width;j++)  
  358.                         {  
  359.                             UCHAR b=buffer[(i*pitch+j)*2]&0x1F;  
  360.                             UCHAR g=(((buffer[(i*pitch+j)*2+1]<<5)&0xFF)>>2)+(buffer[(i*pitch+j)*2]>>5);  
  361.                             UCHAR r=buffer[(i*pitch+j)*2+1]>>3;  
  362.                             pDC->SetPixel(j,i,RGB(r*0xFF/0x1F,g*0xFF/0x3F,b*0xFF/0x1F));  
  363.                         }  
  364.                     }  
  365.                 }  
  366.             }  
  367.         }  
  368.     }  
  369.     //  
  370.     // 24位图解析  
  371.     //  
  372.     else if(info->bmiHeader.biBitCount==24)  
  373.     {  
  374.         int pitch=width%4;  
  375.         // bgr  
  376.         int i,j;  
  377.         if(height>0)  
  378.         {  
  379.             //height>0 表示图片颠倒              
  380.             for(i=0;i<height;i++)  
  381.             {  
  382.                 int realPitch=i*pitch;  
  383.                 for(j=0;j<width;j++)  
  384.                 {  
  385.                     unsigned char b=buffer[(i*width+j)*3+realPitch];  
  386.                     unsigned char g=buffer[(i*width+j)*3+1+realPitch];  
  387.                     unsigned char r=buffer[(i*width+j)*3+2+realPitch];  
  388.                     pDC->SetPixel(j,height-i,RGB(r,g,b));  
  389.                 }  
  390.             }  
  391.         }  
  392.         else  
  393.         {  
  394.             for(i=0;i<0-height;i++)  
  395.             {  
  396.                 int realPitch=i*pitch;  
  397.                 for(j=0;j<width;j++)  
  398.                 {  
  399.                     unsigned char r=buffer[(i*width+j)*3+realPitch];  
  400.                     unsigned char g=buffer[(i*width+j)*3+1+realPitch];  
  401.                     unsigned char b=buffer[(i*width+j)*3+2+realPitch];  
  402.                     pDC->SetPixel(j,i,RGB(r,g,b));  
  403.                 }  
  404.             }  
  405.         }  
  406.     }  
  407.     //  
  408.     // 32位图进行解析  
  409.     //  
  410.     else if(info->bmiHeader.biBitCount==32)  
  411.     {  
  412.         // bgra  
  413.         if(height>0)  
  414.         {  
  415.             //height>0 表示图片颠倒  
  416.             for(i=0;i<height;i++)  
  417.             {  
  418.                 for(j=0;j<width;j++)  
  419.                 {  
  420.                     unsigned char b=buffer[(i*width+j)*4];  
  421.                     unsigned char g=buffer[(i*width+j)*4+1];  
  422.                     unsigned char r=buffer[(i*width+j)*4+2];  
  423.                     pDC->SetPixel(j,height-i, RGB(r,g,b));  
  424.                 }  
  425.             }  
  426.   
  427.   
  428.         }  
  429.         else  
  430.         {  
  431.             for(i=0;i<0-height;i++)  
  432.             {  
  433.                 for(j=0;j<width;j++)  
  434.                 {  
  435.                     unsigned char b=buffer[(i*width+j)*4];  
  436.                     unsigned char g=buffer[(i*width+j)*4+1];  
  437.                     unsigned char r=buffer[(i*width+j)*4+2];  
  438.                     pDC->SetPixel(j, i, RGB(r,g,b));  
  439.                 }  
  440.             }  
  441.         }  
  442.     }  
  443.   
  444.     f.Close();  
  445.     buff = NULL;  
  446.     free(buff);  
  447.     ReleaseDC(pDC);  

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值