I need create a crop effect to my app. I have a TRectangle over a TImage, and I need when the user press the save button, copy just the area that the TRectangle uses. There is some way that I can cut just a specific area from the Image1.Bitmap? I printed a image to better ilustrate what I need:
Asked
Active
Viewed 3,150 times
2
-
You better use a canvas which you can control the scale. Don't just use any random image control. If it were me, I'd write a custom control for this. But it wouldn't be a very trivial one. – Jerry Dodge Oct 23 '17 at 01:25
-
What is the `WrapMode` that you use? What if it's `Tile` and your selector covers more than one tile of the displayed image? – Victoria Oct 23 '17 at 02:04
-
1The crop procedure would be like this: 1) calculate the scaling of your image and convert the rectangles bounds to the image scale. 2) create a TBitmap and use CopyFromBitmap with the calculated rectangle. This copies a section from your TImage bitmap to the new bitmap. 3) assign the bitmap to your TImage bitmap (if that's what you want). – Hans Oct 23 '17 at 06:34
-
Can you please give me a code example on how to do the step number 2? – Diego Bittencourt Oct 23 '17 at 10:32
-
@Victoria I'm using Fit at the moment, and I don't think I'll need change this. Maybe to stretch... Have you any idea on how I can fix this task? I'm just lost and need some direction. – Diego Bittencourt Oct 23 '17 at 19:10
-
@Jerry Dodge Can you be more specific please, I really need fix this. Thanks man! – Diego Bittencourt Oct 23 '17 at 19:11
-
[This question](https://stackoverflow.com/questions/31159795/how-to-crop-an-fmx-tbitmap) might be useful. – asd-tm Oct 23 '17 at 19:20
-
1The concept is very trivial: Draw your image on a controlled canvas (one which you have 100% control over), and do simple math to determine scale. Surely there are plenty of resources how to extract a portion of an image in Firemonkey. I used them to write my own vector signature control. Only much simpler for you. But please don't expect us to write it for you. – Jerry Dodge Oct 28 '17 at 01:44
2 Answers
5
Here is a sample that works for me:
procedure TForm1.Button1Click(Sender: TObject);
var
Bmp: TBitmap;
xScale, yScale: extended;
iRect: TRect;
begin
Bmp := TBitmap.Create;
xScale := Image1.Bitmap.Width / Image1.Width;
yScale := Image1.Bitmap.Height / Image1.Height;
try
Bmp.Width := round(Rectangle1.Width * xScale);
Bmp.Height := round(Rectangle1.Height * yScale);
iRect.Left := round(Rectangle1.Position.X * xScale);
iRect.Top := round(Rectangle1.Position.Y * yScale);
iRect.Width := round(Rectangle1.Width * xScale);
iRect.Height := round(Rectangle1.Height * yScale);
Bmp.CopyFromBitmap(Image1.Bitmap, iRect, 0, 0);
Image2.Bitmap := Bmp
finally
Bmp.Free;
end;
end;
I assume here that Rectangle1
has Image1
as its Parent
:
Otherwise you will need to consider the offset of Position.X
and Position.Y
properties.

asd-tm
- 3,381
- 2
- 24
- 41
-
2
-
I tried your solution on the mobile, but in some smartphones with different resolutions and scales ... the image copied from the selection is not correct. why? – acarlomagno Jun 28 '21 at 07:28
-
This method has a poor accurracy, the scale is a Single, the X, Y, Heigh and Width of the rect is a Single, but TRect ask for a Integer, so many "rounds" to convert on code change de dimension of the area cropped. I´m trying to use TCanvas methods to draw the canvas of the TImage to TCanvas of the retangle and then use makesnapshot to get TBitmap from rectangle. but still trying. – Joao Ishiwatari Dec 30 '21 at 14:56
-
@Joao xScale and yScale are extended, not single. Frankly speaking I doubt the mashine epsilon 5.96e-08 - 1.19e-07 of a single really matters in the current case. The 1 px mistake might occur when having resulutions about 10000000 - 100000000 pixels. Otherwise I wonder if you could specify the exact practical task for the higher precision processing. – asd-tm Dec 30 '21 at 17:38
-
@asd-tm is not about type precision, is about convertion. A extended rounded to integer causes significant changes on result. I'm using your code to grab a rect from a timage and the result cames different of the cropped area, the rect area changes more than scale. – Joao Ishiwatari Jan 01 '22 at 12:33
0
Another way to do:
var
Tmp: TBitmap;
Bmp: TBitmap;
iRect: TRect;
begin
Tmp := TBitmap.Create;
Tmp := Image1.MakeScreenshot; //ignore the scale, so will F*ck the resolution, but resolve the scale issues
Bmp := TBitmap.Create;
try
Bmp.Width := round(Rectangle1.Width);
Bmp.Height := round(Rectangle1.Height);
iRect.Left := round(Rectangle1.Position.X);
iRect.Top := round(Rectangle1.Position.Y);
iRect.Width := round(Rectangle1.Width);
iRect.Height := round(Rectangle1.Height);
Bmp.CopyFromBitmap(tmp, iRect, 0, 0);
Image2.Bitmap := Bmp
finally
Tmp.Free;
Bmp.Free;
end;

Joao Ishiwatari
- 85
- 6
-
Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Dec 30 '21 at 18:22