开门见山,先把这个函数拿出来,看函数实现之前,我想先说一说各参数。
1,szPath是生成的栅格的路径
2,szFile是生成的栅格的文件名
3,rstInfo是RasterInfo结构体变量,是生成栅格的一些参数信息
struct RasterInfo {
IPointPtr ipOrigin; //栅格原点坐标
long lColCount; //栅格列数
long lRowCount; //栅格行数
double dCellSizeX; //栅格X分辨率,X方向每像素大小
double dCellSizeY; //栅格Y分辨率,Y方向每像素大小
long lNumbands; //波段数
ISpatialReferencePtr ipSpaRef; //空间参考
rstPixelType rstTy; //数据类型,具体为:
Constant Value Description
PT_U1 0 Pixel values are 1 bit.
PT_U2 1 Pixel values are 2 bits.
PT_U4 2 Pixel values are 4 bits.
PT_UCHAR 3 Pixel values are unsigned 8 bit integers.
PT_CHAR 4 Pixel values are 8 bit integers.
PT_USHORT 5 Pixel values are unsigned 16 bit integers.
PT_SHORT 6 Pixel values are 16 bit integers.
PT_ULONG 7 Pixel values are unsigned 32 bit integers.
PT_LONG 8 Pixel values are 32 bit integers.
PT_FLOAT 9 Pixel values are single precision floating point.
PT_DOUBLE 10 Pixel values are double precision floating point.
PT_COMPLEX 11 Pixel values are complex.
PT_DCOMPLEX 12 Pixel values are double precision complex.
//为了方便赋值,做了结构体的构造函数
RasterFormat(IPointPtr ipOrg, long lColC, long lRowC, double dCSX, double dCSY, long lNumBDS, rstPixelType ty, ISpatialReferencePtr ipSF)
{
ipOrigin = ipOrg;
lColCount = lColC;
lRowCount = lRowC;
dCellSizeX = dCSX;
dCellSizeY = dCSY;
lNumbands = lNumBDS;
rstTy = ty;
ipSpaRef = ipSF;
};
//为了能从栅格属性接口中得到栅格信息赋值,做了下面这个函数,目的还是方便给结构体赋值。
FromRasProps(IRasterPropsPtr ipRasProps, double dCSX, double dCSY, long lNumBDS,rstPixelType ty= PT_UCHAR, ISpatialReferencePtr ipSF = NULL){
IEnvelopePtr ipEnv;
ipRasProps->get_Extent(&ipEnv);
double x, y;
ipEnv->get_XMin(&x);
ipEnv->get_YMin(&y);
IPointPtr ipPt(CLSID_Point);
ipPt->PutCoords(x,y);
ipOrigin = ipPt;
ipRasProps->get_Width(&lColCount);
ipRasProps->get_Height(&lRowCount);
dCellSizeX = dCSX;
dCellSizeY = dCSY;
lNumbands = lNumBDS;
rstTy = ty;
ipSpaRef = ipSF;
};
};
4,pData是一个BYTE**(LPBYTE)类型的数组,
5,szRasFormat是栅格类型枚举,其定义为
enum RasterFormat
{
IMAGINE_Image,
TIFF,
GRID
};
6,bNoDataValue是透明灰度值,不过现在我还没有研究明白,实现不了效果,哪们朋友研究清楚了,可以指点一下。
//下面才是真正的函数开始了。
//生成ArcGIS支持的栅格数据
void CWzjAoRasterOp::WriteRaster(CString szPath, CString szFile, RasterInfo rstInfo, LPBYTE pData, CString szRasFormat /*= "IMAGINE Image"*/, BYTE bNoDataValue /*= 256*/)
{
IWorkspacePtr ipWS;
IWorkspaceFactoryPtr ipWSF(CLSID_RasterWorkspaceFactory);
//If Not pWSF.IsWorkspace(sPath) Then Exit Sub
ipWSF->OpenFromFile(CComBSTR(szPath), 0, &ipWS);
IRasterWorkspace2Ptr ipRWS(ipWS);
IRasterDatasetPtr ipRasterDS;//szRasFormat),
ipRWS->CreateRasterDataset(CComBSTR(szFile), CComBSTR(szRasFormat), rstInfo.ipOrigin, rstInfo.lColCount,
rstInfo.lRowCount, rstInfo.dCellSizeX, rstInfo.dCellSizeY, rstInfo.lNumbands, rstInfo.rstTy, rstInfo.ipSpaRef, TRUE, &ipRasterDS);
IRasterPtr ipRaster;
ipRasterDS->CreateDefaultRaster(&ipRaster);
IRasterPropsPtr ipRasProps = ipRaster;
// Get RasterBand from the raster
IRasterBandPtr ipBand;
IRasterBandCollectionPtr ipBandCol(ipRaster);
ipBandCol->Item(0, &ipBand);
//目前这个设置透明色值不管用,不知道正确的方法是怎么样
/*if (bNoDataValue > 0 || bNoDataValue < 256) {
VARIANT vVal;
vVal.vt = VT_UI1;
vVal.cVal = bNoDataValue;
// ipRasProps->put_NoDataValue(vVal);
ipRasProps->put_NoDataValue(CComVariant(bNoDataValue));
}
*/// QI RawPixel interface
IRawPixelsPtr ipRawPixel(ipBand);
ipRasProps = ipRaster;
// Create a DblPnt to hold the PixelBlock size
IPntPtr ipSize(CLSID_DblPnt);
long lWidth, lHeight;
ipRasProps->get_Width(&lWidth);
ipRasProps->get_Height(&lHeight);
ipSize->SetCoords(lWidth, lHeight);
// Create PixelBlock with defined size
IPntPtr ipPnt(CLSID_DblPnt);
ipPnt->SetCoords(0,0);
IPixelBlockPtr ipBlock;
ipRawPixel->CreatePixelBlock(ipSize, &ipBlock);
VARIANT varChunk;
SAFEARRAY *psa;
SAFEARRAYBOUND rgsabound[2];
rgsabound[0].cElements = lWidth;
rgsabound[0].lLbound = 0;
rgsabound[1].cElements = lHeight;
rgsabound[1].lLbound = 0;
psa = SafeArrayCreate(VT_UI1,2,rgsabound);
LPBYTE pD;
SafeArrayAccessData(psa, (void**)&pD);
// pD = pData; 事实证明,直接这样不行,必须要经过下面赋值过程
long index;
CProDlg* pProDlg = new CProDlg();
pProDlg->Create(IDD_DLG_PRO);
pProDlg->SetWindowText("正在生成图像文件");
pProDlg->ShowWindow(SW_SHOW);
pProDlg->m_pro.SetRange(0, lWidth * lHeight-1);
for(long i=0;i
for (long j = 0; j < lHeight; j++)
{
index = i*lHeight + j;
pD[index] =pData[index];//i+j;
}
pProDlg->m_pro.SetPos(i*lHeight+j);
}
delete pProDlg;
pProDlg = NULL;
varChunk.vt = VT_ARRAY|VT_UI1;
varChunk.parray = psa;
SafeArrayUnaccessData(psa);
ipBlock->put_SafeArray(0, varChunk);
ipPnt->SetCoords(0,0);
// Write the PixelBlock to raster band
ipRawPixel->Write(ipPnt, ipBlock);
}
小结一下,实现的过程中难点在于SAFEARRAY类型数据的使用,如果在VB或C#中不存在这个难点问题,很简单了,如果有什么问题的话,大家可以查一查SAFEARRAY它的用法或跟wzj23020723联系。