I'm struggling getting the size of the result of gaussian blur ID2D1Effect
(CLSID_D2D1GaussianBlur
).
I want to draw a shadow box behind a rectangle where the shadow will be positioned such that the rectangle is in the center of the shadow.
I start by creating an IWICBitmap
with the size of the rectangle in DIPs like this:
ComPtr<IWICBitmap> bitmap;
HRESULT hr = wic_factory_->CreateBitmap(size.w, size.h, convert_format(ImageFormat::argb32_premultiplied),
WICBitmapCacheOnDemand, &bitmap);
Then I fill this bitmap with black (or the shadow color) and make ID2D1Bitmap
from it:
ComPtr<ID2D1Bitmap> shadow_bitmap;
HRESULT hr = render_target_->CreateBitmapFromWicBitmap(wic_bitmap.Get(), &shadow_bitmap);
I verify that the size of bitmap in DIPs returned from shadow_bitmap->GetSize()
almost equals the size of the rectangle (due to float ceiling when creating the wic bitmap)
After that I create the effect and apply it:
ComPtr<ID2D1Effect> blur_effect;
d2d_context_->CreateEffect(CLSID_D2D1GaussianBlur, &blur_effect);
blur_effect->SetInput(0, shadow_bitmap.Get());
blur_effect->SetValue(D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION, shadow_opts.width * 3);
blur_effect->SetValue(D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION, D2D1_DIRECTIONALBLUR_OPTIMIZATION_QUALITY);
Microsoft docs say that the blur radius (width increase of shadow) is the deviation (in DIPs) multiplied by 3 hence I'm doing so.
Then I get the output and get the local bounds in DIPs (the transform of the target will be applied when drawing the image)
ComPtr<ID2D1Image> out_img;
blur_effect->GetOutput(&out_img);
D2D1_RECT_F img_rect{};
d2d_context_->GetImageLocalBounds(out_img.Get(), &img_rect);
Thing I didn't expect start from here:
img_rect.right
or img_rect.right - img_rect.left
?Output bitmap growth (X and Y) = StandardDeviation (DIPs)6((User DPI)/96)
Also, the document is unclear (or I didn't understand well) is this growth in pixels or DIPs?
Due to the above I'm having trouble positioning the shadow so the rectangle is in its center
Seems to have got it now!
The GetImageLocalBounds
outputs a rectangle whose fields are interpreted as follows:
right
fieldbottom
fieldtop
field equals the total vertical increase (if negative) or decrease (if positive) from input images to output image. Note this is the total in both top and bottomleft
field equals the total horizontal increase or decreaseIn case of blur effect the horizontal increase is the same in each side and equals left / 2
. The same for vertical increase also.
When you pass the image to DrawImage
and pass an offset of (0, 0)
the output image' top left point will not be drawn at (0, 0)
but instead at (left, top)
of its bound rectangle.
There is still another thing about direct2d bluring I didn't manage to do it: control the growth of the image.