探测地球云层分布的CloudSat和CALIPSO卫星
http://www.nasa.gov/mission_pages/calipso/main/index.html
http://www.nasa.gov/topics/earth/features/calipso-1billion.html
Cloud-Aerosol Lidar and Infrared Pathfinder Satellite Observation (CALIPSO)
The occasion was on CALIPSO's 9,491st orbit of Earth. Since its launch, on April 23, 2006, the satellite has traveled 260,198,685.3 miles. It has generated data that would fill almost 3,500 DVDs or more than 24,000 CDs, delighting scientists and researchers from 35 countries who are using the information to prove any number of theories about the atmosphere, about weather, about the past and how it will relate to the future.
数据格式
读取代码:
double lonFrom = ;
double latFrom = ;
double lonTo = ;
double latTo = ;
OSGeo.GDAL.Gdal.AllRegister();
Gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "Yes");
string path = string.Format(@"C:\Users\Desktop\lidar_track_image\CAL_LID_L1-ValStage1-V3-02.2013-01-01T18-30-59ZN_Subset.hdf", WorldSettings.StartupDirectory);
//path = string.Format(@"{0}\data\CAL_LID_L1-ValStage1-V3-02.2013-01-01T18-30-59ZN_Subset.hdf", WorldSettings.StartupDirectory);
byte[] pathUtf16 = Encoding.Unicode.GetBytes(path); byte[] byteUtf8 = Encoding.Convert(Encoding.Unicode, Encoding.UTF8, pathUtf16); string pathUtf8 = Encoding.UTF8.GetString(byteUtf8); Encoding encoud = Encoding.GetEncoding();
byte[] byteGb2312 = Encoding.Convert(Encoding.Unicode, encoud, pathUtf16);
string pathGb2312 = encoud.GetString(byteGb2312); if (!File.Exists(path))
{
MessageBox.Show("Calpso数据不存在", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
//读取文件,获取子数据集信息
Dataset ds = Gdal.Open(path, Access.GA_ReadOnly);
string[] stMetadata = ds.GetMetadata("");
string[] strMetadata = ds.GetMetadata("SUBDATASETS");
string info = string.Empty;
for (int i = ; i < strMetadata.Length; i++)
{
info += strMetadata[i] + "\n";
}
info += "读取波段数据:----------------\n";
//纬度数据
string tmpstr = strMetadata[];
tmpstr = tmpstr.Substring(tmpstr.IndexOf("=") + );
Dataset dsLat = Gdal.Open(tmpstr, Access.GA_ReadOnly);
string strMetadata2 = dsLat.GetDescription(); info += string.Format("像素数目:{0} X {1}", dsLat.RasterXSize, dsLat.RasterYSize);
int count = dsLat.RasterCount;
Band bandLat = dsLat.GetRasterBand();
int Cols = dsLat.RasterXSize;
int Rows = dsLat.RasterYSize;
int width = dsLat.RasterXSize;
int height = dsLat.RasterYSize;
double min, max, no;
int hasvalue;
info += string.Format("类型Lat:{0}\n", bandLat.DataType);
if (bandLat.DataType == DataType.GDT_Float32)
{
bandLat.GetMaximum(out max, out hasvalue);
bandLat.GetMinimum(out min, out hasvalue);
bandLat.GetNoDataValue(out no, out hasvalue);
float[] data = new float[Cols * Rows];
bandLat.ReadRaster(, , width, height, data, Cols, Rows, , ); string ddd = string.Empty;
double min1, max1, mean, hasvalue1;
OSGeo.GDAL.Gdal.GDALProgressFuncDelegate dele = new Gdal.GDALProgressFuncDelegate(GDALProgressFunc);
bandLat.ComputeStatistics(false, out min1, out max1, out hasvalue1, out mean, dele, ddd);
lonFrom = data[];
lonTo = data[data.Length - ];
}
//经度数据
string tmpstrLon = strMetadata[];
tmpstrLon = tmpstrLon.Substring(tmpstrLon.IndexOf("=") + );
Dataset dsLon = Gdal.Open(tmpstrLon, Access.GA_ReadOnly);
info += string.Format("像素数目:{0} X {1}", dsLon.RasterXSize, dsLon.RasterYSize);
Band bandLon = dsLon.GetRasterBand();
int Cols2 = dsLon.RasterXSize;
int Rows2 = dsLon.RasterYSize;
int width2 = dsLon.RasterXSize;
int height2 = dsLon.RasterYSize;
double min2, max2, no2;
int hasvalue2;
info += string.Format("类型Lon:{0}\n", bandLon.DataType);
if (bandLon.DataType == DataType.GDT_Float32)
{
bandLon.GetMaximum(out max2, out hasvalue2);
bandLon.GetMinimum(out min2, out hasvalue2);
bandLon.GetNoDataValue(out no2, out hasvalue2);
float[] data2 = new float[Cols2 * Rows2];
bandLon.ReadRaster(, , width2, height2, data2, Cols2, Rows2, , ); string ddd = string.Empty;
double min1, max1, mean, hasvalue1;
OSGeo.GDAL.Gdal.GDALProgressFuncDelegate dele = new Gdal.GDALProgressFuncDelegate(GDALProgressFunc);
bandLon.ComputeStatistics(false, out min1, out max1, out hasvalue1, out mean, dele, ddd);
latFrom = data2[];
latTo = data2[data2.Length - ];
}
//读取雷达衰减系数
string tmpStrBackScatter = strMetadata[];
tmpStrBackScatter = tmpStrBackScatter.Substring(tmpStrBackScatter.IndexOf("=") + );
Dataset dsBackScatter = Gdal.Open(tmpStrBackScatter, Access.GA_ReadOnly);
info += string.Format("像素数目:{0} X {1}", dsBackScatter.RasterXSize, dsBackScatter.RasterYSize);
Band bandBackScatter = dsBackScatter.GetRasterBand();
int ColsBackScatter = dsBackScatter.RasterXSize;
int RowsBackScatter = ;// ds270.RasterYSize;读取3000个像素
int widthBackScatter = dsBackScatter.RasterXSize;
int heightBackScatter = ;// ds270.RasterYSize;
double min270, max270, no270;
int hasvalue270;
info += string.Format("类型衰减系数:{0}\n", bandBackScatter.DataType);
if (bandBackScatter.DataType == DataType.GDT_Float32)
{
bandBackScatter.GetMaximum(out max270, out hasvalue270);
bandBackScatter.GetMinimum(out min270, out hasvalue270);
bandBackScatter.GetNoDataValue(out no270, out hasvalue270);
string ddd = string.Empty;
double mean, has; OSGeo.GDAL.Gdal.GDALProgressFuncDelegate dele = new Gdal.GDALProgressFuncDelegate(GDALProgressFunc);
bandBackScatter.ComputeStatistics(false, out min270, out max270, out has, out mean, dele, ddd);
float[] data270 = new float[ColsBackScatter * RowsBackScatter];
bandBackScatter.ReadRaster(, , widthBackScatter, heightBackScatter, data270, ColsBackScatter, RowsBackScatter, , ); int x1width = heightBackScatter;
int y1height = widthBackScatter;//
Bitmap bitmap = new Bitmap(x1width, y1height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
int iPixelSize = ; CreateColorRamp createColorRamp = CreateColorRamps();
BitmapData bitmapdata = bitmap.LockBits(new Rectangle(, , x1width, y1height), ImageLockMode.ReadWrite, bitmap.PixelFormat);
try
{
unsafe
{
for (int y = ; y < y1height; y++)
{
byte* row = (byte*)bitmapdata.Scan0 + (y * bitmapdata.Stride); for (int x = ; x < x1width; x++)
{
//int posSrc = x + y * x1width;
int posSrc = y + x * y1height;//图像顺时针旋转90度
double item = data270[posSrc];
if (item == no270)
{
Color? getColor = getColor = createColorRamp.GetColor(); ;
row[x * iPixelSize] = (byte)getColor.Value.B;
row[x * iPixelSize + ] = (byte)getColor.Value.G;
row[x * iPixelSize + ] = (byte)getColor.Value.R;
row[x * iPixelSize + ] = getColor.Value.A;
}
else
{
Color? getColor = null;
if (item < 0.0001 || item > 0.1)
{
getColor = createColorRamp.GetColor();
}
else
{
getColor = createColorRamp.GetColor(item);
}
if (getColor != null)
{
row[x * iPixelSize] = getColor.Value.B;
row[x * iPixelSize + ] = getColor.Value.G;
row[x * iPixelSize + ] = getColor.Value.R;
row[x * iPixelSize + ] = getColor.Value.A;
}
}
}
}
}
}
catch
{
}
finally
{
bitmap.UnlockBits(bitmapdata);
}
bitmap.Save("D:\\b.png");
Vector3d v1 = new Vector3d(lonFrom, latFrom, );
Vector3d v2 = new Vector3d(lonTo, latTo, );
Vector3d dir = v2 - v1; Vector3d v3 = v1 + (double)heightBackScatter / dsBackScatter.RasterYSize * dir.Normalize();
CalpsoRenderObject obj = new CalpsoRenderObject("", v1, v3);
}
public CreateColorRamp CreateColorRamps()
{
CreateColorRamp createColorRamp = new CreateColorRamp();
List<ColorRamp> mColorRamp = new List<ColorRamp>();
double[] valueGray = new double[] {0.0, 0.0001,0.0002,0.0003,0.0004,0.0005,
0.0006,0.0007,0.0008,0.0009,0.001,
0.0015,0.002, 0.0025,0.003, 0.0035,
0.004, 0.0045,0.005, 0.0055, 0.006,
0.0065,0.007, 0.0075,0.008, 0.01,
0.02, 0.03, 0.04, 0.05, 0.06,
0.07, 0.08, 0.09, 0.1};
int[] Rv = new int[] {, , , , , , , , , , ,
,,,,,,,,,,
,,,,,,,,,,
,,,};
int[] Gv = new int[] {,,,,,,,,,,
,,,,,,,,,,,
,,,,,,,,,,
,,,};
int[] Bv = new int[] {,,,,,,,,,,
,,,,,,,,,,,
,,,,, ,,,,,
,,,}; for (int i = ; i < ; i++)
{
ColorRamp clr = new ColorRamp();
clr.start = valueGray[i];
if (i < )
{
clr.end = valueGray[i + ];
}
clr.ColorS = Color.FromArgb(, Rv[i], Gv[i], Bv[i]);
mColorRamp.Add(clr);
}
mColorRamp[mColorRamp.Count - ].end = ;
createColorRamp.ColorRampCollection = mColorRamp;
return createColorRamp;
}
int GDALProgressFunc(double Complete, IntPtr Message, IntPtr Data)
{
return ;
}
CreateColorRamp
public class ColorRamp
{
public double start;
public double Interval;
public double end; public Color ColorS;
}
public class CreateColorRamp
{
public List<ColorRamp> ColorRampCollection { get; set; }
public Color? GetColor(double val)
{
if (ColorRampCollection == null)
{
throw new ArgumentNullException("颜色分级设置为空");
}
for (int i = ; i < ColorRampCollection.Count; i++)
{
ColorRamp colorRam = ColorRampCollection[i];
if (val >= colorRam.start && val < colorRam.end)
{
return colorRam.ColorS;
}
}
return null; }
}
}
GDAL C#封装还是没有解决中文字符的问题。C# 采用Unicode,GDAL的Dll采用多字节字符。所以只能在C++的代码中做些工作,将Unicode转换为多字节字符或者是Utf8。准备测试一下。
NASA上的图片: