2019独角兽企业重金招聘Python工程师标准>>>

CTF做了图片的隐写题,还没有形成系统的认识,先来总结一下BMP图的组成,并通过将彩色图转为二值图的例子加深下理解。

只写了位图二进制文件的格式和代码实现,至于诸如RGB色彩和调色板是什么的一些概念就不啰嗦了。

BMP位图文件格式

BMP文件由文件头、位图信息头、调色板和图形数据四部分组成,真彩色图是没有调色板的。每部分的具体结构在代码中具体列出并解释。

结构体的对齐

定义文件头部各结构体时要注意对齐的问题,至于什么是结构体对齐,请看这篇博文,写的很详细http://www.cnblogs.com/motadou/archive/2009/01/17/1558438.html

位图的四字节对齐

这个对齐是位图每行像素的对齐,不要和上面的结构体对齐混淆,每行像素所占字节数必须是4字节的整数倍,不足的要填充,这时因为内存分配单位是32位的,即4字节,读入的每行像素是连续的,不能和其他行共占一个内存单位

彩色图转为灰度图

RGB共有256种灰色分量,就是R=G=B时的色彩是灰色的,所以可以用一个字节来表示,将彩色图转化为灰度图就是让真彩色图的三个颜色分量等于一个相同的数值,具体等于多少可以与多种方法,比如求三个分量的平均值,取三个分量的最大值或者使其中两个分量等于另一个分量的值,还有一种常用的方法是取加权平均值,根据这个很著名的心理学公式Gray = R*0.299 + G*0.587 + B*0.114

灰度图转化为二值图

二值图只有两个颜色,黑和白,而灰度有256种颜色,将灰度转化为二值是选取一个阈值,将灰度值大于这个阈值的置成白色,反之为黑色,关于这个阈值如何选取和作用范围也有多种方法,不再赘述,为了简单我在全局范围内选用一个固定的阈值190(针对我这张测试图片,手敲了个190,转化的效果还可以)二值图只有两个索引,可以用1bit表示,但是我写的程序是用1个字节表示的,至于如何压缩,看你喽。。。

说了这么多,还是看代码吧,这样更容易理解,额,好像几乎给每行都写了注释╮(╯▽╰)╭,不要嫌我墨迹

