精华内容
下载资源
问答
  • 2022-03-18 18:10:37
     最近一段时间我学习了计算机图像处理这门课程,通过这门课程的学习,我了解到了图片具有灰度和彩色的区别,并且通过具体的代码可以将一些图片数据进行读写与转化。
    

    第一部分:BMP图像的读写
    1.BMP图像的读:
    (1)首先定义BMP文件头和信息头变量BITMAPFILEHEADER bf; //BMP文件头结构体BITMAPINFOHEADER bi; //BMP信息头结构体

    (2)创建文件输入流 fp
    fp=fopen(fileName,“rb”); //fileName为BMP图像文件名

    (3)读取信息头、文件头fread(&bf,sizeof(BITMAPFILEHEADER),1,fp); fread(&bi,sizeof(BITMAPINFOHEADER),1,fp);

    注:经过这两条程序把BMP图像的信息头、文件头赋给bf和bi变量,可以根据bf和bi得到图像的各种属性。

    (4) 读取BMP调色板fread(ipRGB2,sizeof(RGBQUAD),256,fp);

    (5)读取BMP位图数据定义一个二维数Imgdata来存取BMP位图数据。
    unsigned char * * Imgdata;
    Imgdata=new unsigned char*[bi.biHeight]; //声明一个指针数组
    for ( i=0;i<bi.biHeight;i++)
    Imgdata[i]=new unsigned char[(bi.biWidth3+3)/44]; //每个数组元素也是一个指针数组
    for ( i=0;i<bi.biHeight;i++ )
    for(j=0;j<(bi.biWidth3+3)/44;j++)
    fread(&Imgdata[i][j],1,1,fp);//每次只读取一个字节,存入数组

    2.BMP图像的写:
    (1)创建一个输出流fp fp=fopen(“mybmp.bmp”,“wb”);

    (2) 写BMP图像的信息头、文件头fwrite(&bf2,sizeof(BITMAPFILEHEADER),1,fp); fwrite(&bi2,sizeof(BITMAPINFOHEADER),1,fp);

    (3) 写BMP调色板fwrite(ipRGB2,sizeof(RGBQUAD),256,fp);

    (4) 写BMP图像的位图数据部分
    for (i=(bi.biHeight)-1 ;i>=0;i–)
    for (j=0 ;j<(bi.biWidth3+3)/44;j++)
    fwrite(&Imgdata[i][j],1,1,fp);

    注意:将图片信息导入到文件里(导入的图像数据与实际图像数据上下顺序颠倒,最后一行数据应该放在第一行,以此类推)

    第二部分:主程序部分,利用上述函数,即可实现BMP图的存储与处理
    #include “hxlbmpfile.h”
    void ImageProcessing(HXLBMPFILE* bmp) {
    int i = 0, j = 0;
    HXLBMPFILE bf;
    bf.iImagew = bmp->iImagew;
    bf.iImageh = bmp->iImageh;
    bf.iYRGBnum = bmp->iYRGBnum;
    if (!bf.IspImageDataOk()) return;
    for (i = 0; i < bf.iImageh; i++)
    for (j = 0; j < bf.iImagew; j++)
    {
    bf.pDataAt(i)[j] = 255 - bmp->pDataAt(i)[j];
    }
    bf.SaveBMPFile(“2.bmp”);
    }

    int main(int argc, char* argv[]) {
    HXLBMPFILE bmpfile;
    if(!bmpfile.LoadBMPFile(“C:\Users\lenovo\Downloads\b8color.bmp”))
    {printf(“Load BMP file failed.”);return 1;}// do other processing with the imagedata
    ImageProcessing(&bmpfile);
    printf(“program ends!\n”);
    return 0;
    }
    函数大体可以不发生改变,只需要改变能够决定图片处理色度部分的具体函数就可以进行灰度图片与彩色图片之间的转化。

    更多相关内容
  • BMP图像处理

    2015-05-16 21:53:01
    图像处理的基本操作都有针对bmp进行操作的基于vc++下的MFC
  • bmp图像处理

    2018-09-25 16:05:32
    关于图像旋转,并不难。只需要搞清楚像素坐标变换公式就行。我以图像的中心点为坐标原点。先把像素在目标图像中的位置变化为坐标系中的位置,做旋转变换求出变换之前的在坐标系中的坐标,再变换为在图片中的位置。 ...
  • qt 图像处理 上下翻转 放大缩小 二值化 反向 去除噪点 裁剪 自定义txt bin读取 基本作业里的啥都有,要求超过50个子,多说点废话,想下就下,反正必然能跑,记得删除user,然后直接点pro
  • lenna.bmp 图像处理 经典图片 bmp lenna图 彩色 256*256 192kb 欢迎下载 这么经典的东西,又很难找,就不要积分了:)
  • 1. 24位图彩色BMP图像文件的结构分析; 2. 24位图彩色BMP图像文件的读写; 3. 24位图彩色BMP图像文件的置固定值处理、反色处理、平滑处理
  • BMP图像处理VC++

    2013-01-12 12:11:43
    VC6.0下实现图像的基本操作,包括读取图像、基本变换、直方图处理等一些工作,帮助理解windows下bmp图像的基本结构和操作。
  • Bmp图像处理.zip

    2019-07-05 14:57:24
    C语言实现了对BMP图像的读取、存入、水平翻转、竖直翻转、马赛克模糊处理、灰度二极化处理,有代码注释
  • BMP图像处理基本库

    2013-04-15 14:12:56
    这是一个BMP位图处理的动态链接库,实现最基本的图像读写功能,包括了图像读取、存储、创建以及绘制这四个基本功能。
  • 数字图像处理常用图片BMP
  • vc MFC bmp 图像处理

    2014-05-04 12:23:12
    系统介绍了一些通过vc对bmp位图的操作
  • 原理参考:https://blog.csdn.net/liyuan02/article/details/6750828 实现对对任意角度的旋转,具体... } 原图 右旋转30度 右旋转45 右旋转60度 右旋转90度 后续持续更新用C语言实现图像处理算法,敬请期待,欢迎关注。

    原理参考:https://blog.csdn.net/liyuan02/article/details/6750828

    实现对对任意角度的旋转,具体数学推导网上找。如果各位读者需要使用,只需要将打开文件的位置改为你的位置,输入不同的角度即可:

    #include #include #include #include #define CV_PI 3.1415926

    int main(){

    FILE *fp = fopen("./01.bmp", "rb");

    if (fp == 0){

    printf("文件打开失败\n");

    return 0;

    }

    BITMAPFILEHEADER fileHead;

    BITMAPINFOHEADER infoHead;

    fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);

    fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);

    int width = infoHead.biWidth;

    int height = infoHead.biHeight;

    int biCount = infoHead.biBitCount;

    int lineByte = (width*biCount / 8 + 3) / 4 * 4;

    RGBQUAD *pColorTable;

    pColorTable = new RGBQUAD[256];

    fread(pColorTable, sizeof(RGBQUAD), 256, fp);

    unsigned char *pBmpBufSrc,*pBmpBufDst;

    pBmpBufSrc = new unsigned char[lineByte*height];

    fread(pBmpBufSrc, lineByte*height, 1, fp);

    fclose(fp);

    double angle;

    printf("请输入需要旋转的角度: ");

    scanf("%lf", &angle);

    double sita = angle*CV_PI / 180;

    double a = (width - 1) / 2;

    double b = (height - 1) / 2;

    double x1 = -a*cos(sita) - b*sin(sita);

    double y1 = -a*sin(sita) + b*cos(sita);

    double x2 = a*cos(sita) - b*sin(sita);

    double y2 = a*sin(sita) + b*cos(sita);

    double x3 = a*cos(sita) + b*sin(sita);

    double y3 = a*sin(sita) - b*cos(sita);

    double x4 = -a*cos(sita) + b*sin(sita);

    double y4 = -a*sin(sita) - b*cos(sita);

    int w1 = round(fmax(abs(x1 - x3), abs(x2 - x4)));

    int h1 = round(fmax(abs(y1 - y3), abs(y2 - y4)));

    double c = (w1 - 1) / 2;

    double d = (h1 - 1) / 2;

    double f1 = -c*cos(sita) + d*sin(sita) + a;

    double f2 = -c*sin(sita) - d*cos(sita) + b;

    int lineByte1 = (w1*biCount / 8 + 3) / 4 * 4;

    pBmpBufDst = new unsigned char[lineByte1*h1];

    for (int i = 0; i < h1; ++i){

    for (int j = 0; j < w1; ++j){

    unsigned char *p;

    p = (unsigned char *)(pBmpBufDst + i*lineByte1 + j);

    (*p) = 255;

    }

    }

    for (int i = 0; i < h1; ++i){

    for (int j = 0; j < w1; ++j){

    int x = round(j*cos(sita) - i*sin(sita) + f1);

    int y = round(j*sin(sita) + i*cos(sita) + f2);

    if (x>0 && x0 && y < height){

    unsigned char *p1, *p2;

    p1 = (unsigned char *)(pBmpBufDst + i*lineByte1 + j); // 新图像

    p2 = (unsigned char *)(pBmpBufSrc + y*lineByte + x); // 原图像

    (*p1) = (*p2);

    }

    }

    continue;

    }

    char *DstName = "rotate.bmp";

    FILE *fpo = fopen(DstName, "wb");

    if (fpo == 0)

    return 0;

    int colorTableSize = 0;

    if (biCount == 8)

    colorTableSize = 1024;

    BITMAPFILEHEADER dstFileHead;

    dstFileHead.bfOffBits = 14 + 40 + colorTableSize;

    dstFileHead.bfReserved1 = 0;

    dstFileHead.bfReserved2 = 0;

    dstFileHead.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTableSize + lineByte1*h1;

    dstFileHead.bfType = 0x4D42;

    fwrite(&dstFileHead, sizeof(dstFileHead), 1, fpo);

    BITMAPINFOHEADER dstInfoHead;

    dstInfoHead.biBitCount = biCount;

    dstInfoHead.biClrImportant = 0;

    dstInfoHead.biClrUsed = 0;

    dstInfoHead.biCompression = 0;

    dstInfoHead.biHeight = h1;

    dstInfoHead.biPlanes = 1;

    dstInfoHead.biSize = 40;

    dstInfoHead.biSizeImage = lineByte1*h1;

    dstInfoHead.biWidth = w1;

    dstInfoHead.biXPelsPerMeter = 0;

    dstInfoHead.biYPelsPerMeter = 0;

    fwrite(&dstInfoHead, sizeof(BITMAPINFOHEADER), 1, fpo);

    fwrite(pColorTable, sizeof(RGBQUAD), 256, fpo);

    fwrite(pBmpBufDst, lineByte1*h1, 1, fpo);

    fclose(fpo);

    system("pause");

    return 1;

    }

    原图                             右旋转30度                                      右旋转45                                 右旋转60度                           右旋转90度

    67c680e17e2bf48fd8dafbe7b6b6c3e1.png   e44432c7f188dae9827386839236f6d1.png  fcd37f24a5a46d15c9fb897916d36bfb.png7d5fff2dc37caf4eae27d96d0e844ed1.png256d5d9de9ee17a2b9162276910180fe.png

    后续持续更新用C语言实现图像处理算法,敬请期待,欢迎关注。

    展开全文
  • C++BMP图像处理

    2014-08-09 17:07:09
    C++BMP图像处理。加载位图 切割位图 拼接位图 位图像素反转
  • BMP图像处理软件的设计和实现论文.doc
  • BMP图像处理软件

    2015-08-13 10:30:42
    要是对所获得的BMP位图进行读取处理,其中主要包括放大缩小、点运算、灰度变换、图像镜像、图像锐化、拉普拉斯变换等几大模块,对基本图像处理功能比较多。
  • 用于生成处理bmp图像的思路,其中包括最基本的bmp图像打开,放大,缩小,灰度变换,去噪等.
  • BMP图像处理接口一

    2014-05-23 16:16:09
    BMP图像处理接口一,做为自用备份暂时只完成,BMP头的处理,以及完成一张BMP图像嵌入到另一张BMP图像中,所用bmp图片为24位。其他接口如BMP24位16等互转
  • BMP图像处理ppt

    2015-06-01 15:03:09
    BMP位图文件可看成由4个部分组成 位图文件头(bitmap-file header) 位图信息头(bitmap-information header) 彩色表(color table) 位图的字节(byte)阵列
  • BMP图像处理程序设计》是一个处理32位非压缩的真彩BMP图像处理软件。软件采用经典的Windows图形操作界面。软件最主要有向左旋转90度、向右旋转90度、旋转180度和对图像进行锐化处理,处理完后能对图像进行保存和...
  • 实现图像旋转,首先要对图像的存储,图像的读写比较清楚,在此基础上进行线性变换。以下代码为逆时针旋转90度,后续会给出旋转任意角度的代码: 核心还是掌握旋转时的前后变换。变换的过程可以归结为:首先将图像...

     实现图像旋转,首先要对图像的存储,图像的读写比较清楚,在此基础上进行线性变换。以下代码为逆时针旋转90度,后续会给出旋转任意角度的代码:

    核心还是掌握旋转时的前后变换。变换的过程可以归结为:首先将图像坐标变换为数学坐标,然后在数学坐标上进行变换,然后在进行逆变换,得到在图像坐标上的变换。同时需要求出各个变换的逆变换。

    
    #include <Windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(){
    	FILE *fp = fopen("./01.bmp", "rb");
    	if (fp == 0){
    		printf("文件打开失败\n");
    		return 0;
    	}
    
    	BITMAPFILEHEADER fileHead;
    	BITMAPINFOHEADER infoHead;
    	fread(&fileHead, sizeof(BITMAPFILEHEADER), 1, fp);
    	fread(&infoHead, sizeof(BITMAPINFOHEADER), 1, fp);
    
    	int width = infoHead.biWidth;
    	int height = infoHead.biHeight;
    	int biCount = infoHead.biBitCount;
    	int lineByte = (width*biCount / 8 + 3) / 4 * 4;
    
    	RGBQUAD *pColorTable;
    
    	pColorTable = new RGBQUAD[256];
    	fread(pColorTable, sizeof(RGBQUAD), 256, fp);
    
    	unsigned char *pBmpBuf;
    	pBmpBuf = new unsigned char[lineByte*height];
    	fread(pBmpBuf, lineByte*height, 1, fp);
    	fclose(fp);
    	
    	// 右旋转90
    	unsigned char *pBmpBuf3;
    	int lineByte3 = (height*biCount / 8 + 3) / 4 * 4;
    
    	pBmpBuf3 = new unsigned char[lineByte3*width];
    	for (int i = 0; i < width; ++i){
    		for (int j = 0; j < height; ++j){
    			unsigned char *p;
    			p = (unsigned char *)(pBmpBuf3 + lineByte3*i + j);
    			(*p) = 255;
    		}
    	}
    	for (int i = 0; i < width; ++i){
    		for (int j = 0; j < height; ++j){
    			unsigned char *p,*p3;
    			p = (unsigned char *)(pBmpBuf + lineByte*j + i);  // 原图像
    			p3 = (unsigned char *)(pBmpBuf3 + lineByte3*i + height-j-1);// 新图像
    			(*p3) = (*p);
    		}
    	}
    
    	FILE *fpo = fopen("./rotate90N.bmp", "wb");
    	if (fpo == 0)
    		return 0;
    	
    	fwrite(&fileHead, sizeof(BITMAPFILEHEADER), 1, fpo);
        
    	BITMAPINFOHEADER infoHead3;
    	infoHead3.biBitCount = biCount;
    	infoHead3.biClrImportant = 0;
    	infoHead3.biClrUsed = 0;
    	infoHead3.biCompression = 0;
    	infoHead3.biHeight = width;
    	infoHead3.biPlanes = 1;
    	infoHead3.biSize = 40;
    	infoHead3.biSizeImage = lineByte3*width;
    	infoHead3.biWidth = height;
    	infoHead3.biXPelsPerMeter = 0;
    	infoHead3.biYPelsPerMeter = 0;
    
    	fwrite(&infoHead3, sizeof(BITMAPINFOHEADER), 1, fpo);
    	fwrite(pColorTable, sizeof(RGBQUAD), 256, fpo);
    	fwrite(pBmpBuf3, lineByte3*width, 1, fpo);
    	fclose(fpo);
    
    	system("pause");
    	return 1;
    }
    

    实验结果:

           原图                                         逆时针旋转90度

              

    后续持续更新用C语言实现图像处理算法,敬请期待,欢迎关注。

    展开全文
  • vs2010 BMP图像处理

    热门讨论 2014-04-14 10:05:51
    BMP图像的简单的处理,有读写和像素的简单处理,适用于初学者。
  • 创建一个基于对话框的应用程序,添加“打开”、“锐化”和退出按钮以及静态文本控件。当单击“打开”按钮时,可以打开一幅图片,单击“锐化”按钮时,可以实现图像的锐化。
  • 可以将24位BMP文件任意角度旋转。使用时只需将图片与此程序放在同一文件夹中,输入文件名,旋转角度即可。
  • 多媒体 - VC简单BMP图像处理源码
  • 基于MFC的bmp图像处理

    2014-05-12 08:59:39
    基于c++,利用MFC实现bmp图像一系列处理
  • 数字图像处理(一)——BMP图像的介绍和读取

    千次阅读 多人点赞 2020-03-03 10:34:35
    C(C++)语言实现BMP图像的读取,BMP图像的读取,BMP图像的介绍,数字图像处理,C(C++)语言读取BMP图像的像素值。

      数字图像处理的代码在网上已经非常普遍了,但是大部分文章中的代码都是针对某一个功能的,而且实现功能的编程语言种类非常多,这在小贾学习的过程中造成了很多的麻烦。所以小贾打算写几篇的文章来总结小贾在入门时候遇到的“坑”。如果您只想参考图像处理过程中的代码,您可以直接跳到文章的代码部分。小贾在代码中也会有代码的详细注释。当然,如果您刚刚入坑,小贾也会在文章中附加一些段落来帮你理解图像处理。

    1. 写在前面

    1.1. 先放一张图

    Lena.bmp
      熟悉图像处理的人一定认识这张图像。因为他们在实验或者项目任务中经常使用Lena图像。Lena图像已经成为被广泛使用的测试图像。今天,Lena图像的使用被认为是数字图像历史上最重要的事件之一1。如果你刚开始接触图像处理,那么恭喜你以后要经常见到这个图像了。

    1.2. 再说一种图像格式

      说完了上面的图片,那么接下来再了解一种图像格式:BMP。
      BMP是英文Bitmap(位图)的缩写,它是Windows操作系统中的标准图像文件格式2,其能够被多种Windows应用程序所支持。这种格式的特点是包含的图像信息比较丰富,几乎不进行压缩,但由此导致了它与生俱来的缺点——占用空间过大。

    1.3. 接着介绍一个头文件

      随着Windows的逐渐普及,支持BMP图像格式的应用软件越来越多。这主要是因为Windows把BMP作为图像的标准格式,并且内含了一套支持BMP图像处理的API函数。在C(C++)语言编程中,这套API函数的存在是以Windows.h头文件存在于系统中。在用C(C++)语言3编程实现图像处理的时候我们我们需要在代码最前端引用Windows.h头文件。
      Windows.h头文件中包含了windef.h、winnt.h、winbase.h、winuser.h、wingdi.h等头文件,涉及到了Windows内核API,图形界面接口,图形设备函数等重要的功能。

    2. BMP文件格式

      BMP文件格式4可分为文件信息头、位图信息和位图数据三部分。

    2.1. 文件信息头

      BMP文件头含有BMP文件的类型、大小和存放位置等信息。Windows.h中对其定义为:

    typedef struct tagBITMAPFILEHEADER{
    	WORD bftype; // 位图文件的类型,必须设置为BM
    	DWORD bfSize; // 位图文件的大小,以字节为单位
    	WORD bfReserved1; // 位图文件保留字,必须设置为0
    	WORD bfReserved2; // 位图文件保留字,必须设置为0
    	DWORD bfoffBits; // 位图数据相对于位图文件头的偏移量表示
    } BITMAPFILEHEADER;
    
    2.2. 位图信息

      位图信息用BITMAPINFO结构定义,它是由位图信息头(bitmap-information header)和彩色表(color table)组成,位图信息头用BITMAPINFOHEADER结构定义,彩色表用RGBQUAD结构定义。BITMAPINFO结构具有如下形式:

    typedef struct tagBITMAPINFO{
    	BITMAPINFOHEADER bmiHeader;
    	RGBQUAD bmiColor[];
    } BITMAPINFO;
    

      (1)bmiHeader是一个位图信息头(BITMAPINFOHEADER)类型的数据类型,用于说明位图的尺寸。BITMAPINFOHEADER的定义如下:

    typedef struct tagBITMAPINFOHEADER{
    	DWORD biSize; // bmiHeader结构的高度
    	DWORD biWidth; // 位图的宽度,以像素为单位
    	DWORD biHeight; // 位图的高度,以像素为单位
    	WORD biPlanes; // 目标设备的位平面数,必须为1
    	WORD biBitCount; // 每个像素的位数,必须是1(单色)、4(16色)、8(256色)或24(真彩色)
    	DWORD biCompression; // 位图的压缩类型,必须是0(不压缩)、1(BI-RLE8压缩类型)或2(BI-RLE4压缩类型)
    	DWORD biSizeImage; // 位图的大小,以字节为单位
    	DWORD biXPeIsPerMeter; // 位图的目标设备水平分辨率,以每米像素数为单位
    	DWORD biYPeIsPerMeter; // 位图的目标设备垂直分辨率,以每米像素数为单位
    	DWORD biClrUsed; // 位图实际使用的颜色表中的颜色变址数
    	DWORD biClrImpotant; // 位图显示过程中被认为重要颜色的变址数
    } BITMAPINFOHEADER;
    

      (2)bmiColor[ ]是一个颜色表,用于说明位图中的颜色。它有若干个表项,每一表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD的定义如下:

    typedef tagRGBQUAD{
    	BYTE rgbBlue;
    	BYTE rgbGreen;
    	BYTE rgbRed;
    	BYTE rgbReserved;
    } RGBQUAD;
    

      在RGBQUAD定义的颜色中,蓝色的亮度由rgbBlue确定,绿色的亮度由rgbGreen确定,红色的亮度由rgbRed确定。rgbReserved必须为0。
      例如:若某表项为00,00,FF,00,那么它定义的颜色为存红色。
      bmiColor[ ]表项的个数由biBiCount来定:
      当 biBitCount = 1、4、8 时,bmiColor[ ]分别有 2,16,256 个表项。若某点的像素值为 n,则该像素的颜色为bmiColor[n]所定义的颜色。
      当 biBitCount = 24 时,bmiColor[ ]的表项为空。位图阵列的每 3 个字节代表一个像素,3 个字节直接定义了像素颜色中蓝、绿、红的相对亮度,因此省去了bmiColor[ ]颜色。

    2.3. 位图数据

      位图阵列记录了位图的每一个像素值。在生成位图文件时,Windows从位图的左下角开始(即从左到右从下到上)逐行扫描位图,将位图的像素值一一记录下来。这些记录像素值的字节组成了位图阵列。位图阵列有压缩和非压缩两种存储格式。
      (1)非压缩格式。在非压缩格式中,位图的每个像素值对应位图阵列的若干位(bits),位图阵列的大小由位图的亮度、高度及位图的颜色数决定。
       a.位图扫描行与位图阵列的关系
      设记录一个扫描行的像素值需 n 个字节,则位图阵列的 0 至 n-1 个字节记录了位图的第一个扫描行的像素值;位图阵列的 n 至 2n-1 个字节记录了位图的第二个扫描行的像素值;依此类推,位图排列的 (m-1) x n 至 m x n - 1 个字节记录了位图的第 m 个扫描行的像素值。位图阵列的大小为 n * biHeight。
      当 (biWidth * biBitCount) mod32 = 0 时,n = (biWidth * biBitCount) / 8
      当 (biWidth * biBitCount) mod32 ≠ 0 时,n = (biWidth * biBitCount) / 8 + 4
      上式中 +4 而不是 +1 的原因是为了使一个扫描行的像素值占用位图阵列的字节数为 4 的倍数(Windows规定其必须在long边界结束),不足的位用 0 补充。
       b.位图像素值与位图阵列的关系(以第 m 扫描行为例)
      设记录第 m 个扫描行的像素值的 n 个字节分别为a0,a1,a2,···,则
      当 biBitCount = 1 时:a0 的 D7 记录了位图的第 m 个扫描的第 1 个像素值,D6位记录了位图的第 m 个扫描行的第 2 个像素值,···,D0 记录了位图的第 m 个扫描行的第 8 个像素值,a1 的 D7 位记录了位图的第 m 个扫描行的第 9 个像素值,D6 位记录了位图的第 m 个扫描行的第 10 个像素值··· ···
      当 biBitCount = 4 时:a0 的 D7 ~ D4 位记录了位图的第 m 个扫描行的第 1 个像素值,D3 ~ D0 位记录了位图的第 m 个扫描行的第 2 个像素值,a1 的 D7 ~ D4 位记录了位图的第 m 个扫描行的第 3 个像素值··· ···
      当 biBitCount = 8 时:a0 记录了位图的第 m 个扫描行的第 1 个像素值,a1 记录了位图的第 m 个扫描行的第 2 个像素值··· ···
      当 biBitCount = 24 时:a0、a1、a2 记录了位图的第 m 个扫描行的第 1 个像素值,a3、a4、a5 记录了位图的第 m 个扫描行的第 2 个像素值··· ···
      位图其他扫描行的像素值与位图阵列的对应关系与此相似。
      (2)压缩格式。Windows支持 BI_RLE8 及 BI_RLE4 压缩位图存储格式,压缩减少了位图阵列所占用的磁盘空间。
       a. BI_RLE8 压缩格式
      当biCompression = 1 时,位图文件采用此压缩编码格式。压缩编码以两个字节为基本单位。其中第一个字节规定了用两个字节所指定的颜色出现的连续像素的个数。
      例如,压缩编码 05 04 表示从当前位置开始连续显示 5 个像素,着 5 个像素的像素值均为 04。
      在第一个字节为零时,第二个字节有特殊的含义:0——行末;1——图末;2——转义后面的两个字节,这两个字节分别表示一个像素从当前位置开始的水平位移和垂直位移;n (0x003 < n < 0xFF)——转义后面的 n 个字节,其后的 n 像素分别用这 n 个字节所指定的颜色画出。注意:实际编码时必须保证后面的字节数是 4 的倍数,不足的位用 0 补充。
       b. BI_RLE4 压缩格式
      当 biCompression = 2时,位图文件采用此种压缩编码格式。它与 BI_RLE8 的编码方式类似,唯一的不同是:BI_RLE4 的一个字节包含了两个像素的颜色。当连续显示时,第一个像素按字节高四位规定的颜色画出··· ···直到所有像素都画出为止。
      归纳起来,BMP图像文件有下列四个特点:
       I. 改格式只能存放一幅图像。
       II. 只能存储单色、16色、256色或彩色四种图像数据之一。
       III. 图像数据有压缩或不压缩两种处理方式,压缩方式为:RLE_4 和 RLE_8。RLE_4只能处理 16 色图像数据;而 RLE_8 则只能压缩 256 色图像数据。
       IV. 调色板的数据存储结构较为特殊。

      看到这里BMP的文件格式就介绍完了,本次进行编码实现的主要是不压缩的数据格式,压缩的数据格式等到以后有机会再详细介绍。

    2.4. 再说一种坐标系

      说完了BMP文件格式,我们再说一说图像坐标系5,下面这张图片是小贾画的图像坐标系和图像的存储顺序。这张图可能有助于你理解下面代码中对于像素的提取。

    3. 编码实现

    3.1. 创建一个C(C++)项目

      首先我们打开任何一个能进行C语言编程的编译,建立一个空项目的控制台程序,新建一个CPP文件,并将Lena.bmp拷到项目文件夹中(这里我以Visual Studio 2015 为例,点击图片可以看大图)。
    新建项目图片1
    新建项目图片2
    新建项目图片3
    新建项目图片4
    在这里插入图片描述

    3.2. 编码

      在编译器中写上下面的代码(下面的代码是灰度图的读取,关于后面多波段的读取,我们以后在再介绍)。

    #include <stdio.h> // C语言代码中必须要引用的头文件
    #include <windows.h> // 图像读取的头文件
    
    // 使代码在新版本的VS中正常运行不报错
    #define _CRT_SECURE_NO_WARNINGS
    #pragma warning(disable:4996)
    
    // 定义一个结构体来读取BMP的信息
    typedef struct {
    	// 定义文件头信息
    	BITMAPFILEHEADER header;
    	// 定义位图信息头
    	BITMAPINFOHEADER info;
    	// 定义彩色表
    	RGBQUAD rgb[256];
    	// 定义位图数据指针
    	unsigned char *data;
    } BMP;
    
    // 读图像函数
    void bmpRead(const char *bmpPath, BMP &bmp) {
    	// 以二进制的方式打开图片
    	FILE *file = fopen(bmpPath, "rb");
    	// 读取文件信息头
    	fread(&bmp.header, sizeof(BITMAPFILEHEADER), 1, file);
    	// 读取位图信息头
    	fread(&bmp.info, sizeof(BITMAPINFOHEADER), 1, file);
    	// 读取彩色表
    	fread(&bmp.rgb, sizeof(RGBQUAD), 256, file);
    	// 定义位图数据内存大小
    	bmp.data = new unsigned char[bmp.info.biWidth * bmp.info.biHeight];
    	// 读取元素的位图数据
    	fread(bmp.data, sizeof(unsigned char), bmp.info.biWidth*bmp.info.biHeight, file);
    	// 关闭图片
    	fclose(file);
    }
    
    // 定一个函数将读取到bmp.data的像素灰度值存储到一个txt文档中
    void bmpCells(const char *pixelValuePath, BMP &bmp){
    	// 新建一个txt文件用于存储像素值
    	FILE *file = fopen(pixelValuePath, "w");
    	// 循环读取像素值
    	for (int i = 0; i < bmp.info.biHeight; i++)
    	{
    		for (int j = 0; j < bmp.info.biWidth; j++)
    		{
    			// 获取循环到像元的像素值
    			unsigned char pixel = bmp.data[j + i*bmp.info.biWidth];
    			// 这里我们打印一下读出的像元
    			printf("%d ", pixel);
    			// 保存到文件中
    			fprintf(file, "%d ", pixel);
    		}
    		// 打印一行后换行
    		printf("\n");
    		// 完成一行像素的保存后换行继续进行保存
    		fprintf(file, "\n");
    	}
    	// 关闭文件
    	fclose(file);
    }
    
    int main() {
    	// 定义图像结构体
    	BMP mbmp;
    	// 读取图像(如果不是按照本文的新建项目方法,建议使用绝对路径,否则可能会因为文件路径错误而报错。)
    	bmpRead("../lena.bmp", mbmp);
    	// 将像素值存储到一个txt文本中
    	bmpCells("../pixelValue.txt", mbmp);
    	// 删除指针,释放内存
    	delete[] mbmp.data;
    	// 使程序暂停,便于查看
    	scanf("……");
    
    	return 0;
    }
    

    4. 验证一下结果

    4.1. 结果图

      接下来让我们看一下运行的结果。
    在这里插入图片描述
    在这里插入图片描述

    4.2. 验证正确性

      如果你了解遥感图像处理,那么你一定会知道 ERDAS IMAGE 这个软件,现在我们就用这个软件来验证我们编码的结果是否正确。下图中是我们在ERDAS IMAGE中打开的图像像素值。
    在这里插入图片描述
      通过上面的初步对比,我们我们可以看出我们读取的像素值是正确的。

      这节的介绍我们到这里就结束了,有什么错误欢迎大家指出。下一节我继续介绍《数字图像处理(二)——BMP图像的统计》,下节将介绍如何获取图像像素的最小值、最大值、均值、标准差、计算图像的熵、以及统计图像灰度直方图。


    1. Lena图像:了解更多关于Lena图像的信息,请转到Lena图像的百度百科介绍↩︎

    2. 图像格式:BMP仅是众多图像格式中的一种,了解更多的格式请转到图像格式的百度百科介绍↩︎

    3. C语言编程入门教程:网上关于C语言的编程的内容很多。例如,菜鸟教程MOOC慕课平台。小贾这里给列出两种,仅供参考。 ↩︎

    4. BMP文件格式:关于BMP文件格式的介绍来源于《数字图像处理(第三版)》(贾永红版)。 ↩︎

    5. 图像坐标系:图像坐标系的介绍大家可以在百度百科中找到。 ↩︎

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 48,724
精华内容 19,489
关键字:

bmp图像处理

友情链接: PJXJJVL.rar