环境:VS2010,C#,GDAL1.7

读取影像:

 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing.Imaging;
using OSGeo.GDAL;
using AppScene; namespace GdalReader
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string __ImagePath = string.Empty;
private OSGeo.GDAL.Dataset __Geodataset;
private int[] __DisplayBands;
private Rectangle __DrawRect;
private Bitmap __BitMap;
private void btnBrower_Click(object sender, EventArgs e)
{
OpenFileDialog dlg = new OpenFileDialog();
dlg.Title = "";
dlg.Filter = "Img(*.img)|*.img";
if (dlg.ShowDialog() == DialogResult.OK)
{
OSGeo.GDAL.Gdal.AllRegister();
__ImagePath = dlg.FileName;
txtPath.Text = __ImagePath;
OSGeo.GDAL.Dataset dataset = OSGeo.GDAL.Gdal.Open(__ImagePath, OSGeo.GDAL.Access.GA_ReadOnly);
__Geodataset = dataset;
if (__Geodataset != null)
{
if (__Geodataset.RasterCount >= )
__DisplayBands = new int[] { , , };
else
__DisplayBands = new int[] { , , };
}
double[] dd = new double[];
dataset.GetGeoTransform(dd);
string prj = dataset.GetProjection(); string str = string.Format("波段数目:{0}\n行数:{1};列数:{2}\n坐标参考:{3},{4},{5},{6}\n", __Geodataset.RasterCount, __Geodataset.RasterXSize, __Geodataset.RasterYSize, dd[], dd[], dd[], dd[]);
str += prj + "\n";
for (int i = ; i <= __Geodataset.RasterCount; ++i)
{
OSGeo.GDAL.Band band = dataset.GetRasterBand(i);
str += "波段" + i + ":" + band.DataType.ToString(); }
richTextBox1.Text = str;
InitialIMG();
SimpleRasterShow simRaster = new SimpleRasterShow("");
simRaster.IsOn = true;
simRaster.bitmap = __BitMap;
sceneControl1.CurrentWorld.RenderableObjects.ChildObjects.Add(simRaster);
}
} public void InitialIMG()
{
if (__Geodataset != null)
{
Rectangle rect = new Rectangle(, , __Geodataset.RasterXSize, __Geodataset.RasterYSize);
float width = (float)this.Width;
float height = (float)this.Height;
RectangleF Extent = ExtRect(rect, width, height);
double scale = Extent.Width / this.Width;
//double scaley = Extent.Height / this.Height;
double bufWidth = __Geodataset.RasterXSize / scale;
double bufHeight = __Geodataset.RasterYSize / scale;
Debug.WriteLine("Buffered width is:" + bufWidth);
Debug.WriteLine("Buffered height is:" + bufHeight);
double bufX = (this.Width - bufWidth) / 2.0;
double bufY = (this.Height - bufHeight) / 2.0;
__DrawRect = new Rectangle((int)bufX, (int)bufY, (int)bufWidth, (int)bufHeight);
Rectangle ExtentRect = new Rectangle(, , (int)bufWidth, (int)bufHeight);
//__DispRectCenter = new PointF((float)(bufX + bufWidth / 2.0), (float)(bufY + bufHeight / 2.0));
// __Zoom = (float)scale;
//__Zoom=(float)(scalex>scaley?scalex:scaley);
__BitMap = RSImg2BitMap(__Geodataset, ExtentRect, __DisplayBands);
// Invalidate();
}
}
public RectangleF ExtRect(Rectangle rect, float width, float height)
{
double midX = rect.X + rect.Width / 2.0;
double midY = rect.Y + rect.Height / 2.0;
double newh = 0.0;
double neww = 0.0;
//Adjust according to width, if
if (rect.Width * 1.0 / rect.Height > width / height)
{
newh = (height * 1.0 / width) * rect.Width;
neww = rect.Width;
//newh = (rect.Height*1.0 / rect.Width) * height;
//neww = width;
}
else
{
//neww = (rect.Width*1.0 / rect.Height) * width;
//newh = height;
neww = (width * 1.0 / height) * rect.Width;
newh = rect.Height;
}
RectangleF newRect = new RectangleF((float)(midX - neww / 2.0), (float)(midY - newh / 2.0), (float)neww, (float)newh);
return newRect;
}
public Bitmap RSImg2BitMap(OSGeo.GDAL.Dataset dataset,
Rectangle ExtentRect, int[] displayBands)
{
int x1width = ExtentRect.Width;
int y1height = ExtentRect.Height; Bitmap image = new Bitmap(x1width, y1height,
System.Drawing.Imaging.PixelFormat.Format24bppRgb);
int iPixelSize = ; if (dataset != null)
{
BitmapData bitmapdata = image.LockBits(new
Rectangle(, , x1width, y1height),
ImageLockMode.ReadWrite, image.PixelFormat);
int ch = ; try
{
unsafe
{
for (int i = ; i <= displayBands.Length; ++i)
{
OSGeo.GDAL.Band band = dataset.GetRasterBand(displayBands[i - ]);
int[] buffer = new int[x1width * y1height];
band.ReadRaster(, , __Geodataset.RasterXSize,
__Geodataset.RasterYSize, buffer, x1width, y1height, , );
int p_indx = ; if ((int)band.GetRasterColorInterpretation() == )
ch = ;
if ((int)band.GetRasterColorInterpretation() == )
ch = ;
if ((int)band.GetRasterColorInterpretation() == )
ch = ;
if ((int)band.GetRasterColorInterpretation() != )
{
double maxVal = 0.0;
double minVal = 0.0;
maxVal = GetMaxWithoutNoData(dataset,
displayBands[i - ], -9999.0);
minVal = GetMinWithoutNoData(dataset,
displayBands[i - ], -9999.0);
for (int y = ; y < y1height; y++)
{
byte* row = (byte*)bitmapdata.Scan0 +
(y * bitmapdata.Stride);
for (int x = ; x < x1width; x++, p_indx++)
{
byte tempVal = shift2Byte(buffer[p_indx], maxVal, minVal, -9999.0);
row[x * iPixelSize + ch] = tempVal;
}
}
}
else
{
double maxVal = 0.0;
double minVal = 0.0;
maxVal = GetMaxWithoutNoData(dataset,
displayBands[i - ], -9999.0);
minVal = GetMinWithoutNoData(dataset,
displayBands[i - ], -9999.0);
for (int y = ; y < y1height; y++)
{
byte* row = (byte*)bitmapdata.Scan0 +
(y * bitmapdata.Stride);
for (int x = ; x < x1width; x++, p_indx++)
{
byte tempVal = shift2Byte<int>
(buffer[p_indx], maxVal, minVal, -9999.0);
row[x * iPixelSize] = tempVal;
row[x * iPixelSize + ] = tempVal;
row[x * iPixelSize + ] = tempVal;
}
}
}
ch++;
}
}
}
finally
{
image.UnlockBits(bitmapdata);
}
}
return image;
}
#region RASTERoperations
/// <summary>
/// Function of shift2Byte
/// </summary>
/// <remarks>this function will shift a value into a range of byte: 0~255 to be displayed in the graphics.</remarks>
/// <typeparam name="T">the type of the value</typeparam>
/// <param name="val">the value that will be converted to byte</param>
/// <param name="Maximum">the maximum value range</param>
/// <param name="Minimum">the minimum value range</param>
/// <returns>a value within the byte range</returns>
public byte shift2Byte<T>(T val, double Maximum, double Minimum)
{
double a = / (Maximum - Minimum);
double b = - ( / (Maximum - Minimum)) * Maximum;
double tempVal = Convert.ToDouble(val);
byte value = Convert.ToByte(a * tempVal + b);
return value;
}
/// <summary>
/// Function of shift2Byte
/// </summary>
/// <remarks>this function will shift a value into a range of byte: 0~255 to be displayed in the graphics.</remarks>
/// <typeparam name="T">the type of the value</typeparam>
/// <param name="val">the value that will be converted to byte</param>
/// <param name="Maximum">the maximum value range</param>
/// <param name="Minimum">the minimum value range</param>
/// <param name="noData">the value for the non-sens pixel</param>
/// <returns>a value within the byte range</returns>
public byte shift2Byte<T>(T val, double Maximum, double Minimum, double noData)
{
double a = 0.0;
double b = 0.0;
double tempVal = Convert.ToDouble(val);
a = / (Maximum - Minimum);
b = - ( / (Maximum - Minimum)) * Maximum;
if (Math.Abs(tempVal) > Math.Abs(noData))
return ;
try
{
return Convert.ToByte(a * tempVal + b);
}
catch
{
return ;
}
}
/// <summary>
/// Function of GetMaxWithoutNoData
/// </summary>
/// <remarks>Get the maximum data of certain band without the nodata values.</remarks>
/// <param name="band">the band that will be statistically checked.</param>
/// <returns>the maximum values.</returns>
public double GetMaxWithoutNoData(OSGeo.GDAL.Dataset ds, int bandNumb, double __NoData)
{
double max = 0.0;
double tempMax = 0.0;
int index = ;
Band tempBand = ds.GetRasterBand(bandNumb);
tempBand.GetMaximum(out tempMax, out index);
if (Math.Abs(tempMax) < Math.Abs(__NoData))
max = tempMax;
else
{
OSGeo.GDAL.Band band;
band = ds.GetRasterBand(bandNumb);
//the number of columns
int xSize = ds.RasterXSize;
//the number of rows
int ySize = ds.RasterYSize;
double[] bandData = new double[xSize * ySize];
//Read the data into the bandData matrix.
OSGeo.GDAL.CPLErr err = band.ReadRaster(, , xSize, ySize, bandData, xSize, ySize, , );
for (long i = ; i < xSize * ySize; i++)
{
if (bandData[i] > max & (Math.Abs(bandData[i]) < Math.Abs(__NoData)))
max = bandData[i];
}
}
return max;
}
/// <summary>
/// Function of GetMinWithoutNoData
/// </summary>
/// <remarks>Get the maximum data of certain band without the nodata values.</remarks>
/// <param name="band">the band that will be statistically checked</param>
/// <returns>the maximum values.</returns>
public double GetMinWithoutNoData(OSGeo.GDAL.Dataset ds, int bandNumb, double __NoData)
{
double min = Math.Abs(__NoData);
double tempMin = 0.0;
int index = ;
Band tempBand = ds.GetRasterBand(bandNumb);
tempBand.GetMinimum(out tempMin, out index);
if (Math.Abs(tempMin) < Math.Abs(__NoData))
min = tempMin;
else
{
OSGeo.GDAL.Band band;
band = ds.GetRasterBand(bandNumb);
//the number of columns
int xSize = ds.RasterXSize;
//the number of rows
int ySize = ds.RasterYSize;
double[] bandData = new double[xSize * ySize];
//Read the data into the bandData matrix.
OSGeo.GDAL.CPLErr err = band.ReadRaster(, , xSize, ySize, bandData, xSize, ySize, , );
for (long i = ; i < xSize * ySize; i++)
{
if (bandData[i] < min & (Math.Abs(bandData[i]) < Math.Abs(__NoData)))
min = bandData[i];
}
}
return min;
}
/// <summary>
/// Funcion of GetDatasetType
/// </summary>
/// <param name="band">the band where the data type will be defined.</param>
/// <returns>0 is the byte, 1 is int, 2 is double, and 3 is unknown.</returns>
public byte GetDatasetType(OSGeo.GDAL.Band band)
{
switch (band.DataType)
{
case OSGeo.GDAL.DataType.GDT_Byte:
return ;
case OSGeo.GDAL.DataType.GDT_CFloat32:
case OSGeo.GDAL.DataType.GDT_CFloat64:
case OSGeo.GDAL.DataType.GDT_Float32:
case OSGeo.GDAL.DataType.GDT_Float64:
return ;
case OSGeo.GDAL.DataType.GDT_TypeCount:
case OSGeo.GDAL.DataType.GDT_Unknown:
return ;
default:
return ;
}
}
#endregion
private SceneControl sceneControl1;
private void Form1_Load(object sender, EventArgs e)
{
this.sceneControl1 = new AppScene.SceneControl();
//
// sceneControl1
//
this.SuspendLayout();
this.sceneControl1.Dock = System.Windows.Forms.DockStyle.Fill;
this.sceneControl1.Location = new System.Drawing.Point(, );
this.sceneControl1.Name = "sceneControl1";
this.sceneControl1.Size = new System.Drawing.Size(, );
this.sceneControl1.TabIndex = ;
this.panel1.Controls.Add(this.sceneControl1);
sceneControl1.Focus();
Application.Idle += new EventHandler(sceneControl1.OnApplicationIdle);
this.ResumeLayout(false);
}
}
}