1 /*2 Author:蔚蓝行3 Blog:http://www.cnblogs.com/duanv/4 */5 #include <stdio.h>6 #include <stdlib.h>7 8 /*位图文件头*/9 #pragma pack(1)//单字节对齐10 typedef struct tagBITMAPFILEHEADER11 {12   unsigned char bfType[2];//文件格式13   unsigned int bfSize;//文件大小14   unsigned short bfReserved1;//保留15   unsigned short bfReserved2;//保留16   unsigned int bfOffBits;//数据偏移量17 }fileHeader;18 #pragma pack()19 20 /*位图信息头*/21 #pragma pack(1)22 typedef struct tagBITMAPINFOHEADER23 {24   unsigned int biSize;//BITMAPINFOHEADER结构所需要的字数25   int biWidth;//图像宽度,像素为单位26   int biHeight;//图像高度,像素为单位,为正数,图像是倒序的,为负数,图像是正序的27   unsigned short biPlanes;//为目标设备说明颜色平面数,总被置为128   unsigned short biBitCount;//说明比特数/像素29   unsigned int biCompression;//说明数据压缩类型30   unsigned int biSizeImage;//说明图像大小,字节单位31   int biXPixPerMeter;//水平分辨率,像素/米32   int biYPixPerMeter;//垂直分辨率33   unsigned int biClrUsed;//颜色索引数34   unsigned int biClrImportant;//重要颜色索引数,为0表示都重要35 }fileInfo;36 #pragma pack()37 38 /*调色板结构*/39 #pragma pack(1)40 typedef struct tagRGBQUAD41 {42   unsigned char rgbBlue;//蓝色分亮度43   unsigned char rgbGreen;//绿色分亮度44   unsigned char rgbRed;//红色分亮度45   unsigned char rgbReserved;46 }rgbq;47 #pragma pack()48 49 int main()50 {51   /*变量声明*/52   FILE *fpBMP,*fpTwoValue;//源文件fpBMP,目标文件fpTwoValue53   54   fileHeader *fh;//位图文件头55   fileInfo *fi;//位图信息头56   rgbq *rg;//调色板57 58   int i,j,k=0;59   unsigned char *a;//存储源图每行像素值60   unsigned char b;//存储每个像素的灰度值或二值61   unsigned char *c;//存储每行像素的二值62   63   /********************************************************************/64 65   /*打开源文件,创建输出文件*/66   if((fpBMP=fopen("/Users/SPY/Desktop/1.bmp","rb"))==NULL){67     printf("file open failed");68     exit(0);69   }70   71   if((fpTwoValue=fopen("/Users/SPY/Desktop/2.bmp","wb"))==NULL){72     printf("file creat failed");73     exit(0);74   }75   76   /********************************************************************/77   78   /*创建位图文件头,信息头,调色板*/79   fh=(fileHeader *)malloc(sizeof(fileHeader));80   fi=(fileInfo *)malloc(sizeof(fileInfo));81   rg=(rgbq *)malloc(2*sizeof(rgbq));82   83   /*读入源位图文件头和信息头*/84   fread(fh,sizeof(fileHeader),1,fpBMP);85   fread(fi,sizeof(fileInfo),1,fpBMP);86 87   /*修改文件头,信息头信息*/88   fi->biBitCount=8;//转换成二值图后,颜色深度由24位变为8位89   fi->biSizeImage=((fi->biWidth+3)/4)*4*fi->biHeight;//每个像素由三字节变为单字节,同时每行像素要四字节对齐90   fi->biClrUsed=2;//颜色索引表数量,二值图为291   fi->biClrImportant=0;//重要颜色索引为0,表示都重要92   fh->bfOffBits=sizeof(fileHeader)+sizeof(fileInfo)+2*sizeof(rgbq);//数据区偏移量,等于文件头,信息头,索引表的大小之和93   fh->bfSize=fh->bfOffBits+fi->biSizeImage;//文件大小,等于偏移量加上数据区大小94   rg[0].rgbBlue=rg[0].rgbGreen=rg[0].rgbRed=rg[0].rgbReserved=0;//调色板颜色为黑色对应的索引为095   rg[1].rgbBlue=rg[1].rgbGreen=rg[1].rgbRed=255;//白色对应的索引为196   rg[1].rgbReserved=0;97 98   /********************************************************************/99
100   /*将位图文件头,信息头和调色板写入文件*/
101   fwrite(fh,sizeof(fileHeader),1,fpTwoValue);
102   fwrite(fi,sizeof(fileInfo),1,fpTwoValue);
103   fwrite(rg,2*sizeof(rgbq),1,fpTwoValue);
104
105   /*将彩色图转为二值图*/
106   a=(unsigned char *)malloc((fi->biWidth*3+3)/4*4);//给变量a申请源图每行像素所占大小的空间,考虑四字节对齐问题
107   c=(unsigned char *)malloc((fi->biWidth+3)/4*4);//给变量c申请目标图每行像素所占大小的空间,同样四字节对齐
108
109   for(i=0;i<fi->biHeight;i++){//遍历图像每行的循环
110     for(j=0;j<((fi->biWidth*3+3)/4*4);j++){//遍历每行中每个字节的循环
111         fread(a+j,1,1,fpBMP);//将源图每行的每一个字节读入变量a所指向的内存空间
112         //printf("%d ",a[j]);
113     }
114     for(j=0;j<fi->biWidth;j++){//循环像素宽度次,就不会计算读入四字节填充位
115         b=(int)(0.114*(float)a[k]+0.587*(float)a[k+1]+0.299*(float)a[k+2]);//a中每三个字节分别代表BGR分量,乘上不同权值转化为灰度值
116         //printf("%d",b);
117         if(190<=(int)b) b=1;//将灰度值转化为二值,这里选取的阈值为190
118         else b=0;
119         c[j]=b;//存储每行的二值
120         k+=3;
121     }
122     fwrite(c,(fi->biWidth+3)/4*4,1,fpTwoValue);//将二值像素四字节填充写入文件,填充位没有初始化,为随机值
123     k=0;
124   }
125
126   /********************************************************************/
127
128   /*释放内存空间,关闭文件*/
129   free(fh);
130   free(fi);
131   free(rg);
132   free(a);
133   free(c);
134   fclose(fpBMP);
135   fclose(fpTwoValue);
136   printf("success!\n");
137   return 0;
138 }

转载于:https://my.oschina.net/HeroOneHY/blog/910446

