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语言的版本,仅供参考,如有错误,欢迎指正。
- chenLeeCV.h
- #ifndef CHENLEECV_H
- #define CHENLEECV_H
-
- typedef struct
- {
- //unsigned short bfType;
- unsigned long bfSize;
- unsigned short bfReserved1;
- unsigned short bfReserved2;
- unsigned long bfOffBits;
- } ClBitMapFileHeader;
-
- typedef struct
- {
- unsigned long biSize;
- long biWidth;
- long biHeight;
- unsigned short biPlanes;
- unsigned short biBitCount;
- unsigned long biCompression;
- unsigned long biSizeImage;
- long biXPelsPerMeter;
- long biYPelsPerMeter;
- unsigned long biClrUsed;
- unsigned long biClrImportant;
- } ClBitMapInfoHeader;
-
- typedef struct
- {
- unsigned char rgbBlue; //该颜色的蓝色分量
- unsigned char rgbGreen; //该颜色的绿色分量
- unsigned char rgbRed; //该颜色的红色分量
- unsigned char rgbReserved; //保留值
- } ClRgbQuad;
-
- typedef struct
- {
- int width;
- int height;
- int channels;
- unsigned char* imageData;
- }ClImage;
-
- ClImage* clLoadImage(char* path);
- bool clSaveImage(char* path, ClImage* bmpImg);
-
- #endif
-
- chenLeeCV.cpp
- #include "chenLeeCV.h"
- #include <stdio.h>
- #include <stdlib.h>
-
- ClImage* clLoadImage(char* path)
- {
- ClImage* bmpImg;
- FILE* pFile;
- unsigned short fileType;
- ClBitMapFileHeader bmpFileHeader;
- ClBitMapInfoHeader bmpInfoHeader;
- int channels = 1;
- int width = 0;
- int height = 0;
- int step = 0;
- int offset = 0;
- unsigned char pixVal;
- ClRgbQuad* quad;
- int i, j, k;
-
- bmpImg = (ClImage*)malloc(sizeof(ClImage));
- pFile = fopen(path, "rb");
- if (!pFile)
- {
- free(bmpImg);
- return NULL;
- }
-
- fread(&fileType, sizeof(unsigned short), 1, pFile);
- if (fileType == 0x4D42)
- {
- //printf("bmp file! \n");
-
- fread(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);
- /*printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
- printf("bmp文件头信息:\n");
- printf("文件大小:%d \n", bmpFileHeader.bfSize);
- printf("保留字1:%d \n", bmpFileHeader.bfReserved1);
- printf("保留字2:%d \n", bmpFileHeader.bfReserved2);
- printf("位图数据偏移字节数:%d \n", bmpFileHeader.bfOffBits);*/
-
- fread(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);
- /*printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
- printf("bmp文件信息头 \n");
- printf("结构体长度:%d \n", bmpInfoHeader.biSize);
- printf("位图宽度:%d \n", bmpInfoHeader.biWidth);
- printf("位图高度:%d \n", bmpInfoHeader.biHeight);
- printf("位图平面数:%d \n", bmpInfoHeader.biPlanes);
- printf("颜色位数:%d \n", bmpInfoHeader.biBitCount);
- printf("压缩方式:%d \n", bmpInfoHeader.biCompression);
- printf("实际位图数据占用的字节数:%d \n", bmpInfoHeader.biSizeImage);
- printf("X方向分辨率:%d \n", bmpInfoHeader.biXPelsPerMeter);
- printf("Y方向分辨率:%d \n", bmpInfoHeader.biYPelsPerMeter);
- printf("使用的颜色数:%d \n", bmpInfoHeader.biClrUsed);
- printf("重要颜色数:%d \n", bmpInfoHeader.biClrImportant);
- printf("\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");*/
-
- if (bmpInfoHeader.biBitCount == 8)
- {
- //printf("该文件有调色板,即该位图为非真彩色\n\n");
- channels = 1;
- width = bmpInfoHeader.biWidth;
- height = bmpInfoHeader.biHeight;
- offset = (channels*width)%4;
- if (offset != 0)
- {
- offset = 4 - offset;
- }
- //bmpImg->mat = kzCreateMat(height, width, 1, 0);
- bmpImg->width = width;
- bmpImg->height = height;
- bmpImg->channels = 1;
- bmpImg->imageData = (unsigned char*)malloc(sizeof(unsigned char)*width*height);
- step = channels*width;
-
- quad = (ClRgbQuad*)malloc(sizeof(ClRgbQuad)*256);
- fread(quad, sizeof(ClRgbQuad), 256, pFile);
- free(quad);
-
- for (i=0; i<height; i++)
- {
- for (j=0; j<width; j++)
- {
- fread(&pixVal, sizeof(unsigned char), 1, pFile);
- bmpImg->imageData[(height-1-i)*step+j] = pixVal;
- }
- if (offset != 0)
- {
- for (j=0; j<offset; j++)
- {
- fread(&pixVal, sizeof(unsigned char), 1, pFile);
- }
- }
- }
- }
- else if (bmpInfoHeader.biBitCount == 24)
- {
- //printf("该位图为24位真彩色\n\n");
- channels = 3;
- width = bmpInfoHeader.biWidth;
- height = bmpInfoHeader.biHeight;
-
- bmpImg->width = width;
- bmpImg->height = height;
- bmpImg->channels = 3;
- bmpImg->imageData = (unsigned char*)malloc(sizeof(unsigned char)*width*3*height);
- step = channels*width;
-
- offset = (channels*width)%4;
- if (offset != 0)
- {
- offset = 4 - offset;
- }
-
- for (i=0; i<height; i++)
- {
- for (j=0; j<width; j++)
- {
- for (k=0; k<3; k++)
- {
- fread(&pixVal, sizeof(unsigned char), 1, pFile);
- bmpImg->imageData[(height-1-i)*step+j*3+k] = pixVal;
- }
- //kzSetMat(bmpImg->mat, height-1-i, j, kzScalar(pixVal[0], pixVal[1], pixVal[2]));
- }
- if (offset != 0)
- {
- for (j=0; j<offset; j++)
- {
- fread(&pixVal, sizeof(unsigned char), 1, pFile);
- }
- }
- }
- }
- }
-
- return bmpImg;
- }
-
- bool clSaveImage(char* path, ClImage* bmpImg)
- {
- FILE *pFile;
- unsigned short fileType;
- ClBitMapFileHeader bmpFileHeader;
- ClBitMapInfoHeader bmpInfoHeader;
- int step;
- int offset;
- unsigned char pixVal = '\0';
- int i, j;
- ClRgbQuad* quad;
-
- pFile = fopen(path, "wb");
- if (!pFile)
- {
- return false;
- }
-
- fileType = 0x4D42;
- fwrite(&fileType, sizeof(unsigned short), 1, pFile);
-
- if (bmpImg->channels == 3)//24位,3通道,彩图
- {
- step = bmpImg->channels*bmpImg->width;
- offset = step%4;
- if (offset != 4)
- {
- step += 4-offset;
- }
-
- bmpFileHeader.bfSize = bmpImg->height*step + 54;
- bmpFileHeader.bfReserved1 = 0;
- bmpFileHeader.bfReserved2 = 0;
- bmpFileHeader.bfOffBits = 54;
- fwrite(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);
-
- bmpInfoHeader.biSize = 40;
- bmpInfoHeader.biWidth = bmpImg->width;
- bmpInfoHeader.biHeight = bmpImg->height;
- bmpInfoHeader.biPlanes = 1;
- bmpInfoHeader.biBitCount = 24;
- bmpInfoHeader.biCompression = 0;
- bmpInfoHeader.biSizeImage = bmpImg->height*step;
- bmpInfoHeader.biXPelsPerMeter = 0;
- bmpInfoHeader.biYPelsPerMeter = 0;
- bmpInfoHeader.biClrUsed = 0;
- bmpInfoHeader.biClrImportant = 0;
- fwrite(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);
-
- for (i=bmpImg->height-1; i>-1; i--)
- {
- for (j=0; j<bmpImg->width; j++)
- {
- pixVal = bmpImg->imageData[i*bmpImg->width*3+j*3];
- fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
- pixVal = bmpImg->imageData[i*bmpImg->width*3+j*3+1];
- fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
- pixVal = bmpImg->imageData[i*bmpImg->width*3+j*3+2];
- fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
- }
- if (offset!=0)
- {
- for (j=0; j<offset; j++)
- {
- pixVal = 0;
- fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
- }
- }
- }
- }
- else if (bmpImg->channels == 1)//8位,单通道,灰度图
- {
- step = bmpImg->width;
- offset = step%4;
- if (offset != 4)
- {
- step += 4-offset;
- }
-
- bmpFileHeader.bfSize = 54 + 256*4 + bmpImg->width;
- bmpFileHeader.bfReserved1 = 0;
- bmpFileHeader.bfReserved2 = 0;
- bmpFileHeader.bfOffBits = 54 + 256*4;
- fwrite(&bmpFileHeader, sizeof(ClBitMapFileHeader), 1, pFile);
-
- bmpInfoHeader.biSize = 40;
- bmpInfoHeader.biWidth = bmpImg->width;
- bmpInfoHeader.biHeight = bmpImg->height;
- bmpInfoHeader.biPlanes = 1;
- bmpInfoHeader.biBitCount = 8;
- bmpInfoHeader.biCompression = 0;
- bmpInfoHeader.biSizeImage = bmpImg->height*step;
- bmpInfoHeader.biXPelsPerMeter = 0;
- bmpInfoHeader.biYPelsPerMeter = 0;
- bmpInfoHeader.biClrUsed = 256;
- bmpInfoHeader.biClrImportant = 256;
- fwrite(&bmpInfoHeader, sizeof(ClBitMapInfoHeader), 1, pFile);
-
- quad = (ClRgbQuad*)malloc(sizeof(ClRgbQuad)*256);
- for (i=0; i<256; i++)
- {
- quad[i].rgbBlue = i;
- quad[i].rgbGreen = i;
- quad[i].rgbRed = i;
- quad[i].rgbReserved = 0;
- }
- fwrite(quad, sizeof(ClRgbQuad), 256, pFile);
- free(quad);
-
- for (i=bmpImg->height-1; i>-1; i--)
- {
- for (j=0; j<bmpImg->width; j++)
- {
- pixVal = bmpImg->imageData[i*bmpImg->width+j];
- fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
- }
- if (offset!=0)
- {
- for (j=0; j<offset; j++)
- {
- pixVal = 0;
- fwrite(&pixVal, sizeof(unsigned char), 1, pFile);
- }
- }
- }
- }
- fclose(pFile);
-
- return true;
- }
-
- main.cpp
- #include "stdafx.h"
- #include "chenLeeCV.h"
-
-
- int _tmain(int argc, _TCHAR* argv[])
- {
- ClImage* img = clLoadImage("c:/test.bmp");
- bool flag = clSaveImage("c:/result.bmp", img);
- if(flag)
- {
- printf("save ok... \n");
- }
-
-
- while(1);
- return 0;
- }
复制代码
|
相关推荐
这个压缩包“BMP文件的读写C代码及文档.rar”包含了关于如何使用C语言进行BMP文件读写操作的相关资料,包括一个PDF文档“BMP file format.pdf”和一个名为“readwriteBMP.rar”的源代码压缩包。 BMP文件格式的基础...
首先,需要定义 BITMAPFILEHEADER 和 BITMAPINFOHEADER 结构体,然后使用文件输入/输出函数读取或写入 BMP 文件的内容。例如,可以使用 printf 函数显示位图文件头和位图信息头的信息。 6. 位图数据 位图数据是 ...
在IT领域,C语言是一种基础且强大的编程语言,被广泛应用于系统编程、嵌入式开发以及各种底层操作。...但作为初学者的参考,这个简单的C语言BMP读写程序已经足够揭示许多基本概念,帮助开发者迈入图像处理的世界。
- 图像处理库:在实际开发中,可以使用如OpenCV、FreeImage等库来简化BMP文件的读写操作。 - 色彩空间转换:BMP文件通常以RGB格式存储,但可能需要转换为其他色彩空间,如CMYK、HSV等。 - 图像操作:包括缩放、...
纯C语言读写24BMP文件,32位BMP转24位BMP,读写8位BMP,二值化程序 详见:https://blog.csdn.net/libizhide/article/details/104144513
根据给定代码,我们可以分步骤地了解如何用C语言读取BMP文件: 1. **引入必要的库** - `<windows.h>`: 提供了Windows平台下的文件操作API。 - `<stdio.h>`: 标准输入输出函数。 - `<stdlib.h>`: 包含动态内存...
本篇文章主要介绍如何使用C语言进行BMP图像的基本读取、写入以及像素级别的操作。 #### 二、BMP图像基本概念 BMP图像由文件头、信息头和像素数组三部分组成: - **文件头**:包含文件类型等基本信息。 - **信息头**...
C语言作为基础的编程语言,虽然没有内置的图形库来直接处理BMP文件,但通过理解BMP文件的结构,我们可以用C语言编写程序来读取、修改和保存BMP图像。本文将详细介绍如何利用C语言操作BMP文件,以及获取图像的长宽...
压缩包内包含报告及说明文档。源码环境是VC6,在VS内稍做修改之后也可运行。代码是我大一时所写,可能有部分不妥之处,欢迎指正。由于是比赛作品直接压缩上传,压缩包内包含作者信息、还望尊重作者,不喜勿喷,谢谢...
用C语言读取BITMAP文件,此源码默认读取当前目录下的1.bmp。可以改成处理其他BMP文件。
在提供的"生成位图.c"源代码中,你可以看到上述步骤的具体实现,包括如何创建并初始化这些结构体,如何生成像素数据,以及如何使用C语言的文件I/O函数进行操作。执行生成位图.exe文件,将会依据源代码逻辑生成一个...
纯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);
在C语言中,对BMP文件进行读写操作是一项基础但重要的技能,这对于图像处理和计算机图形学领域的开发至关重要。本文将详细介绍如何使用C语言进行BMP文件的读取与写入操作,并探讨相关的关键知识点。 首先,我们需要...
总的来说,调整BMP图像亮度是一个涉及到文件读写、图像处理和基本数学运算的过程,通过C语言实现可以提供较高的效率和灵活性。在编程实践中,可以结合特定需求优化算法,比如使用并行处理来加速对大量像素的操作。
C语言中可以使用标准库如`fread`和`fwrite`进行文件读写,`malloc`分配内存,以及自定义函数处理像素数据。 为了优化效率,可以考虑使用滑动窗口法,避免重复计算邻域像素。同时,处理边界问题时,可选择镜像边界...
256级灰度BMP文件读写的源代码+c语言图像处理 本文档主要介绍了256级灰度BMP文件的读写源代码,以及c语言图像处理的实现。下面是对该文档中所涉及到的知识点的详细解释: 一、BMP文件格式 BMP(Bitmap)是一种...
在IT领域,BMP(Bitmap)位图是一种常见的图像文件格式,它以未压缩的...而C语言的BMP读写封装源码则为这些操作提供了基础。同时,配合PDF文档的详细分析,可以更好地理解BMP文件的内部机制,进一步提升图像处理能力。
接下来,我们将深入探讨BMP文件格式以及如何用C语言进行读写操作。 BMP文件结构主要包括以下几个部分: 1. 文件头(File Header):这是BMP文件的起始部分,包含14个字节,用来标识文件类型和文件大小。其中,前两...
1. **文件读写**:在C语言中,可以使用`fopen`、`fread`和`fwrite`等函数来读取和写入文件。在BMP2JPG程序中,我们需要先读取BMP文件的头信息,然后读取像素数据。 2. **BMP文件头解析**:BMP文件通常由文件头、...
2. **打开文件**:使用`fopen()`函数打开BMP文件,一般以二进制模式("rb"或"wb")进行读写。 3. **读取文件头**:通过`fread()`函数读取文件头数据,然后解析这些数据以获取图像的基本信息。 4. **分配内存**:...