文本数据重建为BMP图像的实现过程
一、问题描述
现有从红外成像设备获取的光强电压值,存为了TXT的文本格式,数据格式如下:
-0.010 -0.078 -0.083 -0.078 -0.073 -0.044 -0.044 -0.049 -0.049
-0.044 0.044 0.029 0.034 -0.039 -0.034 -0.034 -0.029 -0.024
-0.024 -0.029 -0.029 -0.020 -0.010 -0.005 -0.010 -0.005 0.000……
要求根据这些数据,还原成256级灰度的BMP数字图像,还原出红外图像的真实效果。
二、问题分析
感光元件根据光的强度,通过转换可以得到相应的电压值。也就是说,这些电压值代表一定的光亮度。要根据这些电压值重建BMP图形,只要把这些电压值映射为图像相应的颜色值,然后根据BMP文件的规格,便可以还原图像。
三、实现思路和求解过程
(1)根据要求,应把图像恢复成256级的灰度图,这种图像的特点是,0代表黑色,255代表白色,0-255之间的整数代表了黑色过渡到白色相应的灰度值。那么我们必须把现有的这些浮点型数据映射到0-255的整数区间。可以通过以下的公式完成转换:
( k = 0,1,2……N ) ………………………… ①
式中,Uk表示数据文本中第k项的电压值;Umin表示所有电压值中的最小值;Umax表示所有电压值中的最大值;Pk表示映射后的整数值,用以表示相应像素的灰度值;N表示所得图像的总像素数,由于我们要恢复的图像都是128*128的分辨率,所以此处像素数N=128*128=16384;符号[*]表示取整,最终得到的Pk是介于0-255的整数值。通过上式,可以把原文本中的16384个电压值转换成对应于图像的16384个灰度值。
经过转换后,由于经过了一个取整的过程,所以精度有所下降。RDT
(2)得到灰度值后,即可构建bmp位图文件。Bmp文件格式如下:
BITMAPFILEHEADER 位图文件头(只用于BMP文件) |
BITMAPINFOHEADER 位图信息头 |
Palette 调色板 |
DIB Pixels 位图数据 |
其中,BITMAPFILEHEADER、BITMAPINFOHEADER是windows定义的struct(结构体),描述了bmp文件的各种属性;Palette为调色板,用于文件的颜色索引;DIB pixels是位图数据,我们在上面求得的16384个图像灰度值可以保存在一个数组里,再存放在这一块中。关于前三项的详细信息可以查阅windows的相关文档,我们将在程序中对他们进行配置。
四、程序流程图
从数据文件读取字符 开始 结束 文件是否结束 是 否 转换成数字并保存到数组 找出最大值和最小值 根据公式①求出各点的量化值 创建BMP文件头 把BMP文件头写入图像文件 把各点的量化灰度值写入图像文件
五、程序实现
#include "stdafx.h"
#include <math.h>
#include <stdlib.h>
#include <afx.h>
#define MAXSIZE 16384 //the number of bits, 128*128
BITMAPFILEHEADER *m_pBitmapFileHeader; //BMP文件头
BITMAPINFOHEADER *m_pBitmapInfoHeader; //BMP位图信息头
DWORD m_FileLength; //文件长度
RGBQUAD *m_pRGBQuad; //调色板数组
PBITMAPINFO m_pBitmapInfo; //指向BITMAPINFO结构的指针
BYTE *pByte = new BYTE[MAXSIZE]; //位图灰度值数组
BYTE *p = new BYTE[1078]; //保存位图信息头的数据
void CreatInfo( );//创建BMP文件头信息
//函数名:Transform
//参数:szInFile:要转换的txt文件路径
// szOutFile:输出的bmp文件路径
//功能:实现txt到bmp的转换
BOOL Transform( const char *szInFile, const char *szOutFile )
{
FILE *fpIn, *fpOut;
char ch[15];
double num;
int i,n;
double bits[MAXSIZE];
double max;
double min;
double range;
fpIn = fopen( szInFile, "rb" );
if ( fpIn == NULL )
return FALSE;
//从文件读取数据
i=0;
n=0;
do{
ch[i] = fgetc( fpIn );
if( ch[i] == 0x09 || ch[i] == EOF || (ch[i]=='/n') )
{
If( i!=0 )
{
ch[i] = NULL;
num = atof( ch );
bits[n++] = num;
i = 0;
}
}
else
{
i++;
}
}while( !feof( fpIn ) );
fclose( fpIn );
//找出最大和最小值
max = bits[0];
min = bits[0];
i = 0;
while( i < MAXSIZE )
{
if( bits[i]>max )
{
max = bits[i];
}
else if( bits[i]<min )
{
min = bits[i];
}
i++;
}
range = max - min;//数据变化范围
//量化
i = 0;
while( i < MAXSIZE )
{
pByte[i] = (BYTE)( ( ( bits[i] - min )/range) * 255 + 0.5 );//量化到0-255,四舍五入
i++;
}
fpOut = fopen( szOutFile, "wb" );//保存bmp的文件
if ( fpOut == NULL )
return FALSE;
CreatInfo();
fwrite( m_pBitmapInfo, 1078, 1, fpOut ); //写入BMP文件头信息
fwrite( pByte, MAXSIZE, 1, fpOut ); //写入灰度数据文件
fclose( fpOut ); //关闭文件,清理内存
return TRUE;
}
//函数名:CreatInfo
//功能:创建256级灰度图所需的位图文件头
void CreatInfo( )
{
m_FileLength = 1078 + MAXSIZE ;
m_pBitmapFileHeader = (BITMAPFILEHEADER*)p;
m_pBitmapInfoHeader = (BITMAPINFOHEADER*)(p+14);
m_pRGBQuad = (RGBQUAD*)(p + 54 );
m_pBitmapFileHeader->bfType = 0x4d42;//BM
m_pBitmapFileHeader->bfOffBits = 1078;
m_pBitmapFileHeader->bfSize = m_pBitmapFileHeader->bfOffBits+m_FileLength;
m_pBitmapFileHeader->bfReserved1 = 0;
m_pBitmapFileHeader->bfReserved2 = 0;
m_pBitmapInfoHeader->biBitCount = 8;
m_pBitmapInfoHeader->biClrImportant = 0;
m_pBitmapInfoHeader->biClrUsed = 0;
m_pBitmapInfoHeader->biCompression = BI_RGB;
m_pBitmapInfoHeader->biHeight = 128;//height
m_pBitmapInfoHeader->biWidth = 128;//width
m_pBitmapInfoHeader->biPlanes = 1;
m_pBitmapInfoHeader->biSize = 40;
m_pBitmapInfoHeader->biSizeImage = MAXSIZE;
m_pBitmapInfo = (BITMAPINFO *) (m_pBitmapFileHeader);
for( int i=0;i<256;i++ )
{
m_pRGBQuad[i].rgbBlue= i;
m_pRGBQuad[i].rgbGreen = i;
m_pRGBQuad[i].rgbRed =i;
m_pRGBQuad[i].rgbReserved = 0;
}
}
int main(int argc, char* argv[])
{
char *szInFileFile = "c://1.txt";
char *szOutFileFile = "c://1.bmp";
Transform( szInFileFile, szOutFileFile );
printf("OK!/n");
delete[] p;
delete[] pByte;
return 0;
}