`

用c语言进行bmp文件的读写

    博客分类:
  • c++
 
阅读更多

参考:http://cvchina.net/thread-1624-1-1.html



bmp是BitMap(位图)的简称,也是所有windows上图片显示的基础。所有的图片格式,都必须转换成bmp才能进行最终的显示。所以,bmp文件的读写,就变得非常重要了。然而,很多人是借助于MFC类,C# 库函数,OpenCV,OpenGL等库函数进行bmp文件的读写。试想一下,如果你要在诸如DSP、FPGA之类的嵌入式设备上进行bmp文件的读写,总不能去安装一个庞大的MFC,C#类库吧?其实,我们完全可以抛开这些庞杂繁琐的类库和API函数,仅仅利用C语言,编写几个函数,就完全可以实现bmp文件的读写了。 
本文的意图正在于此。

       一个完整的bmp位图文件,可以分为文件信息头,位图信息头和RGB颜色阵列三个部分(希望对这三部分有详细了解的可以参考我的另外一篇文章:http://blog.csdn.net/carson2005/article/details/6227047)。文件信息头主要包含“是否是BMP文件”,文件的大小等信息。而位图信息头则主要包含bmp文件的位图宽度,高度,位平面,通道数等信息。而RGB颜色阵列,里面才真正包含我们所需要的bmp位图的像素数据。需要提醒的是,bmp位图的颜色阵列部分,像素数据的存储是以左下角为原点。也就是说,当你打开一个bmp图片并显示在电脑屏幕上的时,实际在存储的时候,这个图片的最左下角的像素是首先被存储在bmp文件中的。之后,按照从左到右,从下到上的顺序,依次进行像素数据的存储。如果,你存储的是3通道的位图数据(也就是我们通常说的彩图),那么它是按照B0G0R0B1G1R1B2G2R2...的顺序进行存储的,同时,还要考虑到4字节对齐的问题。OK,了解了这些基本概念,相信,自己编程实现一些bmp文件的读写函数并非难事。这里,我给出C语言的版本,仅供参考,如有错误,欢迎指正。
  1. chenLeeCV.h  
  2. #ifndef CHENLEECV_H   
  3. #define CHENLEECV_H   
  4.   
  5. typedef struct  
  6. {  
  7.     //unsigned short    bfType;   
  8.     unsigned long    bfSize;  
  9.     unsigned short    bfReserved1;  
  10.     unsigned short    bfReserved2;  
  11.     unsigned long    bfOffBits;  
  12. } ClBitMapFileHeader;  
  13.   
  14. typedef struct  
  15. {  
  16.     unsigned long  biSize;   
  17.     long   biWidth;   
  18.     long   biHeight;   
  19.     unsigned short   biPlanes;   
  20.     unsigned short   biBitCount;  
  21.     unsigned long  biCompression;   
  22.     unsigned long  biSizeImage;   
  23.     long   biXPelsPerMeter;   
  24.     long   biYPelsPerMeter;   
  25.     unsigned long   biClrUsed;   
  26.     unsigned long   biClrImportant;   
  27. } ClBitMapInfoHeader;  
  28.   
  29. typedef struct   
  30. {  
  31.     unsigned char rgbBlue; //该颜色的蓝色分量   
  32.     unsigned char rgbGreen; //该颜色的绿色分量   
  33.     unsigned char rgbRed; //该颜色的红色分量   
  34.     unsigned char rgbReserved; //保留值   
  35. } ClRgbQuad;  
  36.   
  37. typedef struct  
  38. {  
  39.     int width;  
  40.     int height;  
  41.     int channels;  
  42.     unsigned char* imageData;  
  43. }ClImage;  
  44.   
  45. ClImage* clLoadImage(char* path);  
  46. bool clSaveImage(char* path, ClImage* bmpImg);  
  47.   
  48. #endif   
  49.   
  50. chenLeeCV.cpp  
  51. #include "chenLeeCV.h"   
  52. #include <stdio.h>   
  53. #include <stdlib.h>   
  54.   
  55. ClImage* clLoadImage(char* path)  
  56. {  
  57.     ClImage* bmpImg;  
  58.     FILE* pFile;  
  59.     unsigned short fileType;  
  60.     ClBitMapFileHeader bmpFileHeader;  
  61.     ClBitMapInfoHeader bmpInfoHeader;  
  62.     int channels = 1;  
  63.     int width = 0;  
  64.     int height = 0;  
  65.     int step = 0;  
  66.     int offset = 0;  
  67.     unsigned char pixVal;  
  68.     ClRgbQuad* quad;  
  69.     int i, j, k;  
  70.   
  71.     bmpImg = (ClImage*)malloc(sizeof(ClImage));  
  72.     pFile = fopen(path, "rb");  
  73.     if (!pFile)  
  74.     {  
  75.         free(bmpImg);  
  76.         return NULL;  
  77.     }  
  78.   
  79.     fread(&fileType, sizeof(unsigned short), 1, pFile);  
  80.     if (fileType == 0x4D42)  
  81.     {  
  82.         //printf("bmp file! \n");   
  83.   
  84.         fread(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);  
  85.         /*printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n"); 
  86.         printf("bmp文件头信息:\n"); 
  87.         printf("文件大小:%d \n", bmpFileHeader.bfSize); 
  88.         printf("保留字1:%d \n", bmpFileHeader.bfReserved1); 
  89.         printf("保留字2:%d \n", bmpFileHeader.bfReserved2); 
  90.         printf("位图数据偏移字节数:%d \n", bmpFileHeader.bfOffBits);*/  
  91.   
  92.         fread(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);  
  93.         /*printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n"); 
  94.         printf("bmp文件信息头 \n"); 
  95.         printf("结构体长度:%d \n", bmpInfoHeader.biSize); 
  96.         printf("位图宽度:%d \n", bmpInfoHeader.biWidth); 
  97.         printf("位图高度:%d \n", bmpInfoHeader.biHeight); 
  98.         printf("位图平面数:%d \n", bmpInfoHeader.biPlanes); 
  99.         printf("颜色位数:%d \n", bmpInfoHeader.biBitCount); 
  100.         printf("压缩方式:%d \n", bmpInfoHeader.biCompression); 
  101.         printf("实际位图数据占用的字节数:%d \n", bmpInfoHeader.biSizeImage); 
  102.         printf("X方向分辨率:%d \n", bmpInfoHeader.biXPelsPerMeter); 
  103.         printf("Y方向分辨率:%d \n", bmpInfoHeader.biYPelsPerMeter); 
  104.         printf("使用的颜色数:%d \n", bmpInfoHeader.biClrUsed); 
  105.         printf("重要颜色数:%d \n", bmpInfoHeader.biClrImportant); 
  106.         printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");*/  
  107.   
  108.         if (bmpInfoHeader.biBitCount == 8)  
  109.         {  
  110.             //printf("该文件有调色板,即该位图为非真彩色\n\n");   
  111.             channels = 1;  
  112.             width = bmpInfoHeader.biWidth;  
  113.             height = bmpInfoHeader.biHeight;  
  114.             offset = (channels*width)%4;  
  115.             if (offset != 0)  
  116.             {  
  117.                 offset = 4 - offset;  
  118.             }  
  119.             //bmpImg->mat = kzCreateMat(height, width, 1, 0);   
  120.             bmpImg->width = width;  
  121.             bmpImg->height = height;  
  122.             bmpImg->channels = 1;  
  123.             bmpImg->imageData = (unsigned char*)malloc(sizeof(unsigned char)*width*height);  
  124.             step = channels*width;  
  125.   
  126.             quad = (ClRgbQuad*)malloc(sizeof(ClRgbQuad)*256);  
  127.             fread(quad, sizeof(ClRgbQuad), 256, pFile);  
  128.             free(quad);  
  129.   
  130.             for (i=0; i<height; i++)  
  131.             {  
  132.                 for (j=0; j<width; j++)  
  133.                 {  
  134.                     fread(&pixVal, sizeof(unsigned char), 1, pFile);  
  135.                     bmpImg->imageData[(height-1-i)*step+j] = pixVal;  
  136.                 }  
  137.                 if (offset != 0)  
  138.                 {  
  139.                     for (j=0; j<offset; j++)  
  140.                     {  
  141.                         fread(&pixVal, sizeof(unsigned char), 1, pFile);  
  142.                     }  
  143.                 }  
  144.             }             
  145.         }  
  146.         else if (bmpInfoHeader.biBitCount == 24)  
  147.         {  
  148.             //printf("该位图为24位真彩色\n\n");   
  149.             channels = 3;  
  150.             width = bmpInfoHeader.biWidth;  
  151.             height = bmpInfoHeader.biHeight;  
  152.   
  153.             bmpImg->width = width;  
  154.             bmpImg->height = height;  
  155.             bmpImg->channels = 3;  
  156.             bmpImg->imageData = (unsigned char*)malloc(sizeof(unsigned char)*width*3*height);  
  157.             step = channels*width;  
  158.   
  159.             offset = (channels*width)%4;  
  160.             if (offset != 0)  
  161.             {  
  162.                 offset = 4 - offset;  
  163.             }  
  164.   
  165.             for (i=0; i<height; i++)  
  166.             {  
  167.                 for (j=0; j<width; j++)  
  168.                 {  
  169.                     for (k=0; k<3; k++)  
  170.                     {  
  171.                         fread(&pixVal, sizeof(unsigned char), 1, pFile);  
  172.                         bmpImg->imageData[(height-1-i)*step+j*3+k] = pixVal;  
  173.                     }  
  174.                     //kzSetMat(bmpImg->mat, height-1-i, j, kzScalar(pixVal[0], pixVal[1], pixVal[2]));   
  175.                 }  
  176.                 if (offset != 0)  
  177.                 {  
  178.                     for (j=0; j<offset; j++)  
  179.                     {  
  180.                         fread(&pixVal, sizeof(unsigned char), 1, pFile);  
  181.                     }  
  182.                 }  
  183.             }  
  184.         }  
  185.     }  
  186.   
  187.     return bmpImg;  
  188. }  
  189.   
  190. bool clSaveImage(char* path, ClImage* bmpImg)  
  191. {  
  192.     FILE *pFile;  
  193.     unsigned short fileType;  
  194.     ClBitMapFileHeader bmpFileHeader;  
  195.     ClBitMapInfoHeader bmpInfoHeader;  
  196.     int step;  
  197.     int offset;  
  198.     unsigned char pixVal = '\0';  
  199.     int i, j;  
  200.     ClRgbQuad* quad;  
  201.   
  202.     pFile = fopen(path, "wb");  
  203.     if (!pFile)  
  204.     {  
  205.         return false;  
  206.     }  
  207.   
  208.     fileType = 0x4D42;  
  209.     fwrite(&fileType, sizeof(unsigned short), 1, pFile);  
  210.   
  211.     if (bmpImg->channels == 3)//24位,3通道,彩图   
  212.     {  
  213.         step = bmpImg->channels*bmpImg->width;  
  214.         offset = step%4;  
  215.         if (offset != 4)  
  216.         {  
  217.             step += 4-offset;  
  218.         }  
  219.   
  220.         bmpFileHeader.bfSize = bmpImg->height*step + 54;  
  221.         bmpFileHeader.bfReserved1 = 0;  
  222.         bmpFileHeader.bfReserved2 = 0;  
  223.         bmpFileHeader.bfOffBits = 54;  
  224.         fwrite(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);  
  225.   
  226.         bmpInfoHeader.biSize = 40;  
  227.         bmpInfoHeader.biWidth = bmpImg->width;  
  228.         bmpInfoHeader.biHeight = bmpImg->height;  
  229.         bmpInfoHeader.biPlanes = 1;  
  230.         bmpInfoHeader.biBitCount = 24;  
  231.         bmpInfoHeader.biCompression = 0;  
  232.         bmpInfoHeader.biSizeImage = bmpImg->height*step;  
  233.         bmpInfoHeader.biXPelsPerMeter = 0;  
  234.         bmpInfoHeader.biYPelsPerMeter = 0;  
  235.         bmpInfoHeader.biClrUsed = 0;  
  236.         bmpInfoHeader.biClrImportant = 0;  
  237.         fwrite(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);  
  238.   
  239.         for (i=bmpImg->height-1; i>-1; i--)  
  240.         {  
  241.             for (j=0; j<bmpImg->width; j++)  
  242.             {  
  243.                 pixVal = bmpImg->imageData[i*bmpImg->width*3+j*3];  
  244.                 fwrite(&pixVal, sizeof(unsigned char), 1, pFile);  
  245.                 pixVal = bmpImg->imageData[i*bmpImg->width*3+j*3+1];  
  246.                 fwrite(&pixVal, sizeof(unsigned char), 1, pFile);  
  247.                 pixVal = bmpImg->imageData[i*bmpImg->width*3+j*3+2];  
  248.                 fwrite(&pixVal, sizeof(unsigned char), 1, pFile);  
  249.             }  
  250.             if (offset!=0)  
  251.             {  
  252.                 for (j=0; j<offset; j++)  
  253.                 {  
  254.                     pixVal = 0;  
  255.                     fwrite(&pixVal, sizeof(unsigned char), 1, pFile);  
  256.                 }  
  257.             }  
  258.         }  
  259.     }  
  260.     else if (bmpImg->channels == 1)//8位,单通道,灰度图   
  261.     {  
  262.         step = bmpImg->width;  
  263.         offset = step%4;  
  264.         if (offset != 4)  
  265.         {  
  266.             step += 4-offset;  
  267.         }  
  268.   
  269.         bmpFileHeader.bfSize = 54 + 256*4 + bmpImg->width;  
  270.         bmpFileHeader.bfReserved1 = 0;  
  271.         bmpFileHeader.bfReserved2 = 0;  
  272.         bmpFileHeader.bfOffBits = 54 + 256*4;  
  273.         fwrite(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);  
  274.   
  275.         bmpInfoHeader.biSize = 40;  
  276.         bmpInfoHeader.biWidth = bmpImg->width;  
  277.         bmpInfoHeader.biHeight = bmpImg->height;  
  278.         bmpInfoHeader.biPlanes = 1;  
  279.         bmpInfoHeader.biBitCount = 8;  
  280.         bmpInfoHeader.biCompression = 0;  
  281.         bmpInfoHeader.biSizeImage = bmpImg->height*step;  
  282.         bmpInfoHeader.biXPelsPerMeter = 0;  
  283.         bmpInfoHeader.biYPelsPerMeter = 0;  
  284.         bmpInfoHeader.biClrUsed = 256;  
  285.         bmpInfoHeader.biClrImportant = 256;  
  286.         fwrite(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);  
  287.   
  288.         quad = (ClRgbQuad*)malloc(sizeof(ClRgbQuad)*256);  
  289.         for (i=0; i<256; i++)  
  290.         {  
  291.             quad[i].rgbBlue = i;  
  292.             quad[i].rgbGreen = i;  
  293.             quad[i].rgbRed = i;  
  294.             quad[i].rgbReserved = 0;  
  295.         }  
  296.         fwrite(quad, sizeof(ClRgbQuad), 256, pFile);  
  297.         free(quad);  
  298.   
  299.         for (i=bmpImg->height-1; i>-1; i--)  
  300.         {  
  301.             for (j=0; j<bmpImg->width; j++)  
  302.             {  
  303.                 pixVal = bmpImg->imageData[i*bmpImg->width+j];  
  304.                 fwrite(&pixVal, sizeof(unsigned char), 1, pFile);  
  305.             }  
  306.             if (offset!=0)  
  307.             {  
  308.                 for (j=0; j<offset; j++)  
  309.                 {  
  310.                     pixVal = 0;  
  311.                     fwrite(&pixVal, sizeof(unsigned char), 1, pFile);  
  312.                 }  
  313.             }  
  314.         }  
  315.     }  
  316.     fclose(pFile);  
  317.   
  318.     return true;  
  319. }  
  320.   
  321. main.cpp  
  322. #include "stdafx.h"   
  323. #include "chenLeeCV.h"   
  324.   
  325.   
  326. int _tmain(int argc, _TCHAR* argv[])  
  327. {  
  328.     ClImage* img = clLoadImage("c:/test.bmp");  
  329.     bool flag = clSaveImage("c:/result.bmp", img);  
  330.     if(flag)  
  331.     {  
  332.         printf("save ok... \n");  
  333.     }  
  334.       
  335.   
  336.     while(1);  
  337.     return 0;  
  338. }  
复制代码
分享到:
评论

相关推荐

    BMP文件的读写C代码及文档.rar

    这个压缩包“BMP文件的读写C代码及文档.rar”包含了关于如何使用C语言进行BMP文件读写操作的相关资料,包括一个PDF文档“BMP file format.pdf”和一个名为“readwriteBMP.rar”的源代码压缩包。 BMP文件格式的基础...

    C语言编写BMP的读写

    首先,需要定义 BITMAPFILEHEADER 和 BITMAPINFOHEADER 结构体,然后使用文件输入/输出函数读取或写入 BMP 文件的内容。例如,可以使用 printf 函数显示位图文件头和位图信息头的信息。 6. 位图数据 位图数据是 ...

    C语言读写Bmp图像程序

    在IT领域,C语言是一种基础且强大的编程语言,被广泛应用于系统编程、嵌入式开发以及各种底层操作。...但作为初学者的参考,这个简单的C语言BMP读写程序已经足够揭示许多基本概念,帮助开发者迈入图像处理的世界。

    c语言读取bmp文件

    - 图像处理库:在实际开发中,可以使用如OpenCV、FreeImage等库来简化BMP文件的读写操作。 - 色彩空间转换:BMP文件通常以RGB格式存储,但可能需要转换为其他色彩空间,如CMYK、HSV等。 - 图像操作:包括缩放、...

    纯C语言读写24BMP文件,32位BMP转24位BMP,读写8位BMP,二值化程序

    纯C语言读写24BMP文件,32位BMP转24位BMP,读写8位BMP,二值化程序 详见:https://blog.csdn.net/libizhide/article/details/104144513

    C语言读取BMP文件

    根据给定代码,我们可以分步骤地了解如何用C语言读取BMP文件: 1. **引入必要的库** - `&lt;windows.h&gt;`: 提供了Windows平台下的文件操作API。 - `&lt;stdio.h&gt;`: 标准输入输出函数。 - `&lt;stdlib.h&gt;`: 包含动态内存...

    C语言对BMP图像的读和写和对像素的操作

    本篇文章主要介绍如何使用C语言进行BMP图像的基本读取、写入以及像素级别的操作。 #### 二、BMP图像基本概念 BMP图像由文件头、信息头和像素数组三部分组成: - **文件头**:包含文件类型等基本信息。 - **信息头**...

    C语言对BMP文件的操作

    C语言作为基础的编程语言,虽然没有内置的图形库来直接处理BMP文件,但通过理解BMP文件的结构,我们可以用C语言编写程序来读取、修改和保存BMP图像。本文将详细介绍如何利用C语言操作BMP文件,以及获取图像的长宽...

    C语言读取BMP图片

    压缩包内包含报告及说明文档。源码环境是VC6,在VS内稍做修改之后也可运行。代码是我大一时所写,可能有部分不妥之处,欢迎指正。由于是比赛作品直接压缩上传,压缩包内包含作者信息、还望尊重作者,不喜勿喷,谢谢...

    ReadBitMap_C语言读取bmp文件.cpp

    用C语言读取BITMAP文件,此源码默认读取当前目录下的1.bmp。可以改成处理其他BMP文件。

    C语言代码,生成bmp位图

    在提供的"生成位图.c"源代码中,你可以看到上述步骤的具体实现,包括如何创建并初始化这些结构体,如何生成像素数据,以及如何使用C语言的文件I/O函数进行操作。执行生成位图.exe文件,将会依据源代码逻辑生成一个...

    纯C语言读写24BMP文件,32位BMP转24位BMP

    纯C语言读写24BMP文件,32位BMP转24位BMP; 详情参见:https://blog.csdn.net/libizhide/article/details/104144513 下载后请修改错误:main.c中55行pic=(PIC *)malloc(1);改为pic=(PIC *)malloc(sizeof(PIC)*1);

    bmp文件读写操作C代码

    在C语言中,对BMP文件进行读写操作是一项基础但重要的技能,这对于图像处理和计算机图形学领域的开发至关重要。本文将详细介绍如何使用C语言进行BMP文件的读取与写入操作,并探讨相关的关键知识点。 首先,我们需要...

    用C语言调节BMP图的亮度

    总的来说,调整BMP图像亮度是一个涉及到文件读写、图像处理和基本数学运算的过程,通过C语言实现可以提供较高的效率和灵活性。在编程实践中,可以结合特定需求优化算法,比如使用并行处理来加速对大量像素的操作。

    c语言对bmp图像中值均值滤波

    C语言中可以使用标准库如`fread`和`fwrite`进行文件读写,`malloc`分配内存,以及自定义函数处理像素数据。 为了优化效率,可以考虑使用滑动窗口法,避免重复计算邻域像素。同时,处理边界问题时,可选择镜像边界...

    256级灰度BMP文件读写的源代码+c语言图像处理.docx

    256级灰度BMP文件读写的源代码+c语言图像处理 本文档主要介绍了256级灰度BMP文件的读写源代码,以及c语言图像处理的实现。下面是对该文档中所涉及到的知识点的详细解释: 一、BMP文件格式 BMP(Bitmap)是一种...

    BMP位图图像C语言读写封装源码及BMP位图详细介绍

    在IT领域,BMP(Bitmap)位图是一种常见的图像文件格式,它以未压缩的...而C语言的BMP读写封装源码则为这些操作提供了基础。同时,配合PDF文档的详细分析,可以更好地理解BMP文件的内部机制,进一步提升图像处理能力。

    BMP.rar_bitmap read c source_bmp 读写_bmp文件_c bmp_写bmp

    接下来,我们将深入探讨BMP文件格式以及如何用C语言进行读写操作。 BMP文件结构主要包括以下几个部分: 1. 文件头(File Header):这是BMP文件的起始部分,包含14个字节,用来标识文件类型和文件大小。其中,前两...

    C语言版BMP2JPG

    1. **文件读写**:在C语言中,可以使用`fopen`、`fread`和`fwrite`等函数来读取和写入文件。在BMP2JPG程序中,我们需要先读取BMP文件的头信息,然后读取像素数据。 2. **BMP文件头解析**:BMP文件通常由文件头、...

    bmp图像读写操作程序

    2. **打开文件**:使用`fopen()`函数打开BMP文件,一般以二进制模式("rb"或"wb")进行读写。 3. **读取文件头**:通过`fread()`函数读取文件头数据,然后解析这些数据以获取图像的基本信息。 4. **分配内存**:...

Global site tag (gtag.js) - Google Analytics