?? 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 + -