내가 구현 한 D2D + 루틴 WIC 오늘. 테스트 결과는 정말 좋습니다.
이전 GDI StretchDIBits
버전에서는 1280x640 DDB를 1920x1080 창으로 그리는 데 20 ~ 60ms의 시간이 걸렸습니다. Direct2D + WIC로 전환 한 후 일반적으로 5ms 미만으로 소요되며 화질도 좋아집니다.
원시 픽셀 데이터를 읽고 쓰려면 WicBitmapRenderTarget과 함께 ID2D1HwndRenderTarget을 사용했습니다.
HWndRenderTarget은 화면 그림 (WM_PAINT)에만 사용됩니다.
HWndRenderTarget의 주된 장점은 대상 창 크기가 그리기 성능에 영향을 미치지 않는다는 것입니다.
WicBitmapRenderTarget은 임시 드로잉 캔버스 (GDI 드로잉의 메모리 DC)로 사용됩니다. WIC 비트 맵 객체 (예 : GDI DIBSection)를 사용하여 WicBitmapRenderTarget을 만들 수 있습니다. 언제든지이 WIC 비트 맵에서 /로 원시 픽셀 데이터를 읽고 쓸 수 있습니다. 또한 매우 빠릅니다. 참고로, 약간 비슷한 D3D GetFrontBufferData
전화는 정말 느립니다.
실제 픽셀 입출력은 IWICBitmap 및 IWICBitmapLock 인터페이스를 통해 수행됩니다.
쓰기 :
IWICBitmapPtr m_wicRemote;
...
const uint8* image = ...;
...
WICRect rcLock = { 0, 0, width, height };
IWICBitmapLockPtr wicLock;
hr = m_wicRemote->Lock(&rcLock, WICBitmapLockWrite, &wicLock);
if (SUCCEEDED(hr))
{
UINT cbBufferSize = 0;
BYTE *pv = NULL;
hr = wicLock->GetDataPointer(&cbBufferSize, &pv);
if (SUCCEEDED(hr))
{
memcpy(pv, image, cbBufferSize);
}
}
m_wicRenderTarget->BeginDraw();
m_wicRenderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
ID2D1BitmapPtr d2dBitmap;
hr = m_wicRenderTarget->CreateBitmapFromWicBitmap(m_wicRemote, &d2dBitmap.GetInterfacePtr());
if (SUCCEEDED(hr))
{
float cw = (renderTargetSize.width/2);
float ch = renderTargetSize.height;
float x, y, w, h;
FitFrameToCenter(cw, ch, (float)width, (float)height, x, y, w, h);
m_wicRenderTarget->DrawBitmap(d2dBitmap, D2D1::RectF(x, y, x + w, y + h));
}
m_wicRenderTarget->EndDraw();
읽기 :
IWICBitmapPtr m_wicCanvas;
IWICBitmapLockPtr m_wicLockedData;
...
UINT width, height;
HRESULT hr = m_wicCanvas->GetSize(&width, &height);
if (SUCCEEDED(hr))
{
WICRect rcLock = { 0, 0, width, height };
hr = m_wicCanvas->Lock(&rcLock, WICBitmapLockRead, &m_wicLockedData);
if (SUCCEEDED(hr))
{
UINT cbBufferSize = 0;
BYTE *pv = NULL;
hr = m_wicLockedData->GetDataPointer(&cbBufferSize, &pv);
if (SUCCEEDED(hr))
{
return pv; // return data pointer
// need to Release m_wicLockedData after reading is done
}
}
}
그리기 :
제 생각에는
ID2D1HwndRenderTargetPtr m_renderTarget;
....
D2D1_SIZE_F renderTargetSize = m_renderTarget->GetSize();
m_renderTarget->BeginDraw();
m_renderTarget->SetTransform(D2D1::Matrix3x2F::Identity());
m_renderTarget->Clear(D2D1::ColorF(D2D1::ColorF::Black));
ID2D1BitmapPtr d2dBitmap;
hr = m_renderTarget->CreateBitmapFromWicBitmap(m_wicCanvas, &d2dBitmap.GetInterfacePtr());
if (SUCCEEDED(hr))
{
UINT width, height;
hr = m_wicCanvas->GetSize(&width, &height);
if (SUCCEEDED(hr))
{
float x, y, w, h;
FitFrameToCenter(renderTargetSize.width, renderTargetSize.height, (float)width, (float)height, x, y, w, h);
m_renderTarget->DrawBitmap(d2dBitmap, D2D1::RectF(x, y, x + w, y + h));
}
}
m_renderTarget->EndDraw();
는, GDI Stretch..
API에 민감한 성능 (윈도우 7 + 설정에서 완전히 쓸모 응용 프로그램).
또한 Direct3D와는 달리 Direct2D에서는 텍스트 그리기, 링 그리기와 같은 기본적인 그래픽 작업이 매우 간단합니다.
예, StretchBlt가 실제로 느립니다. 또한 HALFTONE 옵션을 사용하여 더 많은 품질을 원한다면 실시간 렌더링에서 작업 할 수 없습니다. 어쨌든, 귀하의 소프트웨어는 어떤 OS를 대상으로합니까? –
@AntonAngelov 대상 OS는 Windows 7 이상입니다. 현재 내 랩톱은 (GDI 기준) 900x600 @ 20fps를 원활하게 처리 할 수 있으며 목표는 1920x1080 @ 30fps입니다. 다음 주에 결과가 나오면 다른 질문을하겠습니다. – 9dan
좋습니다. 하지만 질문을보다 정확하게 (예 : 한 문장으로) 작성할 수 있습니까? –