C# 产生空白图像的图形-有时

C# 产生空白图像的图形-有时,c#,graphics,bitmap,vb6,handle,C#,Graphics,Bitmap,Vb6,Handle,我正在开发一个天文学应用程序,在这个应用程序中,我必须在一个PictureBox中显示一幅科学16位FITs格式(单色)的图像。我正在与另一个DLL接口,该DLL执行一些复杂的天体测量,还提供了FITS图片的缩放、8位DIB图像(没有chioce,但要使用此DLL)。但是,它是用VB6编写的,不能与C#VS2010位图一起使用。唯一的方法,我已经能够使这项工作是通过图形。“PaintPicture”是执行转换的外部dll方法。问题在于,这种方法通常会产生空白图像,尤其是在调试模式下: obs.F

我正在开发一个天文学应用程序,在这个应用程序中,我必须在一个PictureBox中显示一幅科学16位FITs格式(单色)的图像。我正在与另一个DLL接口,该DLL执行一些复杂的天体测量,还提供了FITS图片的缩放、8位DIB图像(没有chioce,但要使用此DLL)。但是,它是用VB6编写的,不能与C#VS2010位图一起使用。唯一的方法,我已经能够使这项工作是通过图形。“PaintPicture”是执行转换的外部dll方法。问题在于,这种方法通常会产生空白图像,尤其是在调试模式下:

obs.FITSbmp = new Bitmap(obs.p.Columns, obs.p.Rows);
pictureBoxFITS.BackgroundImage = obs.FITSbmp;
obs.g = Graphics.FromImage(obs.FITSbmp); 
//Have to go thru graphics as PP targets VB6
obs.pic.PaintPicture((int)obs.g.GetHdc());
obs.g.ReleaseHdc();

有人知道为什么会发生这种情况,更重要的是,知道如何解决它吗?我是在这里遗漏了什么,还是做错了什么?

