【问题标题】:Drawing a CachedBitmap in Winforms在 Winforms 中绘制 CachedBitmap
【发布时间】:2014-03-25 02:32:33
【问题描述】:

我尝试在 Winforms 中显示缓存的位图(出于性能原因)。我有一个问题,因为我无法绘制它。 这个答案中的例子https://stackoverflow.com/a/6474581/1676819 说应该有类似的东西 graphics.DrawCachedBitmap(bitmap, 0, 0); 我找不到它。

到目前为止我做了什么:

  • 我添加了 Presentationcore.dll 作为参考
  • 我创建了一个CachedBitmap

CachedBitmap tempCBm = new CachedBitmap(new BitmapImage(new Uri(@"D:\test.bmp")),BitmapCreateOptions.None, BitmapCacheOption.OnLoad);

  • 我尝试用标准方法绘制它(导致错误)

    private void CustomPaint(object sender, PaintEventArgs e)
    {
            e.Graphics.DrawImage(tempCBm, 0,0);//error
    }
    

谁能告诉我我做错了什么?非常感谢。

【问题讨论】:

    标签: c# winforms bitmap


    【解决方案1】:

    CachedBitmap 无法通过 .NET 获得。这是 GDI+ 的一个特性。请改用Bitmap。如果您需要优化性能,那么您可以使用unsafe context in C# for faster bitmap access

    这里有一个很好的教程:http://www.codeproject.com/Tips/240428/Work-with-bitmap-faster-with-Csharp

    【讨论】:

    • 这是否也提高了位图绘制所需的时间?我认为这只会提高 get/setpixel ...
    • 如果您使用的是不安全的方法,那么您将需要实现自己的绘图功能。如果您想使用Graphics 对象进行绘制,则必须使用较慢的Bitmap 版本。
    【解决方案2】:

    可以使用缓存位图 - 但由于某种原因,它在标准 C# api 中不可用。但是,您可以绕过它 - 创建一个托管 C++ 库,该库将封装您想要公开给 C# 的方法。

    查看我的 github 存储库 - https://github.com/svejdo1/CachedBitmap

    用于公开缓存位图的 C++ 实用程序类

    #include <windows.h>
    #include <objidl.h>
    #include <gdiplus.h>
    
    using namespace Gdiplus;
    
    namespace CachedBitmapUtility {
        public ref class BitmapUtility {
            public:
                static void* CreateCachedBitmapPtr(void* bitmapPtr, void* graphicsHdc) {
                    Graphics graphics((HDC)graphicsHdc);
                    CachedBitmap* result = new CachedBitmap((Bitmap*)bitmapPtr, &graphics);
                    return result;
                }
                static void DisposeCachedBitmap(void* cachedBitmapPtr) {
                    delete (CachedBitmap*)cachedBitmapPtr;
                }
                static void DisposeBitmap(void* bitmapPtr) {
                    delete (Bitmap*)bitmapPtr;
                }
                static void* GetBitmapPtrFromHICON(void* hicon) {
                    return (void*)Bitmap::FromHICON((HICON)hicon);
                }
                static void DrawCachedBitmap(void* hdc, void* cachedBitmapPtr, int x, int y) {
                    Graphics graphics((HDC)hdc);
                    graphics.DrawCachedBitmap((CachedBitmap*)cachedBitmapPtr, x, y);
    
                }
        };
    }
    

    来自 WinForm 应用程序的示例用法:

    public partial class MainForm : Form {
      IntPtr m_BitmapPtr;
      IntPtr m_CachedBitmapPtr = IntPtr.Zero;
    
      public MainForm() {
        InitializeComponent();
    
        Bitmap bitmap;
        using (var stream = typeof(MainForm).Assembly.GetManifestResourceStream("FormApplication.character.png")) {
          bitmap = (Bitmap)Bitmap.FromStream(stream);
        }
        unsafe {
          m_BitmapPtr = (IntPtr)BitmapUtility.GetBitmapPtrFromHICON((void*)bitmap.GetHicon());
        }
      }
    
      protected override void OnClosed(EventArgs e) {
        // TODO: refactor - dispose should happen in Dispose event
        unsafe {
          BitmapUtility.DisposeBitmap((void*)m_BitmapPtr);
          BitmapUtility.DisposeCachedBitmap((void*)m_CachedBitmapPtr);
        }
      }
    
      protected override void OnPaint(PaintEventArgs e) {
        var graphics = e.Graphics;
        IntPtr hdc;
        if (m_CachedBitmapPtr == IntPtr.Zero) {
          hdc = graphics.GetHdc();
          unsafe {
            m_CachedBitmapPtr = (IntPtr)BitmapUtility.CreateCachedBitmapPtr((void*)m_BitmapPtr, (void*)hdc);
          }
          graphics.ReleaseHdc(hdc);
        }
    
        hdc = graphics.GetHdc();
        unsafe {
          BitmapUtility.DrawCachedBitmap((void*)hdc, (void*)m_CachedBitmapPtr, 0, 0);
        }
        graphics.ReleaseHdc(hdc);
      }
    }
    

    【讨论】:

    • 嗨 Ondrej - 你有从那个 c++ 代码编译的 DLL 吗?
    • 我刚刚在我的一个程序上实现了您的代码,它的性能提高了大约 400%!所以谢谢。但是,尝试使用 ScaleTransform(我添加到您的 CachedBitmapUtility 类中)不会产生明显的输出;也就是说,似乎没有呈现任何内容。你知道为什么吗?
    • @xfx - 我愿意 - 如果绘制缓存位图,则不能使用 ScaleTransform 或 RotateTransform。查看 DrawCachedBitmap 函数返回的值——我敢打赌它会返回 WrongState。这里唯一的解决方法是生成各种比例(或旋转等)的位图并缓存缩放/旋转/等。版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-11
    • 2011-03-18
    相关资源
    最近更新 更多