GDAL的C#版本虽然在很多算法接口没有导出,但是在读写数据中的接口基本上都是完全导出了。使用ReadRaster和WriteRaster方法来进行读写,同时对这两个方法进行了重载,对于常用的数据类型可以不用指定数据类型直接进行读取即可。但是对于复数类型就有点复杂了。下面就针对GDAL如何来读取复数数据来进行一个简单的说明。
 
   我们知道,在使用GDAL读取数据的时候使用的是ReadRaster这个函数,这个函数重载了6个,函数声明分别如下,以Dataset的ReadRaster为例,Band类中的ReadRaster与之类似。
 
   OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Byte[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
 
   OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Int16[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
 
   OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
 
   OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Single[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
 
   OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.Double[], System.Int32, System.Int32, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
 
   OSGeo.GDAL.Dataset.ReadRaster(System.Int32, System.Int32, System.Int32, System.Int32, System.IntPtr, System.Int32, System.Int32, OSGeo.GDAL.DataType, System.Int32, System.Int32[], System.Int32, System.Int32, System.Int32);
 
   前五个函数的声明基本上完全一致,除了第五个参数,分别是Byte[],Int16[],Int32[],Single[],Double[]。分别对应的是将图像中的像素值使用8U,16U\16S,32U\32S,32F和64F。如果图像数据是普通的数据(这里指的是除复数图像之外),那么这五个函数完全可以满足所有的需求。但是如果图像是复数图像(复数图像就是图像的像素值是由复数组成的,比如通过傅立叶变换后的图像),这时,上面的五个函数就有点爱莫能助了,就需要上面的第六个函数来出场救急了 www.lefeng123.com
 
   第六个函数的声明和C\C++的声明完全一致,使用C\C++的同学对这个接口应该比较熟悉。这个函数可以替代上面五个函数来使用,但是比较麻烦的时,就是传入的参数会比较多,首先看一个例子。使用普通的方式来读取一个单波段8U的数据(Landsat5的一个数据)。从数据中读取100×100大小的数据,直接使用ReadRaster的Byte接口。
 
   static void ReadRaster()
 
   {
 
   string strFile = @"D:\Data\landsat\etp139r26_5t19900902\p139r26_5t19900902_nn1.tif";
 
   OSGeo.GDAL.Gdal.AllRegister();
 
   OSGeo.GDAL.Dataset ds = OSGeo.GDAL.Gdal.Open(strFile, OSGeo.GDAL.Access.GA_ReadOnly);
 
   int []bandmap = new int [1];
 
   bandmap[0] = 1;
 
   //读取Byte类型
 
   Byte[] data = new Byte[100 * 100];
 
   OSGeo.GDAL.CPLErr err = ds.ReadRaster(3000, 2000, 100, 100, data, 100, 100, 1, bandmap, 0, 0, 0);
 
   //将读取的数据输出
 
   for (int i = 0; i < 100; i++ )
 
   {
 
   for (int j = 0; j < 100; j++)
 
   {
 
   Console.WriteLine("{0}", ddata[i*100+j]);
 
   }
 
   }
 
   Console.WriteLine("done\n");
 
   }
 
   下面看看如何使用第六个接口来完成上面的功能,代码如下:
 
   static void ReadRaster()
 
   {
 
   string strFile = @"D:\Data\landsat\etp139r26_5t19900902\p139r26_5t19900902_nn1.tif";
 
   OSGeo.GDAL.Gdal.AllRegister();
 
   OSGeo.GDAL.Dataset ds = OSGeo.GDAL.Gdal.Open(strFile, OSGeo.GDAL.Access.GA_ReadOnly);
 
   int []bandmap = new int [1];
 
   bandmap[0] = 1;
 
   //读取Byte类型
 
   Byte[] data = new Byte[100 * 100];
 
   //构造一个IntPtr,大小为100×100个Byte
 
   IntPtr ptr = Marshal.AllocCoTaskMem(data.Length);
 
   //需要指明读取的数据类型
 
   OSGeo.GDAL.CPLErr err = ds.ReadRaster(3000, 2000, 100, 100, ptr, 100, 100, OSGeo.GDAL.DataType.GDT_Byte, 1, bandmap, 0, 0, 0);
 
   //将读取到的数据拷贝到data中
 
   Marshal.Copy(ptr, data, 0, data.Length);
 
   //将读取的数据输出
 
   for (int i = 0; i < 100; i++ )
 
   {
 
   for (int j = 0; j < 100; j++)
 
   {
 
   Console.WriteLine("{0}", ddata[i*100+j]);
 
   }
 
   }
 
   Console.WriteLine("done\n");
 
   }
 
   从上面的代码中可以看出,使用第六个函数的时候,需要一个IntPtr的类型,使用Marshal类中的AllocCoTaskMem函数来进行分配内存空间(不知道C#中的说法是啥,按照C\C++中应该就是分配空间)。需要注意的是,分配的大小是按照字节(Byte)为单位的。接下来在调用ReadRaster时需要指定数据类型,调用之后,像素值应该都存储在这个IntPtr中了,然后再使用Marshal类中的Copy函数将IntPtr中的数据拷贝到Byte数组data中即可 www.tfjy386.com
 
   通过上面的代码,我们大致知道第六个ReadRaster的大致用法,接下来我们通过这个方法来读取一个复数类型的图像。没有复数类型的图像,可以使用ENVI随便打开一个图像,然后在Transform菜单下有个FFT,将打开的数据进行傅立叶变换,输出的结果就是一个复数图像。这里我将上面使用的Landsat的数据使用FFT转了下。使用下面的代码进行打开。
 
   static void ReadRaster()
 
   {
 
   string strFile = @"D:\Data\landsat\etp139r26_5t19900902\p139r26_5t19900902_nn1_fft.tif";
 
   OSGeo.GDAL.Gdal.AllRegister();
 
   OSGeo.GDAL.Dataset ds = OSGeo.GDAL.Gdal.Open(strFile, OSGeo.GDAL.Access.GA_ReadOnly);
 
   int []bandmap = new int [1];
 
   bandmap[0] = 1;
 
   //读取复数类型,由于一个复数由两个数据组成,所以读取100×100的像元需要2倍普通图像的大小
 
   double[] data = new double[100 * 100 * 2];
 
   //构造一个IntPtr,大小为100×100×2个double,一个double为4个byte,所以下面的长度要乘以8
 
   IntPtr ptr = Marshal.AllocCoTaskMem(data.Length*8);
 
   //需要指明读取的数据类型
 
   OSGeo.GDAL.CPLErr err = ds.ReadRaster(0, 0, 100, 100, ptr, 100, 100, OSGeo.GDAL.DataType.GDT_CFloat64, 1, bandmap, 0, 0, 0);
 
   //将读取到的数据拷贝到data中
 
   Marshal.Copy(ptr, data, 0, data.Length*8);
 
   //将读取的数据输出
 
   int in1 = 0;
 
   for (int i = 0; i < 100; i++ )
 
   {
 
   for (int j = 0; j < 100; j++)
 
   {
 
   Console.WriteLine("({0}*i+{1})", ddata[in1++], ddata[in1++]);
 
   }
 
   }
 
   Console.WriteLine("done\n");
 
   }
 
   在上面的代码中,一个复数由实部和虚部组成,所以一个像素值就对应于普通图像的2个像素值,故读取100×100大小的数据就需要分配普通图像2倍的大小。除此之外与读取普通图像一样,不过在最后获取像素值的时候,复数图像的像素值是顺序存储的,即实部,虚部,实部,虚部...这样的顺序来进行存储。

使用C#版本GDAL读取复数图像的更多相关文章

  1. OpenCV imread读取jpg图像的一个大坑

    长话短说 版本区间[OpenCV3.0.0, OpenCV3.4.1]内的OpenCV,(至少在windows下,使用官方提供的预编译版本),imread读取jpg图片后的像素值,和版本区间[Open ...

  2. GDAL关于读写图像的简明总结

    读写影像可以说是图像处理最基础的一步.关于使用GDAL读写影像,平时也在网上查了很多资料,就想结合自己的使用心得,做做简单的总结. 在这里写一个例子:裁剪lena图像的某部分内容,将其放入到新创建的. ...

  3. GDAL读取的坐标起点在像素左上角还是像素中心?

    目录 1. 问题 2. 结论 3. 例外 1. 问题 笔者在处理地理栅格数据的时候,总是会发生偏差半个像素的问题. 比如说通过ArcMap打开一张.tif,查看其地理信息:同时用记事本打开.tfw,比 ...

  4. GDAL读取Shp问题解决:Unable to open EPSG support file gcs.csv

    在GIS软件的开发中,经常用到开源库GDAL读取Shp数据,当shp数据中包含投影信息时,可能会遇到“Unable to open EPSG support file gcs.csv”错误提示,该错误 ...

  5. ArcGIS二次开发之读取遥感图像像素值的做法

    作者:朱金灿 来源:http://blog.csdn.net/clever101 首先是读取遥感图像的R.G.B波段数据的做法.读取R.G.B波段数据的像素值主要通过IRaster接口的Read方法在 ...

  6. VTK读取序列化图像

    vtk获取内存中图像数据 原文链接:http://blog.csdn.net/zmy3376365/article/details/7717721 内存中有段图片数据  ,使用VTK来读入,然后就可以 ...

  7. Halcon一日一练:读取文件目录图像的三种方法

    第一种方法: 读了一个单一图像: read_image(Image,'fabrik') 这种方式可以快速的读取软件自身携带的库图像文件,系统设定了库图像映像文件的快速读取方式,我们也可以通过绝对地址的 ...

  8. 从二进制数据流中构造GDAL可以读取的图像数据

    在很多时候,我们的图像数据往往都不是文件方式存储在磁盘上,而是可能从网络或者数据库中获取的是二进制的图像数据流.最简单的方式和最容易想到的方式就是将这个文件流保存到磁盘上形成一个文件,然后再使用GDA ...

  9. 从二进制数据流中构造GDAL可以读取的图像数据(C#)

    在上一篇博客中,讲了一下使用GDAL从文件流中构造一个GDAL可以识别的数据来进行处理.原以为这个接口在C#中没有,仔细看了下GDAL库中源码,发现C#版本也有类似的函数,下面是GDAL库中的一个C# ...

随机推荐

  1. JavaScript权威指南学习笔记6

    这两天主要翻看了书中的第18-22章,重点看了第17章:事件化处理,其它几章节主要是翻了下书知道有相关的概念,没有真正理解其中的内容,或者没有考虑究竟如何能把里面的内容应用到实际的项目中.说的讽刺一点 ...

  2. List<T> 和DataTable的相互转换

    我用的将集合类转换为DataTable 的方法 /// <summary> /// 将集合类转换成DataTable /// </summary> /// <param ...

  3. Linux下samba的安装与配置

    背景          在window7下面虚拟了一个CentOS6.3,为了学习命令行就没有装图形包,所以我的CentOS是黑屏的那种,呵呵,当然了,VMWare提供 的增强功能我就不能用了(或许能 ...

  4. 【归并排序】【逆序数】HDU 5775 Bubble Sort

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5775 题目大意: 冒泡排序的规则如下,一开始给定1~n的一个排列,求每个数字在排序过程中出现的最远端 ...

  5. Java中的局部代码块、构造代码块、静态代码块

    局部代码块: 作用:控制变量的生命周期: 在程序中,当我们已经使用完 x 后,并且在接下来的代码中,不会再用到x,那么就没必要让x 在内存中占用空间了,这用情况下,可以使用 局部代码块,将x及其所设计 ...

  6. [Design Pattern] Filter Pattern 简单案例

    Filter Pattern,即过滤模式,通过不同的过滤标准,或者低耦合将过滤标准组合在一起,对一组对象进行过滤,属于结构类的设计模式. 下面是一个过滤模式的简单案例. Criteria 定义过滤接口 ...

  7. Android Studio 遇见的第一个Error

    最近在国内多次尝试在Eclipse下更新SDK无果后,最后终于通过FQ后结束了Google服务器无法访问的噩梦. 顺着墙外的梯子,一并下载Google的Android Studio尝鲜,安装成功后,就 ...

  8. Selenium webdriver 查找元素

    1.简单查找 By ID: WebElement element=driver.findElement(By.id("userId")); By Name:WebElement e ...

  9. arc4random和arc4random_uniform

    Objective-C 中有个arc4random()函数用来生成随机数且不需要种子,但是这个函数生成的随机数范围比较大,需要用取模的算法对随机值进行限制,有点麻烦. 其实Objective-C有个更 ...

  10. 什么是MBS,ABS和CDO

    1. 都是资产证券化产品 华尔街有句名言“如果要增加未来的现金流,就把它做成证券.如果想经营风险,就把它做成证券”.从本质上来讲,MBS,ABS和 CDO都是资产证券化产品.根据美国证券交易委员会(S ...