📄 hyperspectralimagcode.cpp
字号:
//累计总的码流比特数
BitPerPixel+=CodeBit_cp;
//计算当前压缩块总字节数
*((int *)lpAuxData)=AuxData_cp+(CodeBit_cp>>3)+((CodeBit_cp&7)?1:0);
//保存当前压缩块信息头
AppendDataToFile(lpAuxData,AuxData_cp);
//保存当前压缩块码流
AppendDataToFile(lpCodeStreamBuf,(CodeBit_cp>>3)+((CodeBit_cp&7)?1:0));
ClearCodeStreamBuf();
}
//计算压缩误差的均方值
ErrMse/=(Height*Width*BandNumber);
//计算单象素比特值
BitPerPixel/=(Height*Width*BandNumber);
delete lpImageData;
delete lpAuxData;
if(lpErrMsePerPixel!=NULL)*lpErrMsePerPixel=ErrMse;
if(lpBitPerPixel!=NULL)*lpBitPerPixel=BitPerPixel;
}
void CHyperspectralImageCode::WriteDataToFile(void *lpBuf,int Bytes)
{
CFile f;
if(f.Open((LPCTSTR)CompressFile,CFile::modeCreate|CFile::modeWrite|CFile::typeBinary)==TRUE)
{
f.Write(lpBuf,Bytes);
f.Close();
}
}
void CHyperspectralImageCode::AppendDataToFile(void *lpBuf,int Bytes)
{
CFile f;
if(f.Open((LPCTSTR)CompressFile,CFile::modeReadWrite|CFile::typeBinary)==TRUE)
{
f.SeekToEnd();
f.Write(lpBuf,Bytes);
f.Close();
}
}
//加载压缩码流
BOOL CHyperspectralImageCode::LoadCompressBitStream(LPCTSTR CompressFile)
{//将压缩文件映射到内存、获取存放于压缩头的控制数据,获取第一个压缩块的指针。
LPBYTE lpCS;
int i=::GetFileLength(CompressFile);//取得完整高光谱压缩数据长度
if(CMF.CreateFileMap(CompressFile,//创建文件映射内存
PAGE_READONLY,
i,
NULL,
OPEN_ALWAYS)!=NULL)
{
lpCS=(LPBYTE)CMF.MapOfFile(0,i);//获取映射文件内存指针
HyperspectralDataFormat=lpCS[0];//格式字节
BandNumber=*((short int *)(lpCS+1));//波段数
if((lpCS[0]==BSQ_H||lpCS[0]==BIP_H||lpCS[0]==BIL_H||lpCS[0]==BFILE)&&(BandNumber>0&&BandNumber<=MAXBANDNUMBER))
{//如果是指定的四种格式
Width=*((short int *)(lpCS+3));//图像宽度
Height=*((short int *)(lpCS+5));//图像高度
if(HyperspectralDataFormat==BFILE)
{//纯图像格式时
OnePixelBits=*((char *)(lpCS+7));//单象素字节数
OnePixelBytes=*((char *)(lpCS+8));//单象素数比特数
if(lpPredictTable!=NULL)delete lpPredictTable;
lpPredictTable=new short int[BandNumber];
MoveMemory(lpPredictTable,lpCS+9,BandNumber*sizeof(short int));//以短整数形式存放的预测波段配置表
lpBlockHead=lpCS+9+BandNumber*sizeof(short int);//压缩数据块头
OneLineAuxDataWidth=0;//每行图像的辅助数据
}
else
{//OMIS高光谱图像数据存放格式
if(lpPredictTable!=NULL)delete lpPredictTable;
lpPredictTable=new short int[BandNumber];
MoveMemory(lpPredictTable,lpCS+7,BandNumber*sizeof(short int));//以短整数形式存放的预测波段配置表
lpHead=(stAuxMsg *)(lpCS+7+BandNumber*sizeof(short int));//高光谱数据的格式头
//压缩块数据头的起始位置
lpBlockHead=lpCS+7+BandNumber*sizeof(short int)+sizeof(stAuxMsg)+lpHead->stLineAuxDataInfo.ladHeight*lpHead->stLineAuxDataInfo.ladWidth;
//由高光谱数据头设置部分与压缩有关的变量
HImageBand=lpHead->iImageBand;//波段数
HImageWidth=lpHead->iImageWidth;//高光谱数据宽度
Height=HImageHeight=lpHead->iImageHeight;//高光谱数据高度
OnePixelBits=HBitPerPixel=lpHead->iBitPerPixel;//每象素比特数
HDataStartPosition=lpHead->iDataStartPosition;//高光谱数据在文件中的实际位置
OneLineAuxDataWidth=HImageWidth-Width;
if(OnePixelBits<=8)OnePixelBytes=1;//由象素比特数产生单象素字节数
else OnePixelBytes=2;
}
return TRUE;
}
else
{
CMF.Close();
return FALSE;
}
}
return FALSE;
}
//准备压缩图像缓冲
BOOL CHyperspectralImageCode::PrepareConstructionImageBuf(LPCTSTR lpHyperspectralImageFile)
{//为高光谱重建图像准备缓冲
LPBYTE lpHpic;
int i;
DeleteFile(lpHyperspectralImageFile);
i=sizeof(stAuxMsg)+lpHead->stLineAuxDataInfo.ladHeight*lpHead->stLineAuxDataInfo.ladWidth+
HImageWidth*HImageHeight*HImageBand*OnePixelBytes;//缓冲区总长度
if(HMF.CreateFileMap(lpHyperspectralImageFile,//创建文件映射内存
PAGE_READWRITE,
i,
NULL,
OPEN_ALWAYS)!=NULL)
{
lpHpic=(LPBYTE)HMF.MapOfFile(0,i);
//高光谱数据格式头
MoveMemory(lpHpic,lpHead,sizeof(stAuxMsg)+lpHead->stLineAuxDataInfo.ladHeight*lpHead->stLineAuxDataInfo.ladWidth);
//高光谱数据指针
lpImageData=lpHpic+sizeof(stAuxMsg)+lpHead->stLineAuxDataInfo.ladHeight*lpHead->stLineAuxDataInfo.ladWidth;
return TRUE;
}
return FALSE;
}
BOOL CHyperspectralImageCode::PrepareConstructionImageBuf(LPCTSTR *lpBandImageFile)
{//为单波段纯图像方式保存高光谱重建成图像准备缓冲
int i,l;
lpIMF=new CMapFile *[BandNumber];//创建映射文件表
for(i=0;i<BandNumber;i++)
{
lpIMF[i]=new CMapFile;
}
lpImageIndex=new LPBYTE[BandNumber];//创建各波段数据指针表
l=Width*Height*OnePixelBytes;
for(i=0;i<BandNumber;i++)
{
DeleteFile(lpBandImageFile[i]);
if(lpIMF[i]->CreateFileMap(lpBandImageFile[i],
PAGE_READWRITE,
l,
NULL,
OPEN_ALWAYS)!=NULL)
{
lpImageIndex[i]=(LPBYTE)lpIMF[i]->MapOfFile(0,l);//从映射文件中获得数据指针表
}
else break;
}
if(i<BandNumber)
{//若其中有文件映射失败,清理已创建的对象.
for(i=0;i<BandNumber;i++)
{
delete lpIMF[i];
}
delete lpIMF;lpIMF=NULL;
delete lpImageIndex;lpImageIndex=NULL;
return FALSE;
}
return TRUE;
}
//设置一行重建图像数据
void CHyperspectralImageCode::SetOneLineImageData(LPBYTE lpOneLineBuf,int Band,int Line)
{
LPBYTE lpLineData;
int i,j;
if(HyperspectralDataFormat==BFILE)//纯图像格式
{
MoveMemory(lpImageIndex[Band]+Line*Width*OnePixelBytes,lpOneLineBuf,Width*OnePixelBytes);
}
else if(HyperspectralDataFormat==BSQ_H)//BSQ_H图像格式
{
MoveMemory(lpImageData+(Band*HImageWidth*HImageHeight*OnePixelBytes)+(Line*HImageWidth*OnePixelBytes),
lpOneLineBuf,
Width*OnePixelBytes);
}
else if(HyperspectralDataFormat==BSQ_H)//BIL_H图像格式
{
MoveMemory(lpImageData+(Line*HImageWidth*HImageBand*OnePixelBytes)+(Band*HImageWidth*OnePixelBytes),
lpOneLineBuf,
Width*OnePixelBytes);
}
else if(HyperspectralDataFormat==BIP_H)//BIP_H图像格式
{
lpLineData=lpImageData+(Line*HImageWidth*HImageBand*OnePixelBytes);
//须按波段间隔采样才能得到单一波段连续一行的数据。
if(OnePixelBytes==1)
{
for(i=0,j=Band;i<Width;i++,j+=HImageBand)
{
lpLineData[j]=lpOneLineBuf[i];
}
}
else
{
for(i=0,j=Band;i<Width;i++,j+=HImageBand)
{
*(((short int *)lpLineData)+j)=*(((short int *)lpOneLineBuf)+i);
}
}
}
}
//设置一行辅助数据
int CHyperspectralImageCode::SetOneLineAuxData(LPBYTE lpOneLineBuf,int Band,int Line)
{
if(HyperspectralDataFormat==BSQ_H)//BSQ_H图像格式
{
MoveMemory(lpImageData+(Band*HImageWidth*HImageHeight*OnePixelBytes)+(Line*HImageWidth*OnePixelBytes)+Width*OnePixelBytes,
lpOneLineBuf,
OneLineAuxDataWidth*OnePixelBytes);
return OneLineAuxDataWidth*OnePixelBytes;
}
else if(HyperspectralDataFormat==BSQ_H)//BIL_H图像格式
{
MoveMemory(lpImageData+(Line*HImageWidth*HImageBand*OnePixelBytes)+(Band*HImageWidth*OnePixelBytes)+Width*OnePixelBytes,
lpOneLineBuf,
OneLineAuxDataWidth*OnePixelBytes);
return OneLineAuxDataWidth*OnePixelBytes;
}
return 0;
}
//完成解压缩全过程
void CHyperspectralImageCode::DoUnCompress()
{
/*
a、建立解压缩块循环。
b、取得压缩块信息头。
c、建立图像行循环
d、建立波段循环
e、解压缩取某行某波段数据
f、保存该行该波段数据。
g、下一个波段。
h、下一个图像行
j、下一个压缩图像块
*/
int Line,i,j,LineBG,LineN,AuxData_L,AuxData_cp,CodeBit_cp,Block_L,AllowMaxErr;
LPBYTE lpImageData=new BYTE[Width*OnePixelBytes+4];
//执行压缩循环
for(Line=0;Line<Height;)
{//这是块循环层
Block_L=*((int *)lpBlockHead);
AuxData_L=LoadBlockCompressHead(lpBlockHead,AllowMaxErr,LineBG,LineN);
AuxData_cp=9;
AllowMaxError=AllowMaxErr;
lpCodeStreamBuf=lpBlockHead+AuxData_L;
for(i=0;i<BandNumber;i++)
{//各波段编码器复位
lpCompressUnit[i]->InitialisationsCode(OnePixelBits,AllowMaxError);
}
CodeBit_cp=0;
for(j=0;j<LineN;j++)
{
for(i=0;i<BandNumber;i++)
{
//解压缩当前行图像,码流指针以比特为单位
CodeBit_cp+=lpCompressUnit[i]->DoDecodeLine(lpImageData,
OnePixelBytes,
lpCodeStreamBuf,
CodeBit_cp);
//保存当前行图像数据
SetOneLineImageData(lpImageData,i,j+LineBG);
//保当前行辅助数据
AuxData_cp+=SetOneLineAuxData(lpBlockHead+AuxData_cp,i,j+LineBG);
}
}
Line+=LineN;
//块指针指向下一块
lpBlockHead+=Block_L;
}
delete lpImageData;
}
//含预测的多波段图像压缩实例
BOOL HyperspectralImageCompress(LPCTSTR lpHyperspectralImageFile,
LPCTSTR lpPredictBandConfig,
LPCTSTR CompressFile,
int AllowMaxError,
int LinesPerBlock,
int OneLineImageAuxDataL,
double *lpErrMsePerPixel,
double *lpBitPerPixel)
{//针对具有高光谱数据格式信息的单一高光谱数据文件
CHyperspectralImageCode HEncode;
// 1、加载高光谱数据。
// a、支持三种形式的高光谱数据文件格式(BSQ_H、BIP_H、BIL_H)及各波段独立文件格式。
// b、从格式文件的头部获取数据各类参数,独立文件形式必须输入压缩所需格式信息。
// c、配置预测波段。(配置信息来自预先的设定)
if(HEncode.LoadHyperspectralImageFile(lpHyperspectralImageFile,OneLineImageAuxDataL)==FALSE)
return FALSE;
HEncode.LoadPredictTable(lpPredictBandConfig);
// 2、为各波段创建编码器。
// a、编码器实际上是用来独立保存各波段编码的上下文信息(包括波段预测所需上下文)。
// b、创建的同时要根据单波段相关参数及预测配置初始化编码器。
HEncode.CreatCompressObject();
// 3、为压缩码流准备缓冲区及存放文件。(缓冲区大小取决于压缩图像块的大小)
HEncode.PrepareCodeStreamBuf(LinesPerBlock,CompressFile);
// 4、执行压缩循环
HEncode.DoCompress(AllowMaxError,lpErrMsePerPixel,lpBitPerPixel);
// 5、释放码流及各波段编码器缓冲区。
HEncode.EndHyperspectralCode();
return TRUE;
}
BOOL HyperspectralImageCompress(LPCTSTR *lpHyperspectralImageFile,
LPCTSTR lpPredictBandConfig,
LPCTSTR CompressFile,
int BandNumber,
int Height,
int Width,
int BitsPerPixel,
int BytesPerPixel,
int AllowMaxError,
int LinesPerBlock,
double *lpErrMsePerPixel,
double *lpBitPerPixel)
{//针对以单波段纯图像文件存放的高谱数据
CHyperspectralImageCode HEncode;
// 1、加载高光谱数据。
// a、支持三种形式的高光谱数据文件格式(BSQ_H、BIP_H、BIL_H)及各波段独立文件格式。
// b、从格式文件的头部获取数据各类参数,独立文件形式必须输入压缩所需格式信息。
// c、配置预测波段。(配置信息来自预先的设定)
if(HEncode.LoadHyperspectralImageFile(lpHyperspectralImageFile,
BandNumber,
Height,
Width,
BytesPerPixel,
BitsPerPixel)==FALSE)
return FALSE;
HEncode.LoadPredictTable(lpPredictBandConfig);
// 2、为各波段创建编码器。
// a、编码器实际上是用来独立保存各波段编码的上下文信息(包括波段预测所需上下文)。
// b、创建的同时要根据单波段相关参数及预测配置初始化编码器。
HEncode.CreatCompressObject();
// 3、为压缩码流准备缓冲区及存放文件。(缓冲区大小取决于压缩图像块的大小)
HEncode.PrepareCodeStreamBuf(LinesPerBlock,CompressFile);
// 4、执行压缩循环
HEncode.DoCompress(AllowMaxError,lpErrMsePerPixel,lpBitPerPixel);
// 5、释放码流及各波段编码器缓冲区。
HEncode.EndHyperspectralCode();
return TRUE;
}
//含预测的多波段图像解压缩实例
BOOL HyperspectralImageUnCompress(LPCTSTR lpHyperspectralImageFile,
LPCTSTR CompressFile)
{//重建单一高谱数据文件,如果压缩时是单波段纯图像,重建时用BSQ_H格式
CHyperspectralImageCode HDecode;
// 1、加载高光谱压缩码流。
if(HDecode.LoadCompressBitStream(CompressFile)==FALSE)
return FALSE;
if(HDecode.HyperspectralDataFormat==BFILE)return FALSE;
//为重建图像准备缓冲
if(HDecode.PrepareConstructionImageBuf(lpHyperspectralImageFile)==FALSE)return FALSE;
// 2、为各波段创建解码器。
HDecode.CreatCompressObject();
// 4、执行解压缩循环
HDecode.DoUnCompress();
// 5、释放码流及各波段编码器缓冲区。
HDecode.EndHyperspectralCode();
return TRUE;
}
BOOL HyperspectralImageUnCompress(LPCTSTR *lpHyperspectralImageFile,
LPCTSTR CompressFile)
{//重建单波段纯图像数据
CHyperspectralImageCode HDecode;
// 1、加载高光谱压缩码流。
if(HDecode.LoadCompressBitStream(CompressFile)==FALSE)
return FALSE;
//为重建图像准备缓冲
if(HDecode.PrepareConstructionImageBuf(lpHyperspectralImageFile)==FALSE)return FALSE;
// 2、为各波段创建解码器。
HDecode.CreatCompressObject();
// 4、执行解压缩循环
HDecode.DoUnCompress();
// 5、释放码流及各波段编码器缓冲区。
HDecode.EndHyperspectralCode();
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -