Firemonkey assign to bitmap after effect - firemonkey

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;

Related

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.

Picture Database, TDBImages, TImageList, Delphi

I am writing a programme that shows a picture(map). when you click on a part of the picture it must Zoom in. There are 26 pictures in total(Including main picture). I Want to load those pictures into Delphi and replace Image1(Whole_map.jpg) with Amusement_park.jpg.
I want to use the good quality jpg not bitmaps :(
*Is it possible to load those 26 images into TImageList and still use the images with its quality
or
*Can i save the images in some sort of Database and load it into Delphi
Loading images and converting to bitmap
doesn't help because i don't want to use bitmaps.
I also don't want to use any 3rd party components because this program must run on default Delphi 2010.
As mentioned in my coment you can create an array of TJPEGImage objects to store the images.
You do this like so:
//Global array for storing images
var Images: Array [1..26] of TJPEGImage;
implemenetation
...
procedure TForm1.FormCreate(Sender: TObject);
var I: Integer;
begin
for I := 1 to 26 do
begin
//Since TJPEGIMage is a class we first need to create each one as array only
//stores pointer to TJPEGImage object and not the object itself
Images[I] := TJPEGImage.Create;
//Then we load Image data from file into each TJPEGImage object
//If file names are not numerically ordered you would probably load images
//later and not inside this loop. This depends on your design
Images[I].LoadFromFile('D:\Image'+IntToStr(I)+'.jpg');
end;
end;
As you see in source coments the array only stores pointers to TJPEGImage objects and not the TJPEGImage objects themself. So don't forget to create them before trying to load any image data to them. Failing to do so will result in Access Violation.
Also becouse you have created these TJPEGImage objects by yourself you also need to free them by yourself to avoid posible memory leaks
procedure TForm1.FormDestroy(Sender: TObject);
var I: Integer;
begin
for I := 1 to 26 do
begin
Images[I].Free;
end;
end;
In order to show these stored images in your TImage component use this
//N is array index number telling us which array item stores the desired image
Image1.Picture.Assign(Images[N]);
Second approach that you can use
Now since TJPEGImage are classed objects you could also use TObjectList to store pointers to them.
In such case creation code would look like this
procedure TForm1.FormCreate(Sender: TObject);
var I: Integer;
Image: TJPEGImage;
for I := 1 to NumberOfImages do
begin
//Create TObject list with AOwnsObjects set to True means that destroying
//the object list will also destroy all of the objects it contains
//NOTE: On ARC compiler destroying TObjectList will only remove the reference
//to the objects and they will be destroyed only if thir reference count
//drops to 0
Images := TObjectList.Create(True);
//Create a new TJPEGImage object
Image := TJPEGImage.Create;
//Load image data into it from file
Image.LoadFromFile('Image'+IntToStr(I)+'.jpg');
//Add image object to our TObject list to store reference to it for further use
Images.Add(Image);
end;
end;
You would now show these images like so
//Note becouse first item in TObject list has index of 0 you need to substract 1
//from your ImageNumber
Image1.Picture.Assign(TJPEGImage(Images[ImageNumber-1]));
Since we set TObjectList to own our TJPEGImage objects we can quickly destroy all of them like so
//NOTE: On ARC compiler destroying TObjectList will only remove the reference
//to the objects and they will be destroyed only if thir reference count
//drops to 0
Images.Free;

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 to store images in FireMonkey?

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
...

Resources