C#+GDAL读取影像(1)
环境:VS2010,C#,GDAL1.7
读取影像:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Diagnostics; 10 using System.Drawing.Imaging; 11 using OSGeo.GDAL; 12 using AppScene; 13 14 namespace GdalReader 15 { 16 public partial class Form1 : Form 17 { 18 public Form1() 19 { 20 InitializeComponent(); 21 } 22 string __ImagePath = string.Empty; 23 private OSGeo.GDAL.Dataset __Geodataset; 24 private int[] __DisplayBands; 25 private Rectangle __DrawRect; 26 private Bitmap __BitMap; 27 private void btnBrower_Click(object sender, EventArgs e) 28 { 29 OpenFileDialog dlg = new OpenFileDialog(); 30 dlg.Title = ""; 31 dlg.Filter = "Img(*.img)|*.img"; 32 if (dlg.ShowDialog() == DialogResult.OK) 33 { 34 OSGeo.GDAL.Gdal.AllRegister(); 35 __ImagePath = dlg.FileName; 36 txtPath.Text = __ImagePath; 37 OSGeo.GDAL.Dataset dataset = OSGeo.GDAL.Gdal.Open(__ImagePath, OSGeo.GDAL.Access.GA_ReadOnly); 38 __Geodataset = dataset; 39 if (__Geodataset != null) 40 { 41 if (__Geodataset.RasterCount >= 3) 42 __DisplayBands = new int[3] { 1, 2, 3 }; 43 else 44 __DisplayBands = new int[3] { 1, 1, 1 }; 45 } 46 double[] dd = new double[4]; 47 dataset.GetGeoTransform(dd); 48 string prj = dataset.GetProjection(); 49 50 string str = string.Format("波段数目:{0}\n行数:{1};列数:{2}\n坐标参考:{3},{4},{5},{6}\n", __Geodataset.RasterCount, __Geodataset.RasterXSize, __Geodataset.RasterYSize, dd[0], dd[1], dd[2], dd[3]); 51 str += prj + "\n"; 52 for (int i = 1; i <= __Geodataset.RasterCount; ++i) 53 { 54 OSGeo.GDAL.Band band = dataset.GetRasterBand(i); 55 str += "波段" + i + ":" + band.DataType.ToString(); 56 57 } 58 richTextBox1.Text = str; 59 InitialIMG(); 60 SimpleRasterShow simRaster = new SimpleRasterShow(""); 61 simRaster.IsOn = true; 62 simRaster.bitmap = __BitMap; 63 sceneControl1.CurrentWorld.RenderableObjects.ChildObjects.Add(simRaster); 64 } 65 } 66 67 public void InitialIMG() 68 { 69 if (__Geodataset != null) 70 { 71 Rectangle rect = new Rectangle(0, 0, __Geodataset.RasterXSize, __Geodataset.RasterYSize); 72 float width = (float)this.Width; 73 float height = (float)this.Height; 74 RectangleF Extent = ExtRect(rect, width, height); 75 double scale = Extent.Width / this.Width; 76 //double scaley = Extent.Height / this.Height; 77 double bufWidth = __Geodataset.RasterXSize / scale; 78 double bufHeight = __Geodataset.RasterYSize / scale; 79 Debug.WriteLine("Buffered width is:" + bufWidth); 80 Debug.WriteLine("Buffered height is:" + bufHeight); 81 double bufX = (this.Width - bufWidth) / 2.0; 82 double bufY = (this.Height - bufHeight) / 2.0; 83 __DrawRect = new Rectangle((int)bufX, (int)bufY, (int)bufWidth, (int)bufHeight); 84 Rectangle ExtentRect = new Rectangle(0, 0, (int)bufWidth, (int)bufHeight); 85 //__DispRectCenter = new PointF((float)(bufX + bufWidth / 2.0), (float)(bufY + bufHeight / 2.0)); 86 // __Zoom = (float)scale; 87 //__Zoom=(float)(scalex>scaley?scalex:scaley); 88 __BitMap = RSImg2BitMap(__Geodataset, ExtentRect, __DisplayBands); 89 // Invalidate(); 90 } 91 } 92 public RectangleF ExtRect(Rectangle rect, float width, float height) 93 { 94 double midX = rect.X + rect.Width / 2.0; 95 double midY = rect.Y + rect.Height / 2.0; 96 double newh = 0.0; 97 double neww = 0.0; 98 //Adjust according to width, if 99 if (rect.Width * 1.0 / rect.Height > width / height) 100 { 101 newh = (height * 1.0 / width) * rect.Width; 102 neww = rect.Width; 103 //newh = (rect.Height*1.0 / rect.Width) * height; 104 //neww = width; 105 } 106 else 107 { 108 //neww = (rect.Width*1.0 / rect.Height) * width; 109 //newh = height; 110 neww = (width * 1.0 / height) * rect.Width; 111 newh = rect.Height; 112 } 113 RectangleF newRect = new RectangleF((float)(midX - neww / 2.0), (float)(midY - newh / 2.0), (float)neww, (float)newh); 114 return newRect; 115 } 116 public Bitmap RSImg2BitMap(OSGeo.GDAL.Dataset dataset, 117 Rectangle ExtentRect, int[] displayBands) 118 { 119 int x1width = ExtentRect.Width; 120 int y1height = ExtentRect.Height; 121 122 Bitmap image = new Bitmap(x1width, y1height, 123 System.Drawing.Imaging.PixelFormat.Format24bppRgb); 124 int iPixelSize = 3; 125 126 if (dataset != null) 127 { 128 BitmapData bitmapdata = image.LockBits(new 129 Rectangle(0, 0, x1width, y1height), 130 ImageLockMode.ReadWrite, image.PixelFormat); 131 int ch = 0; 132 133 try 134 { 135 unsafe 136 { 137 for (int i = 1; i <= displayBands.Length; ++i) 138 { 139 OSGeo.GDAL.Band band = dataset.GetRasterBand(displayBands[i - 1]); 140 int[] buffer = new int[x1width * y1height]; 141 band.ReadRaster(0, 0, __Geodataset.RasterXSize, 142 __Geodataset.RasterYSize, buffer, x1width, y1height, 0, 0); 143 int p_indx = 0; 144 145 if ((int)band.GetRasterColorInterpretation() == 5) 146 ch = 0; 147 if ((int)band.GetRasterColorInterpretation() == 4) 148 ch = 1; 149 if ((int)band.GetRasterColorInterpretation() == 3) 150 ch = 2; 151 if ((int)band.GetRasterColorInterpretation() != 2) 152 { 153 double maxVal = 0.0; 154 double minVal = 0.0; 155 maxVal = GetMaxWithoutNoData(dataset, 156 displayBands[i - 1], -9999.0); 157 minVal = GetMinWithoutNoData(dataset, 158 displayBands[i - 1], -9999.0); 159 for (int y = 0; y < y1height; y++) 160 { 161 byte* row = (byte*)bitmapdata.Scan0 + 162 (y * bitmapdata.Stride); 163 for (int x = 0; x < x1width; x++, p_indx++) 164 { 165 byte tempVal = shift2Byte(buffer[p_indx], maxVal, minVal, -9999.0); 166 row[x * iPixelSize + ch] = tempVal; 167 } 168 } 169 } 170 else 171 { 172 double maxVal = 0.0; 173 double minVal = 0.0; 174 maxVal = GetMaxWithoutNoData(dataset, 175 displayBands[i - 1], -9999.0); 176 minVal = GetMinWithoutNoData(dataset, 177 displayBands[i - 1], -9999.0); 178 for (int y = 0; y < y1height; y++) 179 { 180 byte* row = (byte*)bitmapdata.Scan0 + 181 (y * bitmapdata.Stride); 182 for (int x = 0; x < x1width; x++, p_indx++) 183 { 184 byte tempVal = shift2Byte<int> 185 (buffer[p_indx], maxVal, minVal, -9999.0); 186 row[x * iPixelSize] = tempVal; 187 row[x * iPixelSize + 1] = tempVal; 188 row[x * iPixelSize + 2] = tempVal; 189 } 190 } 191 } 192 ch++; 193 } 194 } 195 } 196 finally 197 { 198 image.UnlockBits(bitmapdata); 199 } 200 } 201 return image; 202 } 203 #region RASTERoperations 204 /// <summary> 205 /// Function of shift2Byte 206 /// </summary> 207 /// <remarks>this function will shift a value into a range of byte: 0~255 to be displayed in the graphics.</remarks> 208 /// <typeparam name="T">the type of the value</typeparam> 209 /// <param name="val">the value that will be converted to byte</param> 210 /// <param name="Maximum">the maximum value range</param> 211 /// <param name="Minimum">the minimum value range</param> 212 /// <returns>a value within the byte range</returns> 213 public byte shift2Byte<T>(T val, double Maximum, double Minimum) 214 { 215 double a = 255 / (Maximum - Minimum); 216 double b = 255 - (255 / (Maximum - Minimum)) * Maximum; 217 double tempVal = Convert.ToDouble(val); 218 byte value = Convert.ToByte(a * tempVal + b); 219 return value; 220 } 221 /// <summary> 222 /// Function of shift2Byte 223 /// </summary> 224 /// <remarks>this function will shift a value into a range of byte: 0~255 to be displayed in the graphics.</remarks> 225 /// <typeparam name="T">the type of the value</typeparam> 226 /// <param name="val">the value that will be converted to byte</param> 227 /// <param name="Maximum">the maximum value range</param> 228 /// <param name="Minimum">the minimum value range</param> 229 /// <param name="noData">the value for the non-sens pixel</param> 230 /// <returns>a value within the byte range</returns> 231 public byte shift2Byte<T>(T val, double Maximum, double Minimum, double noData) 232 { 233 double a = 0.0; 234 double b = 0.0; 235 double tempVal = Convert.ToDouble(val); 236 a = 254 / (Maximum - Minimum); 237 b = 255 - (254 / (Maximum - Minimum)) * Maximum; 238 if (Math.Abs(tempVal) > Math.Abs(noData)) 239 return 0; 240 try 241 { 242 return Convert.ToByte(a * tempVal + b); 243 } 244 catch 245 { 246 return 0; 247 } 248 } 249 /// <summary> 250 /// Function of GetMaxWithoutNoData 251 /// </summary> 252 /// <remarks>Get the maximum data of certain band without the nodata values.</remarks> 253 /// <param name="band">the band that will be statistically checked.</param> 254 /// <returns>the maximum values.</returns> 255 public double GetMaxWithoutNoData(OSGeo.GDAL.Dataset ds, int bandNumb, double __NoData) 256 { 257 double max = 0.0; 258 double tempMax = 0.0; 259 int index = 0; 260 Band tempBand = ds.GetRasterBand(bandNumb); 261 tempBand.GetMaximum(out tempMax, out index); 262 if (Math.Abs(tempMax) < Math.Abs(__NoData)) 263 max = tempMax; 264 else 265 { 266 OSGeo.GDAL.Band band; 267 band = ds.GetRasterBand(bandNumb); 268 //the number of columns 269 int xSize = ds.RasterXSize; 270 //the number of rows 271 int ySize = ds.RasterYSize; 272 double[] bandData = new double[xSize * ySize]; 273 //Read the data into the bandData matrix. 274 OSGeo.GDAL.CPLErr err = band.ReadRaster(0, 0, xSize, ySize, bandData, xSize, ySize, 0, 0); 275 for (long i = 0; i < xSize * ySize; i++) 276 { 277 if (bandData[i] > max & (Math.Abs(bandData[i]) < Math.Abs(__NoData))) 278 max = bandData[i]; 279 } 280 } 281 return max; 282 } 283 /// <summary> 284 /// Function of GetMinWithoutNoData 285 /// </summary> 286 /// <remarks>Get the maximum data of certain band without the nodata values.</remarks> 287 /// <param name="band">the band that will be statistically checked</param> 288 /// <returns>the maximum values.</returns> 289 public double GetMinWithoutNoData(OSGeo.GDAL.Dataset ds, int bandNumb, double __NoData) 290 { 291 double min = Math.Abs(__NoData); 292 double tempMin = 0.0; 293 int index = 0; 294 Band tempBand = ds.GetRasterBand(bandNumb); 295 tempBand.GetMinimum(out tempMin, out index); 296 if (Math.Abs(tempMin) < Math.Abs(__NoData)) 297 min = tempMin; 298 else 299 { 300 OSGeo.GDAL.Band band; 301 band = ds.GetRasterBand(bandNumb); 302 //the number of columns 303 int xSize = ds.RasterXSize; 304 //the number of rows 305 int ySize = ds.RasterYSize; 306 double[] bandData = new double[xSize * ySize]; 307 //Read the data into the bandData matrix. 308 OSGeo.GDAL.CPLErr err = band.ReadRaster(0, 0, xSize, ySize, bandData, xSize, ySize, 0, 0); 309 for (long i = 0; i < xSize * ySize; i++) 310 { 311 if (bandData[i] < min & (Math.Abs(bandData[i]) < Math.Abs(__NoData))) 312 min = bandData[i]; 313 } 314 } 315 return min; 316 } 317 /// <summary> 318 /// Funcion of GetDatasetType 319 /// </summary> 320 /// <param name="band">the band where the data type will be defined.</param> 321 /// <returns>0 is the byte, 1 is int, 2 is double, and 3 is unknown.</returns> 322 public byte GetDatasetType(OSGeo.GDAL.Band band) 323 { 324 switch (band.DataType) 325 { 326 case OSGeo.GDAL.DataType.GDT_Byte: 327 return 0; 328 case OSGeo.GDAL.DataType.GDT_CFloat32: 329 case OSGeo.GDAL.DataType.GDT_CFloat64: 330 case OSGeo.GDAL.DataType.GDT_Float32: 331 case OSGeo.GDAL.DataType.GDT_Float64: 332 return 2; 333 case OSGeo.GDAL.DataType.GDT_TypeCount: 334 case OSGeo.GDAL.DataType.GDT_Unknown: 335 return 3; 336 default: 337 return 1; 338 } 339 } 340 #endregion 341 private SceneControl sceneControl1; 342 private void Form1_Load(object sender, EventArgs e) 343 { 344 this.sceneControl1 = new AppScene.SceneControl(); 345 // 346 // sceneControl1 347 // 348 this.SuspendLayout(); 349 this.sceneControl1.Dock = System.Windows.Forms.DockStyle.Fill; 350 this.sceneControl1.Location = new System.Drawing.Point(0, 0); 351 this.sceneControl1.Name = "sceneControl1"; 352 this.sceneControl1.Size = new System.Drawing.Size(669, 457); 353 this.sceneControl1.TabIndex = 0; 354 this.panel1.Controls.Add(this.sceneControl1); 355 sceneControl1.Focus(); 356 Application.Idle += new EventHandler(sceneControl1.OnApplicationIdle); 357 this.ResumeLayout(false); 358 } 359 } 360 }
在AppScene中渲染对象:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using AppScene; 6 using Microsoft.DirectX.Direct3D; 7 using Microsoft.DirectX; 8 using System.Drawing; 9 using System.IO; 10 using System.Runtime.Serialization.Formatters.Binary; 11 using Utility; 12 13 namespace GdalReader 14 { 15 class SimpleRasterShow : WorldWind.Renderable.RenderableObject 16 { 17 private CustomVertex.PositionTextured[] vertices;// 定义顶点变量 18 private Texture texture;//定义贴图变量 19 private Material material;//定义材质变量 20 public Bitmap bitmap = null; 21 public SimpleRasterShow(string name) 22 : base(name) 23 { 24 25 } 26 public override void Initialize(DrawArgs drawArgs) 27 { 28 this.isInitialized = true; 29 LoadTexturesAndMaterials(drawArgs); 30 VertexDeclaration(); 31 } 32 33 public override void Update(DrawArgs drawArgs) 34 { 35 if (!isInitialized && isOn) 36 { 37 Initialize(drawArgs); 38 } 39 } 40 41 public override void Render(DrawArgs drawArgs) 42 { 43 if (!isInitialized || !isOn) 44 return; 45 46 VertexFormats format = drawArgs.Device.VertexFormat; 47 FillMode currentCull = drawArgs.Device.RenderState.FillMode; 48 int currentColorOp = drawArgs.Device.GetTextureStageStateInt32(0, TextureStageStates.ColorOperation); 49 int zBuffer = drawArgs.Device.GetRenderStateInt32(RenderStates.ZEnable); 50 try 51 { 52 drawArgs.Device.RenderState.FillMode = FillMode.Solid; 53 drawArgs.Device.RenderState.Lighting = false; 54 55 drawArgs.Device.RenderState.DiffuseMaterialSource = ColorSource.Color1; 56 drawArgs.Device.RenderState.AlphaBlendEnable = true; 57 drawArgs.Device.RenderState.AlphaTestEnable = true; 58 59 drawArgs.Device.RenderState.ReferenceAlpha = 20; 60 drawArgs.Device.RenderState.AlphaFunction = Compare.Greater; 61 62 drawArgs.Device.RenderState.SourceBlend = Blend.SourceAlpha; 63 drawArgs.Device.RenderState.DestinationBlend = Blend.BothInvSourceAlpha; 64 drawArgs.Device.RenderState.BlendOperation = BlendOperation.Add; 65 66 drawArgs.Device.SetTexture(0, texture);//设置贴图 67 drawArgs.Device.TextureState[0].ColorOperation = TextureOperation.Modulate; 68 drawArgs.Device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor; 69 drawArgs.Device.TextureState[0].ColorArgument2 = TextureArgument.Current; 70 drawArgs.Device.TextureState[0].AlphaOperation = TextureOperation.SelectArg2; 71 drawArgs.Device.TextureState[0].AlphaArgument1 = TextureArgument.TextureColor; 72 //device.TextureState[0].AlphaArgument2 = TextureArgument.Diffuse; 73 74 drawArgs.Device.VertexFormat = CustomVertex.PositionTextured.Format; 75 drawArgs.Device.DrawUserPrimitives(PrimitiveType.TriangleList, 2, vertices); 76 } 77 catch (Exception ex) 78 { 79 Log.Write(ex); 80 } 81 finally 82 { 83 drawArgs.Device.VertexFormat = format; 84 drawArgs.Device.RenderState.FillMode = currentCull; 85 drawArgs.Device.SetTextureStageState(0, TextureStageStates.ColorOperation, currentColorOp); 86 drawArgs.Device.SetRenderState(RenderStates.ZEnable, zBuffer); 87 drawArgs.Device.Indices = null; 88 } 89 } 90 91 private void VertexDeclaration1()//定义顶点1 92 { 93 vertices = new CustomVertex.PositionTextured[3]; 94 vertices[0].Position = new Vector3(10f, 10f, 0f); 95 vertices[0].Tu = 1; 96 vertices[0].Tv = 0; 97 vertices[1].Position = new Vector3(-10f, -10f, 0f); 98 vertices[1].Tu = 0; 99 vertices[1].Tv = 1; 100 vertices[2].Position = new Vector3(10f, -10f, 0f); 101 vertices[2].Tu = 1; 102 vertices[2].Tv = 1; 103 } 104 private void VertexDeclaration()//定义顶点 105 { 106 vertices = new CustomVertex.PositionTextured[6]; 107 vertices[0].Position = new Vector3(10f, 10f, 0f); 108 vertices[0].Tu = 1; 109 vertices[0].Tv = 0; 110 vertices[1].Position = new Vector3(-10f, -10f, 0f); 111 vertices[1].Tu = 0; 112 vertices[1].Tv = 1; 113 vertices[2].Position = new Vector3(10f, -10f, 0f); 114 vertices[2].Tu = 1; 115 vertices[2].Tv = 1; 116 vertices[3].Position = new Vector3(-10f, -10f, 0f); 117 vertices[3].Tu = 0; 118 vertices[3].Tv = 1; 119 vertices[4].Position = new Vector3(10f, 10f, 0f); 120 vertices[4].Tu = 1; 121 vertices[4].Tv = 0; 122 vertices[5].Position = new Vector3(-10f, 10f, 0f); 123 vertices[5].Tu = 0; 124 vertices[5].Tv = 0; 125 126 } 127 128 private void LoadTexturesAndMaterials(DrawArgs args)//导入贴图和材质 129 { 130 material = new Material(); 131 material.Diffuse = Color.White; 132 material.Specular = Color.LightGray; 133 material.SpecularSharpness = 15.0F; 134 args.Device.Material = material; 135 //MemoryStream memory = new MemoryStream(); 136 //BinaryFormatter formatter = new BinaryFormatter(); 137 //formatter.Serialize(memory, bitmap); 138 int bufferSize = bitmap.Height * bitmap.Width * 4; 139 140 System.IO.MemoryStream memory = new System.IO.MemoryStream(); 141 142 bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Bmp); 143 memory.Seek(0, SeekOrigin.Begin); 144 texture = TextureLoader.FromStream(args.Device, memory); 145 //if (File.Exists(@"d:\temp.jpg")) 146 //{ 147 // File.Delete(@"d:\temp.jpg"); 148 //} 149 //bitmap.Save(@"d:\temp.jpg"); 150 //texture = TextureLoader.FromFile(args.Device, @"d:\temp.jpg"); 151 } 152 153 public override void Dispose() 154 { 155 } 156 157 public override bool PerformSelectionAction(DrawArgs drawArgs) 158 { 159 return true; 160 // throw new NotImplementedException(); 161 } 162 } 163 }
结果:
存在的问题:
其实就是读取影像的时候构建了一个BitMap,没有和金字塔结合,没有实现在放大缩小的时候动态加载金字塔数据。对于特别大的影像加载会失败!
其实初始加载的时候应该根据画布的大小,加载一个缩略的全局影像,放大过程中动态加载不同级别的金字塔影像!
作者:太一吾鱼水
文章未经说明均属原创,学习笔记可能有大段的引用,一般会注明参考文献。
欢迎大家留言交流,转载请注明出处。