在AppScene中渲染对象:

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AppScene;
using Microsoft.DirectX.Direct3D;
using Microsoft.DirectX;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Utility; namespace GdalReader
{
class SimpleRasterShow : WorldWind.Renderable.RenderableObject
{
private CustomVertex.PositionTextured[] vertices;// 定义顶点变量
private Texture texture;//定义贴图变量
private Material material;//定义材质变量
public Bitmap bitmap = null;
public SimpleRasterShow(string name)
: base(name)
{ }
public override void Initialize(DrawArgs drawArgs)
{
this.isInitialized = true;
LoadTexturesAndMaterials(drawArgs);
VertexDeclaration();
} public override void Update(DrawArgs drawArgs)
{
if (!isInitialized && isOn)
{
Initialize(drawArgs);
}
} public override void Render(DrawArgs drawArgs)
{
if (!isInitialized || !isOn)
return; VertexFormats format = drawArgs.Device.VertexFormat;
FillMode currentCull = drawArgs.Device.RenderState.FillMode;
int currentColorOp = drawArgs.Device.GetTextureStageStateInt32(, TextureStageStates.ColorOperation);
int zBuffer = drawArgs.Device.GetRenderStateInt32(RenderStates.ZEnable);
try
{
drawArgs.Device.RenderState.FillMode = FillMode.Solid;
drawArgs.Device.RenderState.Lighting = false; drawArgs.Device.RenderState.DiffuseMaterialSource = ColorSource.Color1;
drawArgs.Device.RenderState.AlphaBlendEnable = true;
drawArgs.Device.RenderState.AlphaTestEnable = true; drawArgs.Device.RenderState.ReferenceAlpha = ;
drawArgs.Device.RenderState.AlphaFunction = Compare.Greater; drawArgs.Device.RenderState.SourceBlend = Blend.SourceAlpha;
drawArgs.Device.RenderState.DestinationBlend = Blend.BothInvSourceAlpha;
drawArgs.Device.RenderState.BlendOperation = BlendOperation.Add; drawArgs.Device.SetTexture(, texture);//设置贴图
drawArgs.Device.TextureState[].ColorOperation = TextureOperation.Modulate;
drawArgs.Device.TextureState[].ColorArgument1 = TextureArgument.TextureColor;
drawArgs.Device.TextureState[].ColorArgument2 = TextureArgument.Current;
drawArgs.Device.TextureState[].AlphaOperation = TextureOperation.SelectArg2;
drawArgs.Device.TextureState[].AlphaArgument1 = TextureArgument.TextureColor;
//device.TextureState[0].AlphaArgument2 = TextureArgument.Diffuse; drawArgs.Device.VertexFormat = CustomVertex.PositionTextured.Format;
drawArgs.Device.DrawUserPrimitives(PrimitiveType.TriangleList, , vertices);
}
catch (Exception ex)
{
Log.Write(ex);
}
finally
{
drawArgs.Device.VertexFormat = format;
drawArgs.Device.RenderState.FillMode = currentCull;
drawArgs.Device.SetTextureStageState(, TextureStageStates.ColorOperation, currentColorOp);
drawArgs.Device.SetRenderState(RenderStates.ZEnable, zBuffer);
drawArgs.Device.Indices = null;
}
} private void VertexDeclaration1()//定义顶点1
{
vertices = new CustomVertex.PositionTextured[];
vertices[].Position = new Vector3(10f, 10f, 0f);
vertices[].Tu = ;
vertices[].Tv = ;
vertices[].Position = new Vector3(-10f, -10f, 0f);
vertices[].Tu = ;
vertices[].Tv = ;
vertices[].Position = new Vector3(10f, -10f, 0f);
vertices[].Tu = ;
vertices[].Tv = ;
}
private void VertexDeclaration()//定义顶点
{
vertices = new CustomVertex.PositionTextured[];
vertices[].Position = new Vector3(10f, 10f, 0f);
vertices[].Tu = ;
vertices[].Tv = ;
vertices[].Position = new Vector3(-10f, -10f, 0f);
vertices[].Tu = ;
vertices[].Tv = ;
vertices[].Position = new Vector3(10f, -10f, 0f);
vertices[].Tu = ;
vertices[].Tv = ;
vertices[].Position = new Vector3(-10f, -10f, 0f);
vertices[].Tu = ;
vertices[].Tv = ;
vertices[].Position = new Vector3(10f, 10f, 0f);
vertices[].Tu = ;
vertices[].Tv = ;
vertices[].Position = new Vector3(-10f, 10f, 0f);
vertices[].Tu = ;
vertices[].Tv = ; } private void LoadTexturesAndMaterials(DrawArgs args)//导入贴图和材质
{
material = new Material();
material.Diffuse = Color.White;
material.Specular = Color.LightGray;
material.SpecularSharpness = 15.0F;
args.Device.Material = material;
//MemoryStream memory = new MemoryStream();
//BinaryFormatter formatter = new BinaryFormatter();
//formatter.Serialize(memory, bitmap);
int bufferSize = bitmap.Height * bitmap.Width * ; System.IO.MemoryStream memory = new System.IO.MemoryStream(); bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp);
memory.Seek(, SeekOrigin.Begin);
texture = TextureLoader.FromStream(args.Device, memory);
//if (File.Exists(@"d:\temp.jpg"))
//{
// File.Delete(@"d:\temp.jpg");
//}
//bitmap.Save(@"d:\temp.jpg");
//texture = TextureLoader.FromFile(args.Device, @"d:\temp.jpg");
} public override void Dispose()
{
} public override bool PerformSelectionAction(DrawArgs drawArgs)
{
return true;
// throw new NotImplementedException();
}
}
}

结果:

C#+GDAL读取影像(1)-LMLPHP

存在的问题:

其实就是读取影像的时候构建了一个BitMap,没有和金字塔结合,没有实现在放大缩小的时候动态加载金字塔数据。对于特别大的影像加载会失败!

其实初始加载的时候应该根据画布的大小,加载一个缩略的全局影像,放大过程中动态加载不同级别的金字塔影像!

05-11 22:34