How to store images in FireMonkey? - image

In VCL I had ImageList to store images. In FireMonkey there is no ImageList control. How do I store images in FireMonkey for later use?

To add images in FireMonkey (XE4)
Project -> Resources and Images
Then to access it:
procedure TForm1.Button1Click(Sender: TObject);
var
InStream: TResourceStream;
begin
InStream := TResourceStream.Create(HInstance, 'MyPng', RT_RCDATA);
try
Image1.Bitmap.LoadFromStream(InStream);
finally
InStream.Free;
end;
end;
Thanks to Peter VonĨa

Because there is no ImageList in Delphi Android you have to:
Add your Images to your Project
Project -> Resources and Images
Delcare the Images in 'Resources and Images' as ResourceType RCDATA
Add this procedure:
->
procedure TForm1.load_image_from_resource(var Im1: Timage; res_name: String);
var InStream: TResourceStream;
begin
InStream := TResourceStream.Create(HInstance, res_name, RT_RCDATA);
try
Im1.Bitmap.LoadFromStream(InStream);
finally
InStream.Free;
end;
end
Then Load your Images with e.g.:
var i : nativeint;
begin
i := 1;
load_image_from_resource(Image1, 'Bitmap_' + inttostr(i));
end;
from everywhere.

Add your images as a resource via Project > Resources and Images.

For people who are looking at this question now, since Delphi XE8 FireMonkey has TImageList component

Put a TPopupMenu on your form and add some Menu Items and assign TBitmap of each TMenuItem. Then you can access bitmaps with this expression:
PopupMenu1.Items[index].Bitmap
or
MenuItem1.Bitmap
MenuItem2.Bitmap
...

Related

Firemonkey assign to bitmap after effect

With FMX, I'm using a standard FMX effect on a TImage and trying to get the bitmap after the effect has been executed - say for example a TColorKeyAlphaEffect. I used the structure pallet to associate the TColorKeyAlphaEffect with the TImage.
When I assign the bitmap of the Timage to another bitmap (or save to file), I only get the original picture prior to the effect - not what is displayed.
Did not find a way to extract the bitmap from the effect itself nor post-effect from the TImage.
Any code for assigning or copying from the TImage to the bmpFinal would do the job and appreciated.
bmpFinal.CopyFromBitmap(TImage.picture.graphic, rect(0,0,iWidth, iHeight), 0, 0 );
TIA
As quick response you can use Image1.MakeScreenshot.SaveToFile('yourfilename.ext');
as long if (2 Timage involved)
Between 2 images it's easy Image2.Bitmap:=Image1.MakeScreenshot;
and you can create effect as runtime i.e
uses FMX.Filter.Effects;
procedure TForm1.Button1Click(Sender: TObject);
var aBitmap : Tbitmap;
begin
if OpenDialog1.Execute then
begin
Image1.Bitmap.LoadFromFile(Opendialog1.FileName);
ABitmap:=Tbitmap.CreateFromFile(Opendialog1.FileName);
try
with TmonochromeEffect.Create(nil) do
try
ProcessEffect(nil,aBitmap, 0);
finally
Free;
end;
image2.Bitmap:=ABitmap;
finally
aBitmap.Free;
end;
end;
end;

TimageList does not contain a member named GetBitmap

