Optimize converting internal Direct2D renderer bitmap to wxImage.
Get access to bitmap bits with IWICBitmap::Lock instead of IWICBitmapSource::CopyPixels because in-place processing is more effective in terms of speed and memory consumption (see IWICBitmap interface description in MSDN). See #17311.
This commit is contained in:
@@ -2336,17 +2336,41 @@ protected:
|
|||||||
private:
|
private:
|
||||||
void FlushRenderTargetToImage()
|
void FlushRenderTargetToImage()
|
||||||
{
|
{
|
||||||
int width = m_resultImage->GetWidth();
|
const int width = m_resultImage->GetWidth();
|
||||||
int height = m_resultImage->GetHeight();
|
const int height = m_resultImage->GetHeight();
|
||||||
int bufferSize = 4 * width * height;
|
|
||||||
|
|
||||||
BYTE* buffer = new BYTE[bufferSize];
|
WICRect rcLock = { 0, 0, width, height };
|
||||||
m_wicBitmap->CopyPixels(NULL, 4 * width, bufferSize, buffer);
|
IWICBitmapLock *pLock = NULL;
|
||||||
unsigned char* dest = m_resultImage->GetData();
|
HRESULT hr = m_wicBitmap->Lock(&rcLock, WICBitmapLockRead, &pLock);
|
||||||
unsigned char* destAlpha = m_resultImage->GetAlpha();
|
wxCHECK_HRESULT_RET(hr);
|
||||||
|
|
||||||
|
UINT rowStride = 0;
|
||||||
|
hr = pLock->GetStride(&rowStride);
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
{
|
||||||
|
pLock->Release();
|
||||||
|
wxFAILED_HRESULT_MSG(hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT bufferSize = 0;
|
||||||
|
BYTE *pBmpBuffer = NULL;
|
||||||
|
hr = pLock->GetDataPointer(&bufferSize, &pBmpBuffer);
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
{
|
||||||
|
pLock->Release();
|
||||||
|
wxFAILED_HRESULT_MSG(hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
WICPixelFormatGUID pixelFormat;
|
WICPixelFormatGUID pixelFormat;
|
||||||
m_wicBitmap->GetPixelFormat(&pixelFormat);
|
hr = pLock->GetPixelFormat(&pixelFormat);
|
||||||
|
if ( FAILED(hr) )
|
||||||
|
{
|
||||||
|
pLock->Release();
|
||||||
|
wxFAILED_HRESULT_MSG(hr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
wxASSERT_MSG( pixelFormat == GUID_WICPixelFormat32bppPBGRA ||
|
wxASSERT_MSG( pixelFormat == GUID_WICPixelFormat32bppPBGRA ||
|
||||||
pixelFormat == GUID_WICPixelFormat32bppBGR,
|
pixelFormat == GUID_WICPixelFormat32bppBGR,
|
||||||
wxS("Unsupported pixel format") );
|
wxS("Unsupported pixel format") );
|
||||||
@@ -2354,21 +2378,29 @@ private:
|
|||||||
// Only premultiplied ARGB bitmaps are supported.
|
// Only premultiplied ARGB bitmaps are supported.
|
||||||
const bool hasAlpha = pixelFormat == GUID_WICPixelFormat32bppPBGRA;
|
const bool hasAlpha = pixelFormat == GUID_WICPixelFormat32bppPBGRA;
|
||||||
|
|
||||||
int k = 0;
|
unsigned char* destRGB = m_resultImage->GetData();
|
||||||
while (k < width * height)
|
unsigned char* destAlpha = m_resultImage->GetAlpha();
|
||||||
|
for( int y = 0; y < height; y++ )
|
||||||
{
|
{
|
||||||
wxPBGRAColor color = wxPBGRAColor(buffer + k * 4);
|
BYTE *pPixByte = pBmpBuffer;
|
||||||
|
for ( int x = 0; x < width; x++ )
|
||||||
|
{
|
||||||
|
wxPBGRAColor color = wxPBGRAColor(pPixByte);
|
||||||
unsigned char a = hasAlpha ? color.a : 255;
|
unsigned char a = hasAlpha ? color.a : 255;
|
||||||
// Undo premultiplication for ARGB bitmap
|
// Undo premultiplication for ARGB bitmap
|
||||||
dest[k * 3 + 0] = (a > 0 && a < 255) ? ( color.r * 255 ) / a : color.r;
|
*destRGB++ = (a > 0 && a < 255) ? ( color.r * 255 ) / a : color.r;
|
||||||
dest[k * 3 + 1] = (a > 0 && a < 255) ? ( color.g * 255 ) / a : color.g;
|
*destRGB++ = (a > 0 && a < 255) ? ( color.g * 255 ) / a : color.g;
|
||||||
dest[k * 3 + 2] = (a > 0 && a < 255) ? ( color.b * 255 ) / a : color.b;
|
*destRGB++ = (a > 0 && a < 255) ? ( color.b * 255 ) / a : color.b;
|
||||||
if ( destAlpha )
|
if ( destAlpha )
|
||||||
*destAlpha++ = a;
|
*destAlpha++ = a;
|
||||||
++k;
|
|
||||||
|
pPixByte += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete[] buffer;
|
pBmpBuffer += rowStride;
|
||||||
|
}
|
||||||
|
|
||||||
|
pLock->Release();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Reference in New Issue
Block a user