C#调用GDAL算法进度信息传递

GDAL库中提供了很多的算法,同时也提供了进度条的参数。对于C++调用来说,应该没什么问题,但是对C#调用来说,在进度条这块需要写一个代理来进行传递。首先写一个简单的测试代码。

首先定义一个委托函数原型,需要与GDAL库中的C#进度条接口保持一致,一个简单的原型如下。

    /// <summary>
    /// 进度信息回调函数
    /// </summary>
    /// <param name="dfComplete">完成比例,0~1之间的数</param>
    /// <param name="pszMessage">进度条信息</param>
    /// <param name="pProgressArg">进度条用户数据</param>
    /// <returns></returns>
    public delegate int ProgressFunc(double dfComplete, char[] pszMessage, IntPtr pProgressArg);

接下来在自己的测试代码中编写一个进度条函数,为了方便,先编写一个控制台的,直接从GDAL库中提供的控制台进度条修改而成,进度条函数代码如下。具体可以参考GDAL库中的控制台进度条实现代码,几乎完全一样,除了将printf函数改成了Console.Write,别的没有啥区别。

    class GDALAlgCsTest
    {
        //进度信息回调函数
        static int nLastTick = -1;
        public int TermProgress(double dfComplete, char[] strMessage, IntPtr Data)
        {
	        int nThisTick = (int) (dfComplete * 40.0);

	        nThisTick = Math.Min(40, Math.Max(0, nThisTick));

	        // Have we started a new progress run?
	        if( nThisTick < nLastTick && nLastTick >= 39 )
		        nLastTick = -1;

	        if( nThisTick <= nLastTick )
		        return 1;

	        while( nThisTick > nLastTick )
	        {
		        nLastTick++;
		        if( nLastTick % 4 == 0 )
                    Console.Write("{0}", (nLastTick / 4) * 10);
		        else
                    Console.Write(".");
            }

	        if( nThisTick == 40 )
                 Console.Write( " - done.\n");
	        else
                Console.Write("");

            return 1;
        }
}

接下来就是在测试代码中进行调用了。下面是我将GDAL库的算法进行了封装,不过进度条的接口与GDAL库中的算法进度条接口一模一样,我封装了一个波段合并的算法,就是将好几个单波段文件合并为一个多波段文件,主要是用来将Landsat卫星下载的分波段存储的数据进行合并形成一个多波段的数据。函数的接口声明如下:

        /// <summary>
        /// 图像波段合并
        /// </summary>
        /// <param name="astrSrcFileList">输入文件列表,所有的输入路径中间使用*号进行分割</param>
        /// <param name="strDstFile">输出文件路径</param>
        /// <param name="iDataType">栅格数据的数据类型(参考GDALDataType)</param>
        /// <param name="bUnion">范围不一致的图像处理方式,true为求并,false为求交</param>
        /// <param name="strFormat">输出文件格式,详细参考GDAL支持数据类型</param>
        /// <param name="pFun">进度条回调函数</param>
        /// <param name="pUserData">进度条指针</param>
        /// <returns>返回值,表示计算过程中出现的各种错误信息</returns>
        [DllImport("GDALAlg", EntryPoint = "ImageLayerStack")]
        public static extern int ImageLayerStack(char[] astrSrcFileList, char[] strDstFile, int iDataType,
            bool bUnion, string strFormat, ProgressFunc pFun, IntPtr pUserData);