I want to load pictures from an ImageList to a TImage (mobile application, fmx). The TImage is part of my customstyle Listbox (LBItem.StylesData['myimage']). The standard approach would be ImageList.GetBitmap(). However the GetBitmap method gives me an error: 'TimageList does not contain a member named GetBitmap'. Any explanation or alternatives? Thanks in advance!
procedure TForm3.Button1Click(Sender: TObject);
var
i : Integer;
LBItem : TListBoxItem;
Bitmap : TBitMap;
begin
ListBox1.BeginUpdate;
ListBox1.Items.Clear;
Bitmap := TBitMap.Create;
try
for i := 0 to 3 do begin
LBItem := TListBoxItem.Create(nil);
LBItem.Parent := ListBox1;
LBItem.StyleLookup := 'mystyle';
LBItem.StylesData['mylabel'] := 'Some text...';
//Bitmap.LoadFromFile('D:\Koala.jpg');
ImageList1.GetBitmap(i, Bitmap);
LBItem.StylesData['myimage']:= Bitmap;
end;
finally
ListBox1.EndUpdate;
end;
end;
Assuming you have an TImage with name Image1, a TImageList with name ImageList1 and at least one entry in the list with image for scale 1.0 called Image1Hover, then you can use the following example to load a "hover picture" in the OnEnter event of Image1:
procedure TForm1.Image1MouseEnter(Sender: TObject);
var
Item: TCustomBitmapItem;
Size: TSize;
begin
ImageList1.BitmapItemByName('Image1Hover', Item, Size);
Image1.Bitmap := Item.MultiResBitmap.Bitmaps[1.0];
end;
This answer is translate from fire-monkey.ru
Use ImageList1.Bitmap(Size, Index);. The size is in physical pixels, i.e. we consider the scale independently (this method knows nothing about the scale of the canvas). This function selects the most appropriate size of the image that is available.
So, your code should look something like this:
LBItem.StylesData['myimage'] := ImageList1.Bitmap(
TSizeF.Create(myImageWidth * Canvas.Scale, myImageHeight * Canvas.Scale),
i);
// Not sure of the correctness of this assignment to 'myimage'
Note 1 All the bitmaps obtained in the 'ImageList1.Bitmap` are stored in the imagelist cache. So don't release them.
Note 2 ListBox has internal mechanism to interact with ImageList. Try to use icon: TImage style item and LBItem.ImageIndex property, without load bitmaps.
In FMX you don't need any additional coding for that, just use TGlyph instead of TImage if you want to display images directly form ImageList.
example :
Glyph1.ImageIndex := i;

Delphi: Can't Draw On Panel's Canvas

I'm trying to draw an image on a TPanel's Canvas in a procedure of this Panel. When I do this in Paint Method of the Panel it works just fine, but when I try to draw on the Canvas in another procedure or in the constructor nothing happens.
This is how I draw on the Panel's Canvas in the Paint Procedure:
procedure TFeld.Paint;
var bmp : TBitmap;
begin
inherited;
bmp := TBitmap.Create;
try
bmp.LoadFromFile('textures\ground.bmp');
self.Canvas.Draw(0,0,bmp);
finally
bmp.Free;
end;
end;
And this is how I try to draw on it in another procedure:
procedure TFeld.setUnsichtbar;
var bmp : TBitmap;
begin
bmp := TBitmap.Create;
try
bmp.LoadFromFile('textures\invisible.bmp');
self.Canvas.Draw(0,0,bmp);
finally
bmp.Free;
end;
end;
But the Panel's Canvas is still the image I applied in the Paint procedure.
I already tried to move the drawing from the Paint procedure to the Constructor which didn't work.
The path is also correct, switched the paths and now the Panels have the 'invisible.bmp' image.
Whole Class/Unit: http://pastebin.com/YhhDr1F9
Any idea why this doesn't work?
Looking at your whole class I asume you desire to controll which image is being shown at which time based on certain condition. Right?
If that is the case first thing that you need is for your class to have a field for storing the image data. In your example above you are only using bmp files so TBitmap would suffice. But if you are using other picture types you might want to use TPicture field instead as this one alows loading of all supported picture images as TImage that you also tried to use component can.
Then you change your component's Paint method to use the above mentioned field for getting picture data instead of creating local picture data variable every time as you do it now.
In fact what you are doing now is terrible as you are forcing your application to read the image data from file into memory every time your component is rendered. This could cause terrible performance.
And finally when you want to change the picture that is shown on your component just load different picture into your picture field.
So with above changes your class should look something like this:
type
TFeld=class(TPanel)
protected
procedure Paint;override;
procedure BitmapChange(Sender: TObject);
private
zSichtbar : Boolean;
zPosHor,zPosVer : Integer; // Position im Array
zEinheit : TEinheit;
Bitmap: TBitmap; //Field for storing picture data
public
// hImage : TImage;
constructor Create(pX,pPosHor,pY,pPosVer,pHoehe,pBreite:integer;pImgPath:String;pForm:Tform); virtual;
destructor Destroy;
procedure ChangeImage(pImgPath: String);
end;
...
implementation
constructor TFeld.Create(pX,pPosHor,pY,pPosVer,pHoehe,pBreite:integer;pImgPath:String;pForm:Tform);
begin
inherited create(pForm);
...
//Creater internal component for storing image data
Bitmap := TBitmap.Create;
//Assign proper method to Bitmaps OnChange event
Bitmap.OnChange := BitmapChange;
//Load initial image data
Bitmap.LoadFromFile(pImgPath);
....
end;
destructor Destroy;
begin
//We need to destroy the internal component for storing image data before
//we destory our own component in order to avoid memory leaks
Bitmap.Free;
end;
procedure TFeld.Paint;
begin
inherited;
//Use local image field to tell the Paint method of what to render
self.Canvas.Draw(0,0,Bitmap);
end;
procedure TFeld.BitmapChange(Sender: TObject);
begin
//Force redrawing of the component on bitmap change
self.Invalidate;
end;
procedure TFeld.ChangeImage(pImgPath: String);
begin
//Load different image into image field
Bitmap.LoadFromFile(pImgPath);
end;
EDIT: Adding necessary code to force component redrawing after bitmap has been changed.

