图形生成空白图像 - 有时

时间:2013-12-27 05:06:14

标签: c# graphics bitmap vb6 handle

我正在研究天文学应用程序,我必须在PictureBox中显示科学16位FIT格式(单色)的图像。我正在与执行一些复杂天体测量的另一个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();

有没有人知道为什么会这样,更重要的是,如何解决这个问题?我在这里遗漏了什么,或者我做错了什么?

1 个答案:

答案 0 :(得分:1)

这离我的专业领域很远,但这里有一些提示可能会有所帮助:

  1. 看起来你(和/或DLL)使用GDI。

    • 确保所有调用都来自主应用程序线程。
    • 如果没有,那么GDI有时不能正常工作......
    • 同样适用于桌面/全屏的所有视觉内容
  2. 你确定未转换的位图是否正确呈现?

    • 尝试在转换前将其转储到文件
    • 并在问题发生后进行检查
    • 如果它也是空白那么
    • 问题可能出在其他地方
  3. [Edit1] VCL直接位图访问(BDS2006 C ++中的代码,所以你必须将* bmp的东西转换为VB风格)

    //---------------------------------------------------------------------------
    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;
        }
    //---------------------------------------------------------------------------
    
    • 此示例3次填充 2500x2500像素32位位图~6MP
    • 我机器上的
    • (Win7 x64 AMD 3.2GHz)运行时间大约118ms (编译为32位应用程序)
    • 避免使用位图使用pyx,xs,ys代替
    • 如果这没有帮助,那么您的代码可能会遇到一些性能问题
    • 但是没有在这里张贴我只是猜测
    • 最好的方法是衡量处理步骤的时间
    • 然后你会看到减速的位置
    • 我想直方图中有一些可怕的编码循环
    • 不要忘记在删除之前将位图绘制到窗口
    • 你也可以在app init / exit上分配/删除它,并将它一直放在内存中
    • 任何调整大小,格式更改(甚至在DLL函数内)都可以重新分配位图内存,因此pyx必须在...之后更新。

    [编辑2]我还有另外一个想法可能是错的。

    我看到您正在从DLL访问piantbox位图

    • paintbox有时候不应该更新图像(至少从VCL开始)
    • 这可能会使您的图像失效(我之前也遇到过问题)
    • 通常很好的放置更新调用排序
    • 或尝试创建单独的位图并从DLL渲染它,然后将其绘制到paintbox上。
    • 如果它是空白而位图不是那么只是将它再次绘制到paintbox