I need to render a dropshadow of bitmap A onto bitmap B using Direct2D.
More specifically, A is 32-bit with alpha-transparency, i.e. some pixels can be transparent. B (also 32-bit) contains another image, i.e. it can't be assumed empty.
Can someone provide a working example of how to do that?
Preferably as a method that takes blur amount, distance, color and opacity of the dropshadow as parameters.
The C++ code I'm trying to convert is the below from MS. But I'm not sure about converting the C++ syntax and also the D2D2 libraries in Delphi XE2 seem to be incomplete.
ComPtr<ID2D1Effect> shadowEffect;
m_d2dContext->CreateEffect(CLSID_D2D1Shadow, &shadowEffect);
shadowEffect->SetInput(0, bitmap);
// Shadow is composited on top of a white surface to show opacity.
ComPtr<ID2D1Effect> floodEffect;
m_d2dContext->CreateEffect(CLSID_D2D1Flood, &floodEffect);
floodEffect->SetValue(D2D1_FLOOD_PROP_COLOR, D2D1::Vector4F(1.0f, 1.0f, 1.0f, 1.0f));
ComPtr<ID2D1Effect> affineTransformEffect;
m_d2dContext->CreateEffect(CLSID_D2D12DAffineTransform, &affineTransformEffect);
affineTransformEffect->SetInputEffect(0, shadowEffect.Get());
D2D1_MATRIX_3X2_F matrix = D2D1::Matrix3x2F::Translation(20, 20));
affineTransformEffect->SetValue(D2D1_2DAFFINETRANSFORM_PROP_TRANSFORM_MATRIX, matrix);
ComPtr<ID2D1Effect> compositeEffect;
m_d2dContext->CreateEffect(CLSID_D2D1Composite, &compositeEffect);
compositeEffect->SetInputEffect(0, floodEffect.Get());
compositeEffect->SetInputEffect(1, affineTransformEffect.Get());
compositeEffect->SetInput(2, bitmap);
m_d2dContext->BeginDraw();
m_d2dContext->DrawImage(compositeEffect.Get());
m_d2dContext->EndDraw();
Related
I want to load the Glyph of a TSpeedButton at runtime from a TImageList. In that image list I have 32bit bitmaps (RGB + Alpha), not 24bit simple RGB. I load the glyph with the following code:
SpeedButton.Glyph.Canvas.Brush.Style:= bsClear;
SpeedButton.Glyph.PixelFormat:= pf32bit;
SpeedButton.NumGlyphs:= 2;
SpeedButton.Glyph.SetSize(ImgList.Width * 2, ImgList.Height);
ImgList.Draw(SpeedButton.Glyph.Canvas, 0, 0, idxCancelRed);
ImgList.Draw(SpeedButton.Glyph.Canvas, Pics.ImgList, 0, idxCancelRedDis);
The transparency it's ok, but the edges of the drawings (where the alpha color is present) are darker as if the alpha value it's not used, and that pixels are blended with some black background... Am I missing something or the TSpeedButton does not support alpha bitmaps (in which case I have to start making my own speed button control) ?
I have to render opencv Mat to using DirectX 11.
D2D1_BITMAP_PROPERTIES1 bitmapProperties = D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
96,
96
);
D2D1_SIZE_U s = D2D1::SizeU(640, 480);
hr = m_d2DeviceContext->CreateBitmap(s, bitmapProp, &m_streamBitmap);
I have to copy opencv matrix to m_streamBitmap.
pImage is a color image with 3 channels.
m_streamBitmap->CopyFromMemory(NULL, reinterpret_cast<BYTE*>(pImage.data),pImage.cols()*3);
This gives distorted image as result.
Can anyone guide me with this.
Thanks in advance ..
Your CopyFromMemory call is copying a three byte color bitmap into a four byte color bitmap. CopyFromMemory does not do format conversion, meaning the format of the source and destination bitmaps must match exactly. In addition, DXGI does not support a three byte color format, so the source bitmap must be modified to four bytes per pixel, even if the fourth is not used. If you cannot change the format of the source bitmap to match the Direct2D bitmap, then you will need to write a conversion function that will expand the bitmap elements to four bytes.
I am trying to creating a blurring function that can take all possible padding options. However for BORDER_CONSTANT you also need to provide the color, i.e. the numbers that you want to pad your image with. In opencv's documentation of blur I don't see an overload of function blur that takes padding and the color value. Does anyone know how to overcome this?
One thing I thought about doing was padding the image first and the blurring some region of interest with no padding at all, although I can't find a way to do that.
The question referred to was asked by me, so basically I would know if this was a duplicated. This question was relating to cv::blur which also handles padding, however does not have an option of adding the border values for BORDER_CONSTANT. I was asking if anyone knows a workaround.
If you follow the source code for blur, you'll find out that, when the borderType is BORDER_CONSTANT, the value for the border will be Scalar(0,0,0,0).
Just a quick reverse-engineering... If you create a white (255) CV_8UC1 matrix and blurwith a 3x3 filter with BORDER_CONSTANT, you'll see that the result is:
In the angles you'll get: (255*4 + 0*5) / 9 = 113, on the border you get (255*6 + 0*3) / 9 = 170. This demonstrate the the padding is of zeros.
Sample code:
#include <opencv2\opencv.hpp>
using namespace cv;
int main()
{
Mat1b img(5,5,uchar(255));
blur(img, img, Size(3, 3), Point(-1, -1), BORDER_CONSTANT);
return 0;
}
Basically what I assumed in the original post is correct. If anyone cares for a solution here goes:
copyMakeBorder(image_in_mat, image_in_mat, r, r, r, r, BORDER_CONSTANT, Scalar(myNumbers));
ROI = Rect(r, r, w, h);
image_in_ROI = image_in_mat(ROI);
blur(image_in_ROI, image_out_mat, Size(blockSize, blockSize), Point(-1, -1));
where r is the radius you want to pad with; w,h are width and height of original image; myNumbers - the color you want your padding to have; image_in_mat - input image.
I want to create a TImage component and fill the image with a background color. However my code is a bit longer than I have expected.
I have to set the width and height of bitmap.
I have to calculate the rectangle of the whole bitmap canvas.
If I remember correctly, in old Delphi versions, I can use FloodFill to fill the whole image with particular color. So I think I have definitively missed something.
Can someone figure out how to fill background color with simpler code?
Image := TImage.Create(nil);
Image.Position.X := 100;
Image.Position.Y := 100;
Image.Width := 500;
Image.Height := 500;
Image.Bitmap.Width := Trunc(Image.Width);
Image.Bitmap.Height := Trunc(Image.Height);
with Image.Bitmap.Canvas do
begin
BeginScene;
try
Fill.Color := TAlphaColors.Black;
FillRect(RectF(0, 0, Image.Bitmap.Width, Image.Bitmap.Height), 0, 0, [], 1.0);
finally
EndScene;
end;
end;
There is no FloodFill in FMX. But you can use Clear(TAlphaColors.Black); in order to fill the entire bitmap with a color.
The reason why you have to set the Bitmap dimensions is becouse the Bitmap size is not necessary the same size as TImage. You can have smaller or larger Bitmap than TImage and then use one of WrapModes to determine how will that image be rendered to TImage:
The WrapMode property should be one of the constants defined in the TImageWrapMode type:
iwOriginal: displays the image with its original dimensions.
iwFit: best fit (keeping image proportions--the ratio between the width and height) for the TImage rectangle. Default.
iwStretch: stretches the image to fill the entire rectangle of this TImage component.
iwTile: tiles the TImage image to cover the entire rectangle of the TImage component.
As for calculating rectangle for the whole bitmap. If you want your bitmap to have the same size as TImage then you can easily read TImage.ClipRect.
ClipRect is generally the rectangle which represents the inner part of the control that you are able to render on. On controls that have borders like TPanel for instance ClipRect dimensions are smaller than the whole control dimensions.
And as it was already stated by Sebastian you can quickly fill the entire Bitmap surface background with a single color by using TBitmap.Clear method.
I just want to know
how to set a particular pixel's colour to red?
suppose x =37 y=54 and i want to change this pixel's colour to red.
I have no clue how to do it.
I have got the values of points around a particular object into an array of pixels using marching square algo.
You cannot change the pixels of an existing CGImage. You have to create a new CGImage with the pixel changed. These are the steps:
Create a CGBitmapContext with CGBitmapContextCreate.
Draw the existing CGImage into it using CGContextDrawImage.
Draw the pixel using CGContextSetFillColorWithColor and CGContextFillRect.
Create a new CGImage using CGBitmapContextCreateImage.
Instead of using CGContextSetFillColorWithColor and CGContextFillRect, you could tweak the bitmap data directly after retrieving a pointer to it with CGBitmapContextGetData. That would be faster if you're going to do it a lot.
Also, if you're going to do it a lot, you will want to create the bitmap context and draw the original image into it just once, and keep the bitmap context around for diddling. But creating the new CGImage from the bitmap context may be a bottleneck.
Your question is quite vague, but here's a general answer:
Pixel colours are usually represented with 3 or 4 bytes:
Red - Green - Blue - ( Alpha )
There should be a function available in the SDK you are using that enables you set these values for a pixel. You would set red to 255 and the others to 0 if you want a pure red colour.
If you are working with CCSprite, just change the color using the color property of the sprite:
mySprite.color=ccc3(123,234,12); //use whatever color values for red, green, blue you want
max values for red, green, blue in ccc3 are 255; when maxed out, the color is the natural color of the sprite; you cannot go brighter, but changing these values will move to other colors or darken the image if all are changed by same amount down.
for pure red, use ccc3(255,0,0)