C语言实现将彩色BMP位图转化为二值图相关推荐

  1. C语言实现将彩色bmp图像转化为灰图、灰度图像反色

    彩色图像转灰度图像 彩色(24位)bmp图像结构: typedef struct{bitmapFileHeader bfHeader;bitmapInfoHeader biHeader;unsigne ...

  2. 利用OpenCV和C++实现由RGB图像转化为灰度图,再将灰度图转化为二值图的程序

    #include<opencv2\opencv.hpp> #include<opencv2/imgproc/imgproc.hpp> #include<opencv2\i ...

  3. c语言读取24位bmp图像,[原创]在TC下显示24位真彩色BMP位图

    [原创]在TC下显示24位真彩色BMP位图 在TC下显示24位BMP 虽然在TC显示24位图像上的速度远远比不上256色的速度快,但是真彩色色彩带给我们的视觉上的冲击是256色远远不能达到的.我们今天 ...

  4. BMP位图转为RGB三通道图

    文章目录 读取BMP位图转为RGB三通道图 注意 相关/参考链接 本人机器开发环境 用到的图像 大小端模式介绍: 完整代码: 结果 读取BMP位图转为RGB三通道图 个人总结,目的是给自己日后参考,或 ...

  5. c语言实现灰度图转换为二值图

    转载自:https://www.cnblogs.com/wd1001/p/4571916.html c语言实现灰度图转换为二值图 将上篇得到的灰度图转换为二值图,读取像素数据,低于某一值置0,否则设置 ...

  6. 彩色图、灰度图和二值图

    首先计算机中图像是用矩阵存储的,所以在分析图像时,应当用矩阵的眼光来看待 1.RGB模式(百万种颜色) 2.CMYK模式(四种印刷色) 3.索引模式(256种颜色) 4.灰度模式(256级灰度) 5. ...

  7. OpenCV(实战)二值图颜色填充(彩色图形、硬币)

    目录 一.彩色图形填充 1.初始效果展示 2.试错过程: 1.试错1:锐化显示所有图片 2.试错2:用礼帽提取出明亮部分 3.正确方式:直接对图片亮度增强(不用形态学处理) 总代码 二.硬币填充 1. ...

  8. C语言二值图的腐蚀膨胀及开闭运算

    (M2C系列)C语言二值图的形态学腐蚀膨胀及开闭运算 一.结构元 二.腐蚀 三.膨胀 四.开闭运算 五.其他 by HPC_ZY 由于剧情,需要纯C(不用三方库)实现图像算法.但作为一名MATLAB老 ...

  9. R语言游程检验:使用runs.test函数对二值序列数据执行游程检验(检验序列是否是随机的)

    R语言游程检验:使用runs.test函数对二值序列数据执行游程检验(检验序列是否是随机的) 目录

最新文章

  1. 【深度学习入门到精通系列】Recurrent和Residual解释
  2. 问题 1436: 地宫取宝 (dp)
  3. Yum卸载软件并删除依赖,下载离线rpm包,制作拷贝rpm包dockerfile
  4. cfs调度算法JAVA实现_关于CFS/BFS调度算法
  5. Python PycURL 网络编程
  6. 使用html记笔记,开始学习HTML,并记下笔记
  7. 数据库AngularJs
  8. java html转图片_Python一键转Java?“Google翻译”你别闹
  9. java mvc .net mvc_.NET MVC 和 JAVA MVC有什么区别?
  10. Divide Groups(分组)(二分图染色)
  11. java kml_从Java中的KML文件中提取坐标
  12. linux nfs共享目录访问速度慢,linux之间共享文件夹选nfs还是选samba--
  13. ElasticSearch(8)-分布式搜索
  14. coap python3_MQTT、CoAP
  15. 几种数据增强:Mixup,Cutout,CutMix 和yolov4中的 Mosaic
  16. 海航金鹿公务机队规模稳居亚太之首;奥森多生物科技创新中心在沪揭牌 | 美通企业日报...
  17. strstr()函数
  18. 俯仰角与横滚角的介绍
  19. 【自然语言处理】实验1布置:Word2Vec TransE案例
  20. oracle自动恢复数据库文件,只有数据文件情况下恢复Oracle数据库

热门文章

  1. 用python写生日快乐说说_祝自己生日快乐的说说
  2. webpy模版中写JS代码的陷阱
  3. Java-opts变量没生效,使用JAVA_OPTS env变量运行java无效
  4. Rust语言正在兴起,Java、Python、C的末日来临?
  5. 日志系统新贵,Loki到底优秀在哪里?
  6. 变量 内存 分配 ios iphone
  7. Altium Designer 2020 PCB 插入图片logo的方法
  8. 【Python】—— pipenv使用小结
  9. Windows编程(2)
  10. VB中MID如何使用