想了想发上来自己以后也好看看。
先直接上代码吧,有时间可能会写一下学习的过程
注:白平衡使用灰白世界算法

首先是源文件:

#define     _CRT_SECURE_NO_WARNINGS
#include "IMGVision.h"_inline void showBmpHead(tBITMAPFILEHEADER pBmpHead);
_inline void showBmpInfoHead(tBITMAPINFOHEADER pBmpInfo);
_inline uint8_t IMG_BMP_FILEINFOGET(const char* ORI_IMG);FILE* IMG;
unsigned short fileType;tBITMAPFILEHEADER BITMAPFILEHEADER;
tBITMAPINFOHEADER BITMAPINFOHEADER;
_tPixelInfo PixelInfo;struct rgbPerPixel
{unsigned char r;unsigned char g;unsigned char b;
};uint8_t IMG_Whitebalance(const char* ORI_IMG,const char* NEW_IMG)
{FILE* IMG_K;FILE* IMG_G;rgbPerPixel* Pc = (rgbPerPixel*)malloc(sizeof(rgbPerPixel));unsigned long r_SUM=0, g_SUM=0, b_SUM=0;unsigned char r_Aver, g_Aver, b_Aver;unsigned int Grey_Aver;double Kr, Kg, Kb;unsigned long IMGPixelcount;IMG = fopen(ORI_IMG, "rb");if (IMG == NULL){printf("图片打开失败,检查图片格式或是否有损\r\n");return -1;}fread(&fileType, 1, sizeof(unsigned short), IMG);if (fileType == 0x4d42){fread(&BITMAPFILEHEADER, 1, sizeof(tBITMAPFILEHEADER), IMG);fread(&BITMAPINFOHEADER, 1, sizeof(tBITMAPINFOHEADER), IMG);}else{printf("BMP图片类型不正确,请检查BMP图片的数据格式\r\n");fclose(IMG);return -2;}for (long i = (BITMAPINFOHEADER.biWidth * BITMAPINFOHEADER.biHeight); i > 0; i--){fread(Pc, 1, sizeof(rgbPerPixel), IMG);r_SUM = r_SUM + Pc->r;g_SUM = g_SUM + Pc->g;b_SUM = b_SUM + Pc->b;//printf("第%d个像素的累加值%d,%d,%d\r\n", i, r_SUM, g_SUM, b_SUM);//printf("第%d个像素RGB为 (%d,%d,%d)\r\n", i, Pc->r, Pc->g, Pc->b);}fclose(IMG);IMGPixelcount = BITMAPINFOHEADER.biWidth * BITMAPINFOHEADER.biHeight;r_Aver = r_SUM / IMGPixelcount;g_Aver = g_SUM / IMGPixelcount;b_Aver = b_SUM / IMGPixelcount;printf("R通道平均值为%0x\tG通道平均值为%0x\tB通道平均值为%0x\r\n",r_Aver,g_Aver,b_Aver);Grey_Aver = (r_Aver + g_Aver + b_Aver) / 3;if (Grey_Aver > 255)Grey_Aver = 255;Kr = (double)(Grey_Aver *1.0/ r_Aver);Kg = (double)(Grey_Aver *1.0/ g_Aver);Kb = (double)(Grey_Aver *1.0/ b_Aver);printf("三通道灰度平均值为%d\r\nR通道增益为%.5f\r\nG通道增益为%.5f\r\nB通道增益为%.5f\r\n",Grey_Aver,Kr,Kg,Kb);IMG_G = fopen(NEW_IMG, "wb");IMG_K = fopen(ORI_IMG, "rb");if (IMG_K == NULL){printf("图片打开失败,检查图片格式或是否有损\r\n");return -1;}fread(&fileType, 1, sizeof(unsigned short), IMG_K);if (fileType == 0x4d42){fread(&BITMAPFILEHEADER, 1, sizeof(tBITMAPFILEHEADER), IMG_K);fread(&BITMAPINFOHEADER, 1, sizeof(tBITMAPINFOHEADER), IMG_K);}else{printf("BMP图片类型不正确,请检查BMP图片的数据格式\r\n");fclose(IMG_K);return -2;}if (IMG_G == NULL){printf("文件建立失败...\r\n");return -3;}fwrite(&fileType, 2, 1, IMG_G);fwrite(&BITMAPFILEHEADER, sizeof(tBITMAPFILEHEADER), 1, IMG_G);fwrite(&BITMAPINFOHEADER, sizeof(tBITMAPINFOHEADER), 1, IMG_G);for (long i = (BITMAPINFOHEADER.biWidth * BITMAPINFOHEADER.biHeight); i > 0; i--){fread(Pc, 1, sizeof(rgbPerPixel), IMG_K);Pc->r = ((Pc->r) * Kr * 1.0); if ((Pc->r) > 255)Pc->r = 255;Pc->g = ((Pc->g) * Kg * 1.0); if ((Pc->g) > 255)Pc->g = 255;Pc->b = ((Pc->b) * Kb * 1.0); if ((Pc->b) > 255)Pc->b = 255;fwrite(Pc, 1, 3, IMG_G);//printf("第%d个像素RGB为 (%d,%d,%d)\r\n", i, Pc->r, Pc->g, Pc->b);}free(Pc);fclose(IMG_K);fclose(IMG_G);printf("\t图像白平衡处理完成,图片默认保存于自定义目录下\r\n\r\n");return 0;
}uint8_t IMG_GreyChange(const char* ORI_IMG,const char* NEW_IMG)
{uint8_t _IS_OPEN = IMG_BMP_FILEINFOGET(ORI_IMG);FILE* IMG_G;unsigned char Grey;if (_IS_OPEN == 0){printf("BMP图片信息读取成功\r\n");rgbPerPixel* Pc = (rgbPerPixel*)malloc(sizeof(rgbPerPixel));IMG_G = fopen(NEW_IMG, "wb");if (IMG_G == NULL){printf("文件建立失败...\r\n");return -2;}fwrite(&fileType, 2, 1, IMG_G);fwrite(&BITMAPFILEHEADER, sizeof(tBITMAPFILEHEADER), 1, IMG_G);fwrite(&BITMAPINFOHEADER, sizeof(tBITMAPINFOHEADER), 1, IMG_G);for (long i = (BITMAPINFOHEADER.biWidth * BITMAPINFOHEADER.biHeight); i > 0; i--){fread(Pc, 1, sizeof(rgbPerPixel), IMG);Grey = (Pc->r * 30 + Pc->g * 59 + Pc->b * 11 + 50) / 100;Pc->r = Pc->g = Pc->b = Grey;fwrite(Pc, 1, 3, IMG_G);//printf("第%d个像素RGB为 (%d,%d,%d)\r\n", i, Pc->r, Pc->g, Pc->b);}free(Pc);fclose(IMG);fclose(IMG_G);printf("\t图像灰值处理完成,图片保存于自定义目录下\r\n\r\n");return 0;}else if(_IS_OPEN == -1){printf("图片打开失败,检查图片格式或是否有损\r\n");printf("BMP图片读取失败...\r\n");return -1;}else{printf("BMP图片类型有误,请检查BMP文件数据格式\r\n");return-2;}
}uint8_t BMP_INFOPRINT(const char* BMP)
{IMG = fopen(BMP, "rb");if (IMG == NULL){printf("检查文件是否存在或者是否损坏\r\n");return -1;}fread(&fileType, 1, sizeof(unsigned short), IMG);if (fileType == 0x4d42){printf("BMP文件信息如下:\r\n");printf("文件标识符:%d\r\n", fileType);fread(&BITMAPFILEHEADER, 1, sizeof(tBITMAPFILEHEADER), IMG);showBmpHead(BITMAPFILEHEADER);fread(&BITMAPINFOHEADER, 1, sizeof(tBITMAPINFOHEADER), IMG);showBmpInfoHead(BITMAPINFOHEADER);fclose(IMG);return 0;}else{printf("BMP图片类型不正确,请检查BMP图片的数据格式\r\n");fclose(IMG);return -2;}
}_inline void showBmpHead(tBITMAPFILEHEADER pBmpHead)
{printf("BMP文件大小:%dkb\n", BITMAPFILEHEADER.bfSize / 1024);printf("保留字必须为0:%d\n", BITMAPFILEHEADER.bfReserved1);printf("保留字必须为0:%d\n", BITMAPFILEHEADER.bfReserved2);printf("位图数据偏移字节量:%d\n", BITMAPFILEHEADER.bfOffBits);
}_inline void showBmpInfoHead(tBITMAPINFOHEADER pBmpInfo)
{printf("文件类型:BMP\n");printf("信息头大小:%d\n", BITMAPINFOHEADER.biSize);printf("位图宽度:%d\n", BITMAPINFOHEADER.biWidth);printf("位图高度:%d\n", BITMAPINFOHEADER.biHeight);printf("图像位面数:%d\n", BITMAPINFOHEADER.biPlanes);printf("图像单个像素大小:%d\n", BITMAPINFOHEADER.biBitCount);printf("图像压缩方式:%d\n", BITMAPINFOHEADER.biCompression);printf("图像大小:%d\n", BITMAPINFOHEADER.biSizeImage);printf("水平方向分辨率:%d\n", BITMAPINFOHEADER.biXPelsPerMeter);printf("垂直方向分辨率:%d\n", BITMAPINFOHEADER.biYPelsPerMeter);printf("使用的颜色索引数:%d\n", BITMAPINFOHEADER.biClrUsed);printf("重要颜色索引数:%d\n", BITMAPINFOHEADER.biClrImportant);
}
_inline uint8_t IMG_BMP_FILEINFOGET(const char* ORI_IMG)
{IMG = fopen(ORI_IMG, "rb");if (IMG == NULL){return -1;}fread(&fileType, 1, sizeof(unsigned short), IMG);if (fileType == 0x4d42){fread(&BITMAPFILEHEADER, 1, sizeof(tBITMAPFILEHEADER), IMG);fread(&BITMAPINFOHEADER, 1, sizeof(tBITMAPINFOHEADER), IMG);return 0;}else{fclose(IMG);return -2;}
}

然后是头文件“IMGVision.h”:

#ifndef _IMG_VISION_H_
#define _IMG_VISION_H_#include <stdio.h>
#include <stdint.h>
#include <malloc.h>//14 Bytes 文件头信息块
typedef struct tBITMAPFILEHEADER
{//unsigned short       bfType;         //BMP : 0X4D42 WINDOWS读 42 4D  DEC= 19778unsigned int  bfSize;         //图片大小unsigned short        bfReserved1;    //保留字为0unsigned short       bfReserved2;    //保留字为0unsigned int bfOffBits;      //文件头到像素数据偏移量
};
//40 Bytes 图像描述信息块
typedef struct tBITMAPINFOHEADER
{unsigned int   biSize;         //此结构体大小long    biWidth;long    biHeight;unsigned short     biPlanes;       //平面显示属,一般显示器只有一个平面所以为1unsigned short        biBitCount;     //一个像素所占的位数,一般为24,带A通道的有32unsigned int    biCompression;  //图像数据压缩的类,0为不压缩unsigned int biSizeImage;    //像素数据所占的大小 =bfSize-bfOffBitslong  biXPelsPerMeter;//水平分辨率long biYPelsPerMeter;//垂直分辨率unsigned int biClrUsed;      //位图实际使用的彩表的彩色索引数,为0证明全部使用unsigned int   biClrImportant; //说明对图象显示有重要影响的颜色索引数,如果是0,表示无差别
};//调色板(由颜色索引数决定)-可以省略此信息()
typedef struct _tPixelInfo
{unsigned char      rgbBlue;            //该颜色的蓝色分量(0~255)unsigned char        rgbGreen;           //该颜色的绿色分量(0~255)unsigned char        rgbRed;             //该颜色的红色分量(0~255)unsigned char        rgbReserved;        //保留字
};
//图像像素区数据 2色图像 - 1点1位
//               16色图像- 1点4位(半字节)
//               256色图像-1点8位 (整字节)
//               真彩图像- 1点24位 (3字节)
//在一个字节中,不存在两个像素点的数据补位,一个字节如果在存好一个像素的数据之后有冗余,后补00
//不同显示模式下的输出一幅图像的补位情况不同uint8_t BMP_INFOPRINT(const char* BMP);
uint8_t IMG_GreyChange(const char* ORI_IMG, const char* NEW_IMG);
uint8_t IMG_Whitebalance(const char* ORI_IMG,const char* NEW_IMG);#endif // !_IMG_VISION_H_

调用以上两个文件即可,为了直观体会,这里多加一个写好的输出测试:

#define     _CRT_SECURE_NO_WARNINGS
#include "IMGVision.h"
#include "Windows.h"int main()
{unsigned int mode;char IMG[200] = "L:/ImgFactor/Temp/HelloWorld/HelloWorld/source/IMGSource/IEI.bmp";char NEWIMG[200] = "NEWIEI_G.bmp";char IMG_QYZ[200] = "L:/ImgFactor/Temp/HelloWorld/HelloWorld/source/IMGSource/IMGT.bmp";char NEWIMG_QYZ[30] = "NEWIMGT_G.bmp";printf("使用此程序进行BMP图像处理:输入mode\r\n\t\t1->BMP图片信息提取\r\n\t\t2->BMP灰白处理\r\n\t\t3->BMP图片白平衡处理(请注意,白平衡不适用于极端情况)\r\n输入mode->> ");scanf_s("%d", &mode);getchar();system("cls");if(mode == 1){printf("下方粘贴目标图片地址:\r\n");scanf("%s", IMG);printf("目标图片地址为:%s\r\n点击任意按键继续\r\n\r\n",IMG);getchar();system("cls");BMP_INFOPRINT((const char*)IMG);}else if (mode == 2){printf("下方粘贴目标图片地址:\r\n");scanf("%s", IMG);printf("目标图片地址为:%s\r\n下方输入图片保存地址:(若手动输入则回车继续)\r\n",IMG);scanf("%s", NEWIMG);printf("图片保存地址为:%s\r\n点击任意按键继续\r\n\r\n", NEWIMG);system("cls");IMG_GreyChange((const char*)IMG, (const char*)NEWIMG);}else if (mode == 3){printf("下方粘贴目标图片地址:\r\n");scanf("%s", IMG);printf("目标图片地址为:%s\r\n下方输入图片保存地址:(若手动输入则回车继续)\r\n", IMG);scanf("%s", NEWIMG);printf("图片保存地址为:%s\r\n点击任意按键继续\r\n\r\n", NEWIMG);system("cls");IMG_Whitebalance((const char*)IMG, (const char*)NEWIMG);}else if (mode == 0){system("cls");printf("进行自动处理演示,使用默认图片和默认处理方式\t任意按键继续\r\n");getchar();printf("BMP图片信息提取->>>>>>>>>>>\r\n");BMP_INFOPRINT((const char*)IMG_QYZ);printf("\r\n任意按键继续\r\n"); getchar();printf("BMP图片灰白处理->>>>>>>>>>>\r\n");IMG_GreyChange((const char*)IMG_QYZ, (const char*)NEWIMG_QYZ);printf("\r\n任意按键继续\r\n"); getchar();printf("BMP图片白平衡处理->>>>>>>>>>>\r\n");IMG_Whitebalance((const char*)IMG, (const char*)NEWIMG);printf("\r\n演示结束,前往程序所在路径查看NEWIMG_QYZ.bmp以及NEWIEI_QYZ.bmp; 任意按键结束\r\n"); getchar();}else{printf("方案不存在");system("pause");return -1;}printf("Hello World !");return 0;
}

以上三个文件打包就是一个完整的处理程序
处理效果如下:
原图像
灰白处理后的图像

原图像

白平衡处理后的图像

白平衡不适用于处理极端情况下的图片,所以处理后会出现这种现象。
具体原理可以百度白平衡不适用的情况。

----------------------------END OF ARTICLE-------------------------------------

C语言实现对BMP图像信息的读取、灰白处理和白平衡处理相关推荐

  1. java bmp_JAVA实现对BMP图片的读取

    BMP图片格式,是windows自带的一个图片格式,(*bmp),在windows的系统下都支持这种格式,bmp格式与设备无关的位图(DIB)格式,BMP简称位图,BMP的原始数据是没有经过压缩处理的 ...

  2. java读取bmp图像_JAVA实现对BMP图片的读取

    BMP图片格式,是windows自带的一个图片格式,(*bmp),在windows的系统下都支持这种格式,bmp格式与设备无关的位图(DIB)格式,BMP简称位图,BMP的原始数据是没有经过压缩处理的 ...

  3. c语言bmp图片合并,C语言实现对bmp格式图片打码

    相信大家看到上面的标题一定觉的是上面高大上的技术,其实很简单. 前提准备:一张bmp格式的图片,如果没有的话,可以用Windows的画图软件来才裁剪.设置像素大小为(1024,768): 程序原理:将 ...

  4. VB.net:VB.net编程语言学习之基于VS软件利用VB.net语言实现对SolidWorks进行二次开发的简介、案例应用之详细攻略

    VB.net:VB.net编程语言学习之基于VS软件利用VB.net语言实现对SolidWorks进行二次开发的简介.案例应用之详细攻略 目录 调用SolidWorks功能简介 1.宏录制步骤 (1) ...

  5. 用c语言实现对n个进程采用“短进程优先”算法的进程调度_为什么Linux CFS调度器没有带来惊艳的碾压效果?...

    文章转自公众号"人人都是极客" 但凡懂Linux内核的,都知道Linux内核的CFS进程调度算法,无论是从2.6.23将其初引入时的论文,还是各类源码分析,文章,以及Linux内核 ...

  6. netDxf实现对cad文件的读取与写入

    工程项目中CAD作为常用的设计软件 有大量的设计数据及信息需要在项目中使用,cad文件的解析与读取变的十分重要 对cad的解析,尝试过多种方式,java的读文件流 安装dxf的文件格式进行解析,费时又 ...

  7. 朝花夕拾:Java中实现对EXCEL文件的读取

    在项目中实现读取EXCEL文件中的数据是实现工作项目中数据读取的常用方式.这个对于之前无论写C/C++还是后来写Java来读取txt数据的我来说都是一个新的方式.新的技巧,相信对刚入手的很多小伙伴都是 ...

  8. Codesys用ST语言实现对CSV文件的读写操作的代码案例

    一.开发环境说明 编程软件: Codesys V3.5 SP17 运行设备:PC电脑 编程语言: ST 二.配置操作 1.新建Codesys工程,依次点击[文件]-[新建工程]-[标准工程]- 输入名 ...

  9. 通过TDM C DLL,使用C实现对TDMS文件的读取

    最近项目的第二个要求便是使用C++对实验采集到的TDMS文件进行读取,从而对数据进行分析以及计算.众所周知,TDMS文件是NI公司提倡的一类文件,关于这个格式的详细介绍大家可以百度,比较关键的一点我简 ...

最新文章

  1. RocketMQ集群启动报错:java.lang.RuntimeException: Lock failed,MQ already started
  2. wasm逆向——(极客大挑战2021wasm
  3. boost::type_erasure模块construction相关的测试程序
  4. JAVA循环结构学校上机经常遇到的几题 笔记
  5. Mybatis——返回类型为 集合嵌套集合 应该如何处理
  6. 禁售苹果手机_苹果、华为供应商工厂突发火灾!浓烟冲天
  7. 鸽主姓名查询成绩_鸽主姓名
  8. 创建物化视图commit_oracle慎用基于on commit刷新物化视图的方式(一)
  9. linux安装pip3_Liunx下安装Python3.5.0版本,本地有python2.7.5,python2和3共存
  10. win10台式机前置耳机无声音解决方案
  11. 远程连接virtualBox本地虚拟机并访问虚拟机服务
  12. html文本打印lt;igt;字段,6-HTMLlt; formgt;表单标签和属性
  13. 传说华为面试爱问正则,这不海外留学生校招面试题来了
  14. 耗时10个小时用纯HTML和CSS写成的小兔鲜儿
  15. 启动SparkSql,报javax.jdo.JDOFatalInternalException: Error creating transactional connection factory
  16. 谈谈如何写好一份简历
  17. 解决import lief运行报错问题
  18. stm8下载程序(使用ST-LINK下载器和STVP下载软件)
  19. C语言经典例题及答案3
  20. Python读写文件的推荐写法-try-open

热门文章

  1. 美国国会议员敦促国家经济委员会举办区块链论坛
  2. Oracle期末考试 复习笔记
  3. 电信诈骗为何如此难以根治?
  4. 高中信息技术:信息技术教学论
  5. 我在支付宝花了 1 分钟,查到了对象的开房记录
  6. 使用wrap和unwrap加密解密Oracle的PL/SQL对象(包,存储过程,函数等)代码
  7. java计算机毕业设计学习社区管理系统源码+数据库+系统+lw文档+部署
  8. C++:string模拟实现(下)
  9. 第二章 数据库和表的基本操作
  10. 【大神】陈天奇:机器学习科研的十年