How to get dimensions of an Image which is in Clipboard?

I want to know width and height of Image while it is in Clipboard, because if dimensions are too small then message like "Image is too small" should appear.
How to get width and height?
Unless you are prepared to manually parse the various image formats that you want to support, you can have the VCL simply load the image for you (just make sure suitable TGraphic classes have been registered, such as TGIFImage, TJPEGImage, TPNGImage, etc), and then you can ask the image for its dimensions, eg:
uses
Graphics, Clipbrd, Jpeg, PngImage, ...;
procedure TForm1.BitBtn1Click(Sender: TObject);
var
p: TPicture;
begin
p := TPicture.Create;
try
try
p.Assign(Clipboard);
// use p.Graphic, p.Graphic.Width, p.Graphic.Height as needed...
except
// unable to access Clipboard, or Clipboard
// does not contain a supported image type
end;
finally
p.Free;
end;
end;
If this is about bitmap I think you may try this.
procedure TForm1.BitBtn1Click(Sender: TObject);
var b:TBitmap;
begin
if Clipboard.HasFormat(CF_BITMAP) then begin
b:=TBitmap.Create;
try
b.Assign(Clipboard);
ShowMessage(IntToStr(b.Width)+','+IntToStr(b.Height));
finally
b.Free;
end;
end;
end;
you can instead of showmessage put If-statement and do what ever you want.

How do I add dock-icon badge and popupmenu support for lazarus apps in OSX?

I've tried googling around abit but I cannot find any help in using the badge feature of dock-icons on OSX aswell as getting access to the dock icon menu? I guess I could change the dock icon during run to indicate something is up but it isn't as sleek ;)
This feature isn't implemented in LCL, so if you want to use it, you will have to use the relevant Cocoa framework directly. You can use ObjPas for that. Of course if you are up for writing an LCL implementation, that would be a better long term solution, as it could be made to work on Windows/Gnome later.
Ludicrous late ... but I bumped into this post, and found this post in the Lazarus Forum, which shows code how you can change the application icon in the dock while the application is running.
Hope it will be of use for someone looking for an answer to the same question, even though it's years after the post of the original question. (apologies if this is not appropriate)
uses
... MacOSAll ...
procedure TFrm_Main.FormCreate(Sender: TObject);
begin
...
FResPath := TrimFilename(ExtractFilePath(Application.ExeName) + PathDelim + 'Resource');
...
end;
procedure TFrm_Main.SomeEventWhenOverlay(SomeVar: Integer);
var
temp_ImagePath: String;
temp_CGDataProvider: CGDataProviderRef;
temp_Float32Ptr: Float32Ptr;
temp_CGImage: CGImageRef;
temp_CGContext: CGContextRef;
begin
temp_ImagePath := TrimFilename(FResPath + PathDelim + 'Image' + PathDelim + 'overlay_image.png'); // image must be same size as icon, if not, will be deformed
if (FileExists(temp_ImagePath)) then
begin
temp_CGDataProvider := CGDataProviderCreateWithFilename(PChar(temp_ImagePath));
temp_Float32Ptr := nil;
temp_CGImage := CGImageCreateWithPNGDataProvider(temp_CGDataProvider, temp_Float32Ptr, 1, kCGRenderingIntentDefault);
CGDataProviderRelease(temp_CGDataProvider);
// Draw image
temp_CGContext := BeginCGContextForApplicationDockTile;
//SetApplicationDockTileImage(temp_CGImage);
OverlayApplicationDockTileImage(temp_CGImage);
CGImageRelease(temp_CGImage);
EndCGContextForApplicationDockTile(temp_CGContext);
end;
end;
procedure TFrm_Main.SomeOtherEventWhenRestore();
begin
//This will not work if you use SetApplicationDockTileImage
RestoreApplicationDockTileImage;
end;

Resources