这与我的专业领域相去甚远,但这里有一些提示可能会有所帮助:

  • 看起来您(和或DLL)使用的是GDI

    • 确保所有调用都来自主应用程序线程
    • 如果没有,那么GDI有时不能正常工作
    • 桌面/全屏上的所有可视内容也是如此
  • 是否确实正确渲染了未转换的位图

    • 在转换之前尝试将其转储到文件
    • 并在问题发生后进行检查
    • 如果它也是空的,那么
    • 问题可能在别处
  • <强> [Eddi1] VCL直接位图访问<强>(代码在BDS2006 C++中,所以必须将*BMP素材转换成VB样式)

    //---------------------------------------------------------------------------
    void bmp_示例()
    {
    图形::TBitmap*bmp;
    int**pyx=NULL,xs=0,ys=0;
    //[初始化位图使用]
    bmp=新图形::TBitmap;//新VCL位图
    bmp->HandleType=bmDIB;//独立于设备,允许直接访问
    bmp->PixelFormat=pf32bit;//我使用32位匹配int/DWORD变量大小的像素
    //在这里渲染/加载数据到bmp
    bmp->Width=2500;//例如,将bmp调整为128x128像素
    bmp->高度=2500;
    //为直接访问创建所有neded
    //必须在任何位图realloc/RESIGH后执行此操作
    //主要思想是将指针存储到您自己的变量中
    //并通过它们而不是GDI访问,以避免检查减速
    如果(pyx)删除pyx;
    xs=bmp->Width;//xs,ys=实际bmp大小
    ys=bmp->高度;
    bmp->HandleType=bmDIB;//独立于设备,允许直接访问
    bmp->PixelFormat=pf32bit;//我使用32位匹配int/DWORD变量大小的像素
    pyx=新整数*[ys];
    对于(int y=0;yScanLine[y];
    //[直接存取]
    int x,y,*p;
    
    对于(y=0;yHi Spektre-我认为这是迄今为止我所听到的最好的想法,可以解释这种不稳定的行为。我根本无法控制dll,也无法将其输出复制到文件中。基本上,我所能做的就是调用封装方法,剩下的就是一个黑匣子。我知道这不是最优的,但制造商不会做出任何更改来帮助事实上,我使用的95%都很好,但是图像显示对用户来说很重要,即使它是次要的。我唯一能控制的就是我自己。你知道我如何在主线程中强制它吗?我举个简单的例子会很有帮助。tnxi如果DLL创建自己的线程进行处理,那么答案是否定的,如果你只调用blocki从DLL调用函数(将暂停代码直到完成,然后继续),然后它们的调用必须在主线程内(在应用程序窗口的事件内,如在计时器上、在按钮上单击等…或消息过程中)。此外,您还可以测试输出是否为空,如果为空,则重复渲染,直到没有其他结果。PS这也可能是由于视觉框架(.net…只有在有帮助的情况下才尝试基本MFC内容)导致的某些不兼容我担心DLL会创建自己的线程,所以测试bmp可能是目前最好的解决方案。我确实获得了一个动态值数组(16位),并尝试将其转换为bmp,但时间太长:首先将其转换为8位(基于直方图)然后SetPixel太慢了。在6MP图像上,这需要一段时间。知道从字节数组生成单色图像的快速方法吗?我讨厌原始DLL接口,并且被锁定在其中…顺便说一句,非常感谢您的帮助和时间。Get/Set Pixels太慢(检查和转换太多)请改用扫描线(每行只检查一次)或从中创建一个线指针数组,这样就不会执行任何检查。(对于简单网格,我的软件位图渲染速度高达70fps,因此对于单次测光转换应该足够快)我尝试过,但我的图像非常大,比如6MP。相反,我使用了Marshal.Copy(pixel_array,0,data.Scan0,pixel_array.Length)。这似乎是绘制图片的最快方法。现在处理输入数组需要更长的时间。数据是16位单色格式,但我只显示其中的一部分(通常为1000到4000),这些参数取决于图像直方图。因此,我必须将字节数组渲染为这些值之间的8位。我仍在考虑最快的方法。现在它只是几个“for”循环。有什么想法吗?
    //---------------------------------------------------------------------------
    void bmp_example()
        {
        Graphics::TBitmap *bmp;
        int **pyx=NULL,xs=0,ys=0;
    
        // [init bitmap use]
        bmp=new Graphics::TBitmap;  // new VCL bitmap
        bmp->HandleType=bmDIB;      // is Device independent to allow direct access
        bmp->PixelFormat=pf32bit;   // i use 32 bit to match pixel with int/DWORD variable size
    
        // here render/load data into bmp
        bmp->Width=2500;             // for example resize bmp to 128x128 pixels
        bmp->Height=2500;
    
        // create all neded for direct  access
        // must do this after any bitmap realloc/resize
        // main idea is to store pointers into your own variables
        // and access throu them instead of GDI to avoid checking slow-downs
        if (pyx) delete pyx;
        xs=bmp->Width;              // xs,ys = actual bmp size
        ys=bmp->Height;
        bmp->HandleType=bmDIB;      // is Device independent to allow direct access
        bmp->PixelFormat=pf32bit;   // i use 32 bit to match pixel with int/DWORD variable size
        pyx=new int*[ys];
        for (int y=0;y<ys;y++)      // copy line pointers to pyx
         pyx[y]=(int*)bmp->ScanLine[y];
    
        // [direct access]
        int x,y,*p;
        for (y=0;y<ys;y++)          // fill whole bmp
         for (x=0;x<xs;x++)
            {                       // this will fill bmp with grayscale diagonal patern
            pyx[y][x]=((x+y)&255)*0x00010101;
            }
        for (x=0;x<xs;x++)          // does not mater which loop is first
         for (y=0;y<ys;y++)
            {                       // this will fill bmp with grayscale diagonal patern
            pyx[y][x]=((x+y)&255)*0x00010101;
            }
        for (y=0;y<ys;y++)          // this is bit faster (but not by much and limitaccess to lines so y loop must be first)
            {
            p=pyx[y];               // acces just line to avoid 2D addresing
            for (x=0;x<xs;x++)
                {                   // this will clear bmp with white color
                p[x]=0x00FFFFFF;
                }
            }
    
        // [exit btmap use]
        if (bmp) delete bmp; bmp=NULL;
        if (pyx) delete pyx; pyx=NULL;
        }
    //---------------------------------------------------------------------------