最后两个参数就是进度条参数,倒数第二个为进度条回调函数(C#里面的委托函数),倒数第一个参数为进度条所需的参数信息。具体请参考我之前的进度条相关的博客。上面的函数实现此处不再进行说明,也不是本文的重点。下面就看看怎么调用这个函数并将进度条传入。

using System;
using GdalAlg;
using System.Collections;
using System.IO;
using System.Text;

namespace GDALAlgCS
{
    class GDALAlgCsTest
    {
        //进度信息回调函数
        static int nLastTick = -1;
        public int TermProgress1(double dfComplete, char[] strMessage, IntPtr Data)
        {
	        int nThisTick = (int) (dfComplete * 40.0);

	        nThisTick = Math.Min(40, Math.Max(0, nThisTick));

	        // Have we started a new progress run?
	        if( nThisTick < nLastTick && nLastTick >= 39 )
		        nLastTick = -1;

	        if( nThisTick <= nLastTick )
		        return 1;

	        while( nThisTick > nLastTick )
	        {
		        nLastTick++;
		        if( nLastTick % 4 == 0 )
                    Console.Write("{0}", (nLastTick / 4) * 10);
		        else
                    Console.Write(".");
            }

	        if( nThisTick == 40 )
                 Console.Write( " - done.\n");
	        else
                Console.Write("");

            return 1;
        }

        static void Main(string[] args)
        {
            //声明进度信息回调函数
            ProgressFunc pd = new ProgressFunc(new GDALAlgCsTest().TermProgress1);
            IntPtr p = new IntPtr(0);
            int ire = 0;

            string strLandsat1 = @"F:\Data\LandSat\LT51230322011159IKR00\LT51230322011159IKR00_B1.TIF";
            string strLandsat2 = @"F:\Data\LandSat\LT51230322011159IKR00\LT51230322011159IKR00_B2.TIF";
            string strLandsat3 = @"F:\Data\LandSat\LT51230322011159IKR00\LT51230322011159IKR00_B3.TIF";
            string strLandsat4 = @"F:\Data\LandSat\LT51230322011159IKR00\LT51230322011159IKR00_B4.TIF";
            string strLandsat5 = @"F:\Data\LandSat\LT51230322011159IKR00\LT51230322011159IKR00_B5.TIF";
            string strLandsat6 = @"F:\Data\LandSat\LT51230322011159IKR00\LT51230322011159IKR00_B6.TIF";
            string strLandsat7 = @"F:\Data\LandSat\LT51230322011159IKR00\LT51230322011159IKR00_B7.TIF";

            string strInfiles = strLandsat1 + "*" + strLandsat2 + "*" + strLandsat3 + "*" + strLandsat4 + "*" + strLandsat5 + "*" + strLandsat6 + "*" + strLandsat7;
            string strChineseOut = @"F:\Data\LandSat\LT51230322011159IKR00.tif";

            ire = GdalAlgInterface.ImageLayerStack(strInfiles.ToCharArray(), strChineseOut.ToCharArray(), 0, false, "GTiff", pd, p);

            Console.Write(ire.ToString());
        }
    }
}

上面程序运行中进度效果如下图所示。

上面的是控制台的,那么在图形界面中如何编写呢。接下来就写一个图形界面的进度条。声明代理函数都一样,只不过就是自己需要根据各自界面的进度条控件编写对应的进度函数。也就是上面类似的TermProgress1函数。首先做一个简单的界面,如下图所示。

首先看这个界面的进度条实现函数。在该Form类中定义一个进度条类,具体代码如下:

        public class Progress
        {
            public int ProgressBarInfo(double dfComplete, char[] strMessage, IntPtr pData)
            {
                GDALForm form = (GDALForm)Control.FromHandle(pData);

                int iValue = (int)(100 * dfComplete + 0.5);
                form.progressBar.Value = iValue;
                string strMsg = new string(strMessage);
                form.labelMessage.Text = strMsg;
                return 1;
            }
        }

首先对函数ProgressBarInfo的参数进行说明,dfComplete是进度信息,0~1之间的小数,strMessage是进度信息,主要是一些说明文字,最后一个pData是用户自定义的结构信息,这里的pData就是整个Form的handle。这样就可以从这个Form的handle中转换为界面类的一个对象,并从中获取进度条控件,然后将进度信息设置给进度条控件,将Message设置给界面的一个Label。

下面再看看函数调用。

        private void buttonOK_Click(object sender, EventArgs e)
        {
            try
            {
                int iRev = 0;
                string strInput = textBoxInput.Text;
                string strOutput = textBoxOutput.Text;
                string strField = "OBJECTID";

                ProgressFunc pd = new ProgressFunc(new Progress().ProgressBarInfo);
                IntPtr pre = this.Handle;
                iRev = GdalAlgInterface.ShpRasterize(strInput.ToCharArray(), strOutput.ToCharArray(), 10, 1, 0, strField.ToCharArray(), "GTiff", pd, pre);
                MessageBox.Show("处理返回代码:" + iRev.ToString(), "提示");
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(ex.ToString(), "提示");
            }
        }

在点击【计算】按钮之后,先获取输入和输出的文件路径,然后声明一个委托,用户定义的结构信息给当前form的handle。然后将委托函数和handle传入算法函数即可。程序运行的截图如下所示。该算法为矢量栅格化的一个封装函数。

上面的两个截图和界面设计截图有点不一致,主要是将矢量栅格化的几个参数可以由界面进行设置。上面的代码中这几个参数都是在代码中设置死的。其他的都一样,对于进度条这块没有任何变动。

时间: 2024-12-10 20:05:15

C#调用GDAL算法进度信息传递的相关文章

表单提交时如何将错误信息传递到页面中,并且保存原来提交数据

曾经何时,你还有我或许都在困惑,如何方便的将验证不通过的表单信息再返回到前台页面,例如我注册一个账号,辛辛苦苦填写了N多项,一个格式验证没有通过,一切都需要充填,虽然Ajax可以解决这个问题,但是我们总不能把所有表单提交都弄成ajax,更何况有若干人就是没事把javascript给禁止了.哎哎,好了解决方案来了,下面以用户登录为例,说说我的解决方案. 服务器端用nodejs实现: login.html 简单的提交表单 <form action="" id="loginF

【原创】用JAVA实现大文件上传及显示进度信息

用JAVA实现大文件上传及显示进度信息 ---解析HTTP MultiPart协议 一. 大文件上传基础描述: 各种WEB框架中,对于浏览器上传文件的请求,都有自己的处理对象负责对Http MultiPart协议内容进行解析,并供开发人员调用请求的表单内容. 比如: Spring 框架中使用类似CommonsMultipartFile对象处理表二进制文件信息. 而.NET 中使用HtmlInputFile/ HttpPostedFile对象处理二进制文件信息. 优点:使用框架内置对象可以很方便的

noip2015 信息传递 强连通块

时隔好久,重新把那些题找出来,写一写了,毕竟实力还很有限,得学. 一开始,最大的疑惑还是怕一个环里有另外一个环(毕竟经验不丰富),后来看到了这段话 T2 信息传递 大意:在一个只有n条有向边的图中,每个结点出度为1,求一个包含节点数最少的环. 分析:因为只有n条边并且每个点都有且仅有一条边连出去,所以只可能存在简单环,不会出现那种8字形的环套环. 证明:每个点有两种情况:1.不在任何一个环中 这样的点可以直接忽略掉,看成是有n-1个点,n-1条边来证明就行了.2.在某个环中.那么如果我们现在有了

NOIP 2015:信息传递

题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象).当有人从别人口中得知自己的生日时,游戏结束.请问该游戏一共可以进行几轮? 输入输出格式 输入格式: 输入共2行. 第1行包含1个正整数n表示

