I would like to fill a TPath.Data from a TBitmap.
Delphi FMX provides a FillPath on a Bitmap Canvas:-
http://docwiki.embarcadero.com/CodeExamples/Rio/en/FMXTCanvasFillFunctions_(Delphi)
Image1.Bitmap.Canvas.FillPath(path, 200);
But I'm looking fill the Path Data from the Bitmap.
Any code examples?
tia
You mean how do you fill an enclosed TPath with a bitmap instead of a solid color. You change the Fill property to a Bitmap:
path1.Fill.Bitmap:=mybitmap;
path1.Fill.Kind:=TBrushKind.Bitmap;
Related
In Delphi 10.4, I have loaded a PNG image (32BPP with Alpha Channel Transparency) at DESIGN-TIME in the Picture property of a TImage. Here is how it looks at run-time:
Here is a copy of the TImage component (which can be pasted at design-time in any Delphi VCL Application project):
object Image1: TImage
Left = 46
Top = 200
Width = 32
Height = 32
AutoSize = True
Center = True
Picture.Data = {
0954506E67496D61676589504E470D0A1A0A0000000D49484452000000200000
00200806000000737A7AF40000000473424954080808087C086488000006F749
44415478DAB557694C545714BE33C3BE8A0CEBB096224EA94241B16AACA68520
6DA1D1D485B00A1421DA0A36A9B64D9AFE68AA69A340451B4A41405903D6A5D4
0AB4285B59442236884C054640C080EC8475A6DF19670803B40C466F72F3DEBB
E7DC73BE77EED92EE78083195BB74A87310E872D1E52261E9D6409CD8FD9CB1A
9CD3EEF66C9B99E11800682FD62F9DBA3F34AE155CD9F212016C788500CCD2FB
12069002002FB8F2C1336658C9CCCC8C595B5B333E9FCF74747494D827262658
5F5F1FEBECEC64DDDDDD4C2291BC180011756DCCDDDD9DB9B8B8700C0D0DB781
F23EE69B988E98AB3149D300A608F32FCCC2D1D1D18AC6C646697D7D3D1B1F1F
7F7E001D1C4DDE9FF61BB8BABABA2158390E2B38AA625AA9544AE77672727232
A3ACAC4C72E7CE9DE703D06624E0D55B39D740F146B960311E7C7CEBE2FD1814
24C0D4126D6DED20ACA5606D06F4C778B791F3D7E211D4D2D2222A2C2C645353
532B03D0C2B7E5DDB35C2B81A04758F91CCF6A0827538FE15D909E9E3E3A3838
C8A2A3A3D53435351F81660E3C6E780AC1F32D9EB6E01BC6DC03BF28CECDCD55
02B12C0091B135EFAEA5300B020EE25C47F4F5F58F40681CBE33E16C41999999
32566F6F6FE6EAEA7A06B443A07D353636F60D9C541FDF4998FBB13685E9FBF0
E1C3E24B972E91655403D0A9BB9A57C45FC36EDDBAC56C6C6CC811AF41E07B10
10505C5C9CAD385B3B3B3BB66FDF3E3FD02E83562A168BDFA9ADAD65BEBEBE4C
4B4BEB14D663C91260DD585A5A2A229ACA51A008C3D0D0500AC32710C687996D
9293933B07060664341E8FC76263634DF0ECC1E7087CC3283E3E5E6A6E6E4EC0
084496DC12B538822D29292992E1E1E19501387AF4A8B58686861842FA6062D3
C4C44425F6C0C040261008C450640D808EA03FA410B4B5B5657BF7EED5E772B9
F7C839B13F0CE199565252B23C00B1BA1E2F47DD8C6133B3B7B77F1B024A20A0
1C7FB89D12CEFC41494A4F4FAF083C9EE0F1E9E8E8B8A170382B2B2B0627F507
2D934214FB8500285D16C03FE48482D7964F692B1CB0D0F6828282721500D800
80F085038015BEABA9A939BE2C80475AAB78D70C6CC98918D2F0699830069B63
E17C090B938A9A9A1A333636FE043CF1E0F901611B035F99A3D3319A98987882
5E047A596B6BEB0E959D70FDFAF5CCC7C7E7276C8EC0E688FCFCFC54C4B412BB
A9A929454A1814FD0C9E94F2F2F28FAAAAAAE6E854CC6262622CE00B5DA077F7
F4F408540680F8673B77EE3C0F2121D81C92969676A1B7B757891DF5821D3E7C
9852723A78322A2A2A422B2B2B957800500DA1494969020074560A200DC283B1
3918002EFE078040F06480E70200842C04101212C2B3B0B098067D1200B4570A
2019C2C3B1393C2F2FEF7C5B5B9B123BF508E1E1E107E445291500221602A023
803FD111407F8FE5F2D550439F97CB336106060674C671107E849C1085256161
9D4792A266E563F02490133E7DFA344691296950B644CA563861797B7BFB7625
00280F7F4F334EA81A93A671197B5D660154C326544395E34BC50100DFDFBE7D
FBD81C002C34F4E819BF7BD7C2698F437F4781C340E7AF5C297BA3896FC7BB6F
E9F45212D1D5AB57CB39A79E35A565542A2BAC5D867B579937A949669B843DA2
68C7818E7CB196D15BBFE959CBCC871856A4E2B2E9E9E91D30B192503A263426
73A9B8BFBFFFC6CCCC8C8C6664644447A448C522EC5F2B4BC5B1424BE66AA4CB
2A9E0CB1660B27B679F3E60388E314EEECCCEF82C1EE0FC71EDC1BFFACAC5126
04C54800211D10D03F32326272EEDC39250001010194F3A929B1C21FBE7AF6EC
D9564A44541151A8F4F1138DF206251CFDE2F9EBD7AF2B3B1E75B99191915C24
8A2A307A80311B9D6E007531F0581616164656E801CD140A6C9392923A868686
647B29CBC1C3F9EAEAEA149BC3C892ABE3E2E2A4F4E7FEFEFE0C8DCC5C399E9D
9DDD929A9A2A210B2EF27C373737E6E9E9B906CCB59806D81007109F5EB97285
098542CA8897B1EE47B9A0A8A8E8624343836C1FB5EA50F40180FC02DA1F6848
BC6EDEBCC976EFDE4DCAE71A12CC8DD5D5D52234AAB27D8B0050BADCB56B1773
7474F4C62729D3244BE08FA3807804B17E086B67B0968772BB3F2B2B4BB6CFCB
CB8BC0FF08DA41D0BE84654EA03493D9955A3294F0E29C9C9CB93BC352F731AA
DBD44030642C6F6CCEC3D49777C35F605266A1223089352B34A583D494464545
6920C15083608CE982B98E2D684AF103C5D9D9D96C7E815A12000D4A2A7E7E7E
CCC1C1C1099F19F3DAF276522207F5359CF1243C5D82B38EC45A22FD29E8DDA4
58CE5F8BBF0DEAEAEA12D131CE57FEBF0014C7E1E1E1C1B66EDDCA8573ADF462
42ADFB0980CBA8ABAB93504A86F32DD6A18A308AEF4D9B36316767670E2CB30D
20E65FCD8C481F9B773583F24228AE686E6E96C2E1D8C27CB162008A410D07B5
DF4B5D4EA9CF479F27BB9CC23919F2FCA25BD052E35F02ED3A5D68222C670000
000049454E44AE426082}
Proportional = True
end
Now, at run-time, I try to save this image as a BITMAP image file (.bmp):
procedure TForm1.btnSaveTImageToBitmapClick(Sender: TObject);
begin
Image1.Picture.Bitmap.SaveToFile('Y:\Downloads\test.bmp');
end;
But when I execute this code at run-time, something very strange happens: The TImage component VANISHES (it becomes apparently INVISIBLE!) and the created .bmp file has a ZERO size (0 bytes).
However, when instead of the above code I execute this code:
procedure TForm1.btnSaveTImageToBitmapClick(Sender: TObject);
begin
Image1.Picture.SaveToFile('Y:\Downloads\test.bmp');
end;
...then the resulting file is a .PNG file with a WRONG .BMP file extension!
So how can I save this image as a valid BITMAP (.BMP) file?
EDIT: The answer by #Andreas Rejbrand and #Remy Lebeau has provided extensive explanations and ways to solve the problem.
You must create a TBitmap and assign the Picture.Graphic to it:
procedure TForm3.btnSaveClick(Sender: TObject);
var
bm: TBitmap;
begin
bm := TBitmap.Create;
try
bm.Assign(Image1.Picture.Graphic);
bm.SaveToFile('C:\Users\Andreas Rejbrand\Desktop\bitmap.bmp');
finally
bm.Free;
end;
end;
Your approach:
Image1.Picture.Bitmap.SaveToFile('Y:\Downloads\test.bmp');
doesn't work because the Picture doesn't contain a bitmap. From the documentation of the TPicture.Bitmap property:
Use Bitmap to reference the picture object when it contains a bitmap. If Bitmap is referenced when the picture contains a Metafile or Icon graphic, the graphic won't be converted (Types of Graphic Objects). Instead, the original contents of the picture are discarded and Bitmap returns a new, blank bitmap.
This approach:
Image1.Picture.SaveToFile('Y:\Downloads\test.bmp');
does exactly what it is supposed to do. It saves the Picture.Graphic as-is, which happens to be a PNG image in your case, to the file you specified. You chose a strange extension for a PNG image, but that's not something the VCL tries to correct.
Handling PNG transparency
If the PNG file has an alpha channel, bm.Assign will very faithfully create a bitmap image with an alpha channel. That's great, in one sense, because then you don't lose any information: the BMP you get contains all graphic data from the PNG, including the entire alpha channel. So you can, in principle, render this BMP onto any background and will look as nice as the PNG would look.
But in another way, it's not that great, after all. Because almost no image viewers or editors support BMPs with alpha channels. These applications will probably ignore the alpha channel, effectively making every pixel fully opaque. That will look horrible.
So if you want to create a normal BMP, without alpha channel, you need to "render" the PNG, using its alpha channel, onto a background of your choice, and then save the non-transparent result. The BMP you get will not contain the alpha channel of the original PNG, so you lose information. The BMP will not be transparent. For instance, if you draw it onto a white background, you will always have this white rectangle behind your icon/subject, even if you place it on a red area of the screen.
procedure TForm3.Image1Click(Sender: TObject);
var
bm: TBitmap;
begin
bm := TBitmap.Create;
try
bm.SetSize(Image1.Picture.Width, Image1.Picture.Height);
bm.Canvas.Brush.Color := clSkyBlue; {*}
bm.Canvas.FillRect(Rect(0, 0, bm.Width, bm.Height)); {*}
bm.Canvas.Draw(0, 0, Image1.Picture.Graphic);
bm.SaveToFile('C:\Users\Andreas Rejbrand\Desktop\bitmap2_1.bmp');
finally
bm.Free;
end;
end;
The lines with asterisks (*) can be omitted if you are happy with the default background color, which is white.
I am trying to make a row color have 74% transparency.
My code:
TDBGrid(sender).canvas.brush.color := RGB(0,176,240);
But I can't figure out where to add transparency to brush?
gdi+ can support alpha channel for color, you can use gdi+ functions in any canvas
I'm trying to port some code from Delphi to Firemonkey (XE6).
I've run into a problem with a function which draws to a TCanvas supplied by the caller. The Canvas could be from a TPaintBox, a TPanel, a TForm or a TBitmap. The function reads the TCanvas.ClipRect property to avoid doing cpu-intensive drawing outside of it. (The cliprect represents invalidated areas of the TForm, TPaintBox etc.)
Unfortunately the TCanvas ClipRect property no longer seems to exist. Does anyone know how I can access the TCanvas.ClipRect in Firemonkey? I did notice that TPaintBox and TPanel now have a ClipRect property, so I could maybe use those, but the TForm and TBitmap don't.
Please note, I'm not trying to create or change a cliprect in a Canvas, I'm trying to read it.
You use the Scene property of TControl. It has a list of clip rects to be painted. Use GetUpdateRectsCount and GetUpdateRect to read them.
For example this code read out the rects that needs repainting:
lStr := '';
for i := 0 to MyControl.Scene.GetUpdateRectsCount-1 do
with MyControl.Scene.GetUpdateRect(i) do
lStr := lStr + Format('(%g,%g,%g,%g)', [Left,Top,Right,Bottom]);
The DoBeginScene has a parameter for the cliprects. But there doesn't seem to be a way to actually retrieve that value. In addition to that there might be additional clipping on the canvas.
In order to get the clip rects, you need the dc or cgcontext of the canvas. You could get it using RTTI. Here's an example for OSX:
function TCanvasCHelper.GetCGContext: CGContextRef;
var
Context: TRttiContext;
Field: TRttiField;
begin
// needs about 1ms
Field := Context.GetType(TCanvasQuartz).GetField('FContext'); // get private field using RTTI
Assert(Field <> nil);
Result := PPointer(Field.GetValue(Self).GetReferenceToRawData)^;
end;
Unfortunately using RTTI for this might not be as fast as required. I ended up with having to create a copy of the FMX.Canvas.* classes that expose the CGContext or DC. You'll need this anyway if you want to do more advanced things with the canvas that FMX does not implement.
When you have the CGContext or DC, you can use the functions of the OS like CGContextGetClipBoundingBox or GetClipBox to retrieve the cliprects if the canvas supports them.
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 would like to draw bitmap image over the text that I type in editfield.
How can I do that?
You will need to subclass EditField and then override the paint method. In the override, call super.paint before you do anything so that the component can draw the text, and then you can use the Graphics object provided by paint to draw a Bitmap over the contents of the EditField (Graphics.drawBitmap).