🦍
[.NET5] ピクセルデータを描画する処理時間の比較
0. やりたいこと
- ピクセルデータは外部から転送されてくることを想定(カメラ等)
- ワークメモリはアプリ起動中は解放されない
上記環境を想定して、フレームイベント毎にピクセルデータを画面に描画したい。
1. テストコード
#pragma once
#ifdef _DEBUG
#pragma comment(lib, "opencv_world450d.lib")
#else
#pragma comment(lib, "opencv_world450.lib")
#endif
#pragma comment(lib, "Gdi32.lib")
#include <windows.h>
#include <opencv2\opencv.hpp>
#using <System.dll>
#using <System.Drawing.dll>
//#using <System.Drawing.Common.dll>
using namespace System;
using namespace System::Drawing;
using namespace System::Drawing::Imaging;
namespace Library
{
public ref class Class
{
private:
static byte* _data;
static cv::Mat* _mat;
public:
static void TestInit()
{
_data = new byte[640 * 480 * 3](); // zero clear
_mat = new cv::Mat(480, 640, CV_8UC3, _data);
//- 実環境では、カメラ等から取得したピクセルデータを想定
auto temp = cv::imread("./image.bmp", cv::IMREAD_COLOR);
memcpy(_mat->data, temp.data, 640 * 480 * 3);
//------------
}
static void DrawWithBitmap(Bitmap^% bitmap)
{
bitmap = gcnew Bitmap(_mat->cols, _mat->rows, _mat->step, PixelFormat::Format24bppRgb, IntPtr(_mat->data));
}
static void DrawWithMemcpy(Bitmap^% bitmap)
{
auto bmpData = bitmap->LockBits(System::Drawing::Rectangle(0, 0, _mat->cols, _mat->rows), ImageLockMode::ReadWrite, PixelFormat::Format24bppRgb);
memcpy(bmpData->Scan0.ToPointer(), _mat->data, _mat->cols * _mat->rows * 3);
bitmap->UnlockBits(bmpData);
}
static void DrawWithGraphics(Bitmap^% bitmap)
{
auto temp = gcnew Bitmap(_mat->cols, _mat->rows, _mat->step, PixelFormat::Format24bppRgb, IntPtr(_mat->data));
auto g = Graphics::FromImage(bitmap);
g->DrawImage(temp, 0, 0, _mat->cols, _mat->rows);
delete g;
delete temp;
}
static void DrawWithDC(Bitmap^% bitmap)
{
auto temp = gcnew Bitmap(_mat->cols, _mat->rows, _mat->step, PixelFormat::Format24bppRgb, IntPtr(_mat->data));
auto g = Graphics::FromImage(bitmap);
auto pDC = g->GetHdc();
HDC hDC = static_cast<HDC>(pDC.ToPointer());
HDC hMemDC = CreateCompatibleDC(hDC);
HGDIOBJ hBitmap = static_cast<HGDIOBJ>(temp->GetHbitmap().ToPointer());
HGDIOBJ oldObj = SelectObject(hMemDC, hBitmap);
BitBlt(hDC, 0, 0, _mat->cols, _mat->rows, hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, oldObj);
DeleteObject(hBitmap);
DeleteDC(hMemDC);
g->ReleaseHdc(pDC);
delete g;
delete temp;
}
};
}
2. 結果
・環境
- .NET5
- C#/WinForms
- C++/CLI
- OpenCV4.5
・条件1
VGA: 640×480
試行回数: 10,000
Function | Time [ms] |
---|---|
DrawWithBitmap | 0.0098 |
DrawWithMemcpy | 0.0261 |
DrawWithGraphics | 0.7575 |
DrawWithDC | 2.2837 |
・条件2
8K: 7,680×4,320
試行回数: 1,000
Function | Time [ms] |
---|---|
DrawWithBitmap | 0.0091 |
DrawWithMemcpy | 7.0200 |
DrawWithGraphics | 80.4080 |
DrawWithDC | 27.0260 |
3. おわり
洗練されたコードではありませんが、明確な結果が出たと思います。
Discussion