?? hyperspectralimagcode.cpp
字號:
#include "stdafx.h"
#include <math.h>
#include ".\AdvanceJPEG-LS\AdvanceJPEG-LSCode.h"
#include "HyperspectralImagCode.h"
//高光譜圖像編碼器
CHyperspectralImageCode::CHyperspectralImageCode()
{
HyperspectralDataFormat=BFILE;
BandNumber=Height=Width=OnePixelBytes=OnePixelBits=LinesPerCompressBlock=AllowMaxError=0;
lpHead=NULL;
lpImageData=NULL;
HImageWidth=HImageHeight=HImageBand=HBitPerPixel=HDataStartPosition=HImageFormat=OneLineAuxDataWidth=0;
lpIMF=NULL;
lpImageIndex=NULL;
lpCompressUnit=NULL;
lpPredictTable=NULL;
lpCodeStreamBuf=NULL;
}
CHyperspectralImageCode::~CHyperspectralImageCode()
{
EndHyperspectralCode();
}
void CHyperspectralImageCode::EndHyperspectralCode()
{
int i;
if(HMF.IsOpen()==TRUE)HMF.Close();
if(lpImageIndex!=NULL){delete lpImageIndex;lpImageIndex=NULL;}
if(lpIMF!=NULL)
{
for(i=0;i<BandNumber;i++)
{
if(lpIMF[i]->IsOpen()==TRUE)lpIMF[i]->Close();
delete lpIMF[i];
}
delete lpIMF;
lpIMF=NULL;
}
if(lpPredictTable!=NULL)delete lpPredictTable;lpPredictTable=NULL;
if(CMF.IsOpen()==TRUE)
{
CMF.Close();
lpCodeStreamBuf=NULL;
}
else
{
if(lpCodeStreamBuf!=NULL)delete lpCodeStreamBuf;
lpCodeStreamBuf=NULL;
}
if(lpCompressUnit!=NULL)
{
for(i=0;i<BandNumber;i++)
{
lpCompressUnit[i]->EndCode();
delete lpCompressUnit[i];
}
delete lpCompressUnit;
lpCompressUnit=NULL;
}
BandNumber=Height=Width=OnePixelBytes=OnePixelBits=LinesPerCompressBlock=AllowMaxError=0;
}
//OMIS相關圖像格式時
BOOL CHyperspectralImageCode::LoadHyperspectralImageFile(LPCTSTR pHFile,
int OneLineImageAuxDataL/*每掃描行圖像輔助數據數*/)
{
LPBYTE lpHpic;
int i=::GetFileLength(pHFile);//取得完整高光譜數據長度
if(HMF.CreateFileMap(pHFile,//創建文件映射內存
PAGE_READONLY,
i,
NULL,
OPEN_ALWAYS)!=NULL)
{
lpHpic=(LPBYTE)HMF.MapOfFile(0,i);
lpHead=(stAuxMsg *)lpHpic;
if(lpHead->iImageBand<=MAXBANDNUMBER&&lpHead->iBitPerPixel<=MAXBITPERPIXEL)
{
lpImageData=lpHpic+lpHead->iDataStartPosition;//高光譜數據指針
BandNumber=HImageBand=lpHead->iImageBand;//波段數
HImageWidth=lpHead->iImageWidth;//高光譜數據寬度
Height=HImageHeight=lpHead->iImageHeight;//高光譜數據高度
OnePixelBits=HBitPerPixel=lpHead->iBitPerPixel;//每象素比特數
HDataStartPosition=lpHead->iDataStartPosition;//高光譜數據在文件中的實際位置
HyperspectralDataFormat=HImageFormat=lpHead->iImageFormat;//高光譜數據格式
OneLineAuxDataWidth=OneLineImageAuxDataL;
Width=HImageWidth-OneLineImageAuxDataL;//每行圖像的寬度要減出輔助數據項
if(OnePixelBits<=8)OnePixelBytes=1;//由象素比特數產生單象素字節數
else OnePixelBytes=2;
return TRUE;
}
else
{
HMF.Close();
return FALSE;
}
}
return FALSE;
}
//純圖像格式時,任何高光譜數據都可以先轉化為單波段純圖像格式再行壓縮.
BOOL CHyperspectralImageCode::LoadHyperspectralImageFile(LPCTSTR *lpIFileList,
int BandN,
int H,
int W,
int Bytes,
int Bits)
{//這是從單波段純圖像列表中加載高光譜數據
int i,l;
if(BandN<=MAXBANDNUMBER&&Bits<=MAXBITPERPIXEL)
{
HyperspectralDataFormat=BFILE;//數據格式標志
OneLineAuxDataWidth=0;//沒有輔助數據
BandNumber=HImageBand=BandN;//波段數
Height=HImageHeight=H;//圖像高度
Width=HImageWidth=W;//圖像寬度
OnePixelBits=HBitPerPixel=Bits;//單象素比特數
OnePixelBytes=Bytes;//單象素字節數
l=H*W*Bytes;//最小文件長度
for(i=0;i<BandN;i++)
{//檢查每個文件是否有足夠的長度
if((int)::GetFileLength(lpIFileList[i])<l)
{
break;
}
}
if(i<BandN)
{//中間有文件不足最小長度時,加載高光譜數據失敗
return FALSE;
}
lpIMF=new CMapFile *[BandN];//創建映射文件表
for(i=0;i<BandN;i++)
{
lpIMF[i]=new CMapFile;
}
lpImageIndex=new LPBYTE[BandN];//創建各波段數據指針表
for(i=0;i<BandN;i++)
{
if(lpIMF[i]->CreateFileMap(lpIFileList[i],
PAGE_READONLY,
l,
NULL,
OPEN_ALWAYS)!=NULL)
{
lpImageIndex[i]=(LPBYTE)lpIMF[i]->MapOfFile(0,l);//從映射文件中獲得數據指針表
}
else break;
}
if(i<BandN)
{//若其中有文件映射失敗,清理已創建的對象.
for(i=0;i<BandN;i++)
{
delete lpIMF[i];
}
delete lpIMF;lpIMF=NULL;
delete lpImageIndex;lpImageIndex=NULL;
return FALSE;
}
return TRUE;
}
return FALSE;
}
LPBYTE CHyperspectralImageCode::GetOneLineImageData(int Band,int Line)//直接從原始數據中取得指針
{//這種方式支持純圖像格式及BSQ_H、BIL_H格式
if(HyperspectralDataFormat==BFILE)//純圖像格式
{
return lpImageIndex[Band]+Line*Width*OnePixelBytes;
}
else if(HyperspectralDataFormat==BSQ_H)//BSQ_H圖像格式
{
return lpImageData+(Band*HImageWidth*HImageHeight*OnePixelBytes)+(Line*HImageWidth*OnePixelBytes);
}
else if(HyperspectralDataFormat==BSQ_H)//BIL_H圖像格式
{
return lpImageData+(Line*HImageWidth*HImageBand*OnePixelBytes)+(Band*HImageWidth*OnePixelBytes);
}
return NULL;
}
void CHyperspectralImageCode::GetOneLineImageData(LPBYTE lpOneLineBuf,int Band,int Line)//從原始數據中取得數據裝入到指定緩沖
{//這種方式支持所有格式,尤其是BIP_H格式。
LPBYTE lpLineData;
int i,j;
TCHAR Andcod1;
short int Andcod2;
if(HyperspectralDataFormat==BIP_H)//BIP_H圖像格式
{
lpLineData=lpImageData+(Line*HImageWidth*HImageBand*OnePixelBytes);
//須按波段間隔采樣才能得到單一波段連續一行的數據。
if(OnePixelBytes==1)
{
Andcod1=~((-1)<<OnePixelBits);
for(i=0,j=Band;i<Width;i++,j+=HImageBand)
{
lpOneLineBuf[i]=lpLineData[j]&Andcod1;
}
}
else
{
Andcod2=~((-1)<<OnePixelBits);
for(i=0,j=Band;i<Width;i++,j+=HImageBand)
{
*(((short int *)lpOneLineBuf)+i)=(*(((short int *)lpLineData)+j))&Andcod2;
}
}
}
else if(HyperspectralDataFormat==BIL_H||HyperspectralDataFormat==BSQ_H||HyperspectralDataFormat==BFILE)
{
MoveMemory(lpOneLineBuf,GetOneLineImageData(Band,Line),Width*OnePixelBytes);
if(OnePixelBytes==1)
{
Andcod1=~((-1)<<OnePixelBits);
for(i=0;i<Width;i++)
{
lpOneLineBuf[i]&=Andcod1;
}
}
else
{
Andcod2=~((-1)<<OnePixelBits);
for(i=0;i<Width;i++)
{
*(((short int *)lpOneLineBuf)+i)&=Andcod2;
}
}
}
}
//從原始數據中取得每行輔助數據裝入到指定緩沖
int CHyperspectralImageCode::GetOneLineAuxData(LPBYTE lpOneLineBuf,int Band,int Line)
{//這種方式支持BSQ_H、BIL_H格式。
if(HyperspectralDataFormat==BIL_H||HyperspectralDataFormat==BSQ_H)
{
MoveMemory(lpOneLineBuf,
GetOneLineImageData(Band,Line)+Width*OnePixelBytes,
OneLineAuxDataWidth*OnePixelBytes);
return OneLineAuxDataWidth*OnePixelBytes;
}
return 0;
}
//為輸出碼流準備緩沖
void CHyperspectralImageCode::PrepareCodeStreamBuf(int OneBlockLines,LPCTSTR CodeFileName,int AllowError)
{
int i;
CompressFile=CodeFileName;
LinesPerCompressBlock=OneBlockLines;
i=OneBlockLines*Width*BandNumber*OnePixelBits/8;
if(AllowError>=4)i/=2;
if(AllowError>=32)i/=2;
if(AllowError>=80)i/=2;
if(lpCodeStreamBuf!=NULL)
{
if(i!=StreamBufLength)
{
delete lpCodeStreamBuf;
lpCodeStreamBuf=new BYTE[i];
StreamBufLength=i;
}
}
else
{
lpCodeStreamBuf=new BYTE[i];
StreamBufLength=i;
}
ClearCodeStreamBuf();
}
void CHyperspectralImageCode::ClearCodeStreamBuf()
{
ZeroMemory(lpCodeStreamBuf,StreamBufLength);
}
//從輸入的字符串中裝入預測波段的配置
void CHyperspectralImageCode::LoadPredictTable(LPCTSTR lpAsc)
{
TCHAR *lpasc;
int i,j,k,l;
if(lpPredictTable!=NULL)delete lpPredictTable;
lpPredictTable=new short int[BandNumber];
l=strlen(lpAsc)+2;
lpasc=new TCHAR[l];
strcpy(lpasc,lpAsc);
for(i=0,j=0;i<BandNumber&&j<l;i++)
{
for(;lpasc[j]!='-'&&(lpasc[j]>'9'||lpasc[j]<'0')&&j<l;j++);
k=j;
for(;lpasc[j]=='-'||(lpasc[j]<='9'&&lpasc[j]>='0')&&j<l;j++);
lpasc[j]='\0';
lpPredictTable[i]=atoi(lpasc+k);
}
if(i<BandNumber)for(;i<BandNumber;i++)lpPredictTable[i]=-1;
delete lpasc;
}
//一般在調用預測波段配置后才可調用
void CHyperspectralImageCode::CreatCompressObject()//根據波段數創建相應數量的壓縮對象
{
int i;
lpCompressUnit=new CAdvanceJepgLSOneLineCode *[BandNumber];
for(i=0;i<BandNumber;i++)
{
lpCompressUnit[i]=new CAdvanceJepgLSOneLineCode;
if(lpPredictTable[i]>=0)lpCompressUnit[i]->PrepareCode(Width,lpCompressUnit[lpPredictTable[i]]);
else lpCompressUnit[i]->PrepareCode(Width);
}
}
//創建高光譜數據壓縮信息頭,返回頭字節數
int CHyperspectralImageCode::CreatHyperspectralCompressHead(LPBYTE lpBuf,LPBYTE &lpAuxBuf,int &AuxBufL)
{
lpBuf[0]=HyperspectralDataFormat;//高光譜數據格式
*((short int *)(lpBuf+1))=BandNumber;//波段數
*((short int *)(lpBuf+3))=Width;//圖像寬
*((short int *)(lpBuf+5))=Height;//圖像高
if(HyperspectralDataFormat==BFILE)
{//純圖像格式時
*((char *)(lpBuf+7))=(char)OnePixelBits;//單象素比特數
*((char *)(lpBuf+8))=(char)OnePixelBytes;//單象素字節數
MoveMemory(lpBuf+9,lpPredictTable,BandNumber*sizeof(short int));//以雙字節存放預測波段號
lpAuxBuf=NULL;AuxBufL=0;
return 9+BandNumber*sizeof(short int);
}
else
{//高光譜數據格式時
//以雙字節存放預測波段號
MoveMemory(lpBuf+7,lpPredictTable,BandNumber*sizeof(short int));
lpAuxBuf=(LPBYTE)lpHead;
AuxBufL=sizeof(stAuxMsg)+lpHead->stLineAuxDataInfo.ladHeight*lpHead->stLineAuxDataInfo.ladWidth;
//高光譜數據格式頭
// MoveMemory(lpBuf+7+BandNumber*sizeof(short int),lpHead,sizeof(stAuxMsg));
//高光譜數據格式頭中的輔助數據
// MoveMemory(lpBuf+7+BandNumber*sizeof(short int)+sizeof(stAuxMsg),
// lpHead+sizeof(stAuxMsg),
// lpHead->stLineAuxDataInfo.ladHeight*lpHead->stLineAuxDataInfo.ladWidth);
return 7+BandNumber*sizeof(short int)+sizeof(stAuxMsg)+lpHead->stLineAuxDataInfo.ladHeight*lpHead->stLineAuxDataInfo.ladWidth;
}
return 0;
}
//創建高光譜數據塊壓縮信息頭,返回頭字節數
int CHyperspectralImageCode::CreatBlockCompressHead(LPBYTE lpBuf,int Maxerr,int LineBG,int LineN)
{
//前四字節用于保存塊的總字節數
lpBuf[4]=Maxerr;//當前塊誤差界
*((short int *)(lpBuf+5))=LineBG;//當前塊起始行
*((short int *)(lpBuf+7))=LineN;//當前塊所包含的圖像行數
return 9+OneLineAuxDataWidth*OnePixelBytes*BandNumber*LineN;//返回塊信息頭總字節數
}
int CHyperspectralImageCode::LoadBlockCompressHead(LPBYTE lpCodeStream,int &AllowMaxErr,int &LineBG,int &LineN)
{
AllowMaxErr=lpCodeStream[4];
LineBG=*((short int *)(lpCodeStream+5));
LineN=*((short int *)(lpCodeStream+7));
return 9+OneLineAuxDataWidth*OnePixelBytes*BandNumber*LineN;
}
//執行壓縮操作
void CHyperspectralImageCode::DoCompress(int AllowMaxErr,double *lpErrMsePerPixel,double *lpBitPerPixel)
{
/*
a、建立壓縮塊循環。
b、創建壓縮塊信息頭。
c、建立圖像行循環
d、建立波段循環
e、取某行某波段數據
f、用相應的波段編碼器編碼該圖像行數據,碼流匯入總碼流。
g、下一個波段。
h、下一個圖像行
i、導出壓縮塊碼流。
j、下一個壓縮圖像塊
*/
int Line,i,j,LineBG,LineN,AuxData_cp,CodeBit_cp;
LPBYTE lpAuxData=new BYTE[9+OneLineAuxDataWidth*OnePixelBytes*BandNumber*LinesPerCompressBlock];
LPBYTE lpImageData=new BYTE[Width*OnePixelBytes+4];
LPBYTE lpAuxD;
int AuxL;
double ErrMse,BitPerPixel;
AllowMaxError=AllowMaxErr;
//創建并保存高光譜數據壓縮頭信息
i=CreatHyperspectralCompressHead(lpCodeStreamBuf,lpAuxD,AuxL);
WriteDataToFile(lpCodeStreamBuf,i-AuxL);
if(AuxL>0)AppendDataToFile(lpAuxD,AuxL);
//執行壓縮循環
for(Line=0;Line<Height;)
{//這是塊循環層
LineBG=Line;
LineN=((Height-LineBG)>=LinesPerCompressBlock)?LinesPerCompressBlock:(Height-LineBG);
AuxData_cp=9;
CreatBlockCompressHead(lpAuxData,AllowMaxError,LineBG,LineN);
for(i=0;i<BandNumber;i++)
{//各波段編碼器復位
lpCompressUnit[i]->InitialisationsCode(OnePixelBits,AllowMaxError);
}
CodeBit_cp=0;
ErrMse=0;
BitPerPixel=0;
for(j=0;j<LineN;j++)
{
for(i=0;i<BandNumber;i++)
{
//取當前行圖像數據
GetOneLineImageData(lpImageData,i,j+LineBG);
//取當前行輔助數據
AuxData_cp+=GetOneLineAuxData(lpAuxData+AuxData_cp,i,j+LineBG);
//壓縮當前行圖像,碼流以比特為單位存放
CodeBit_cp+=lpCompressUnit[i]->DoEncodeLine(lpImageData,
OnePixelBytes,
lpCodeStreamBuf,
CodeBit_cp,
&ErrMse);
}
}
Line+=LineN;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -