ID2D1Bitmap1::Map 问题

ID2D1Bitmap1::Map issue

我有一个 ID2D1BitmapBrush。我想要实现的是获取其图像数据。这是我试过的:

// imageBrush - ID2D1BitmapBrush
// topLeft is a d2d1_point2u (0,0)
// uBounds is image bounding rectangle

Microsoft::WRL::ComPtr<ID2D1Bitmap> tmpBitmap;
Microsoft::WRL::ComPtr<ID2D1Bitmap1> tmpBitmap1;
D2D1_MAPPED_RECT bitmapData;

imageBrush->GetBitmap(tmpBitmap.ReleaseAndGetAddressOf());

///Creating a new bitmap

D2D1_SIZE_U dimensions;
dimensions.height = uBounds.bottom;
dimensions.width = uBounds.right;

D2D1_BITMAP_PROPERTIES1  d2dbp;
D2D1_PIXEL_FORMAT d2dpf;
FLOAT dpiX = 0;
FLOAT dpiY = 0;

d2dpf.format = DXGI_FORMAT_R8G8B8A8_UNORM;
d2dpf.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;

d2dFactory->GetDesktopDpi(&dpiX, &dpiY);

d2dbp.pixelFormat = d2dpf;
d2dbp.dpiX = dpiX;
d2dbp.dpiY = dpiY;
d2dbp.bitmapOptions = D2D1_BITMAP_OPTIONS_CPU_READ | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
d2dbp.colorContext = nullptr;

HRESULT hr = d2dCtx->CreateBitmap(dimensions, nullptr, 0, d2dbp, tmpBitmap1.GetAddressOf());

/// Getting image data

tmpBitmap1.Get()->CopyFromBitmap(&topLeft, tmpBitmap.Get(), &uBounds);
tmpBitmap1.Get()->Map(D2D1_MAP_OPTIONS_READ, &bitmapData);

问题是 - 最后 bitmapData.bits 是空的。

我哪里弄错了?

从上面的代码开始并提供适当的位图画笔后,只需要进行一些修改(保留变量名等)。

ID2D1Factory1* d2dFactory = /* [ get current factory ] */;
ASSERT(d2dFactory);

ID2D1DeviceContext* d2dCtx = /* [ get current target ] */;
ASSERT(d2dCtx);

Microsoft::WRL::ComPtr<ID2D1Bitmap> tmpBitmap { };
Microsoft::WRL::ComPtr<ID2D1Bitmap1> tmpBitmap1 { };
D2D1_MAPPED_RECT bitmapData { };

imageBrush->GetBitmap(tmpBitmap.ReleaseAndGetAddressOf());
ASSERT(tmpBitmap);

D2D1_SIZE_F const bitmapSize = tmpBitmap->GetSize();
ASSERT(bitmapSize.width > 0.0f);
ASSERT(bitmapSize.height > 0.0f);

D2D1_RECT_U const uBounds
{
    0u,
    0u,
    static_cast<UINT32>(bitmapSize.width),
    static_cast<UINT32>(bitmapSize.width)
};

D2D1_SIZE_U const dimensions
{
    uBounds.bottom,
    uBounds.right
};

D2D1_BITMAP_PROPERTIES1 d2dbp { };
D2D1_PIXEL_FORMAT d2dpf { };
FLOAT dpiX = 0.0f;
FLOAT dpiY = 0.0f;

// This modification to the color format was required 
// to correlate with my swap chain format.  Otherwise 
// you will receive an error [E_INVALIDARG ] when 
// calling CopyFromBitmap (as you had described)
d2dpf.format = DXGI_FORMAT_B8G8R8A8_UNORM; // <-- previously DXGI_FORMAT_R8G8B8A8_UNORM;
d2dpf.alphaMode = D2D1_ALPHA_MODE_PREMULTIPLIED;
d2dbp.pixelFormat = d2dpf;

d2dFactory->GetDesktopDpi(&dpiX, &dpiY);
d2dbp.dpiX = dpiX;
d2dbp.dpiY = dpiY;

d2dbp.bitmapOptions = D2D1_BITMAP_OPTIONS_CPU_READ | D2D1_BITMAP_OPTIONS_CANNOT_DRAW;
d2dbp.colorContext = nullptr;

HRESULT hr = S_OK;
// [ omitting the interrogation of hr ]
D2D1_POINT_2U const topLeft { uBounds.left, uBounds.top };
hr = d2dCtx->CreateBitmap(dimensions, nullptr, 0u, d2dbp, tmpBitmap1.GetAddressOf());
hr = tmpBitmap1.Get()->CopyFromBitmap(&topLeft, tmpBitmap.Get(), &uBounds);
hr = tmpBitmap1.Get()->Map(D2D1_MAP_OPTIONS_READ, &bitmapData);
ASSERT(bitmapData.pitch == /* [call funtion to determine pitch] */);
ASSERT(bitmapData.bits != nullptr);
// [ ... code to further utilize bits ]

主要更改是确保像素格式与交换链中设置的格式相关联,以避免在调用 CopyFromBitmap 时出现您描述的错误 (E_INVALIDARG One or more arguments are invalid)。

附加代码用于验证生成的 D2D1_MAPPED_RECT(音高和位)。希望这有帮助。