使用VB6写一个自定义的进度信息框窗口

一.起因说明 之前有些项目是用Access完成的,当时为了给用户显示一些进度信息,自制了一个进度信息窗体,类似下图所示: 随着项目不断变迁,需要将进度信息按阶段及子进度进行显示,并且出于代码封装的需求,需要将其封装到一个dll文件中.最终完成的效果如下图: 调用该进度信息框的代码类似如下所示: 1 Private Sub cmdCommand1_Click() 2 Dim pb As New CProgressBar 3 pb.AddStage "第一步", 10000 4 pb.Ad

[转] 实现winfrom进度条及进度信息提示,winfrom程序假死处理

china_xuhua 原文地址 1.方法一:使用线程 功能描述:在用c#做WinFrom开发的过程中.我们经常需要用到进度条(ProgressBar)用于显示进度信息.这时候我们可能就需要用到多线 程,如果不采用多线程控制进度条,窗口很容易假死(无法适时看到进度信息).下面我就简单结合一个我写的例子给大家做一个介绍. 第一步:设计界面,注意需要引用 using System.Threading; 控件名称分别为: progressBar1:label1:textBox1:button1: 第二

信息传递 NOIP2015 day1 T2

题文: 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象).当有人从别人口中得知自己的生日时,游戏结束.请问该游戏一共可以进行几轮? 输入共2行. 第1行包含1个正整数n表示n个人. 第2行包含n个用空

tg2015 信息传递 (洛谷p2661)

题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一轮中,所有人会同时将自己当前所知的生日信息告诉各自的信息传递对象(注意:可能有人可以从若干人那里获取信息,但是每人只会把信息告诉一个人,即自己的信息传递对象).当有人从别人口中得知自己的生日时,游戏结束.请问该游戏一共可以进行几轮? 输入输出格式 输入格式: 输入共2行. 第1行包含1个正整数n表示

实现winfrom进度条及进度信息提示,winfrom程序假死处理

1.方法一:使用线程 功能描述:在用c#做WinFrom开发的过程中.我们经常需要用到进度条(ProgressBar)用于显示进度信息.这时候我们可能就需要用到多线程,如果不采用多线程控制进度条,窗口很容易假死(无法适时看到进度信息).下面我就简单结合一个我写的例子给大家做一个介绍. 第一步:设计界面,注意需要引用 using System.Threading; 控件名称分别为: progressBar1:label1:textBox1:button1: 第二步:定义一个代理,用于更新Progr