### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: I need to rotate a picture in a TImage 90°  (Read 1923 times)

#### marcov

• Global Moderator
• Hero Member
• Posts: 8734
• FPC developer.
##### Re: I need to rotate a picture in a TImage 90°
« Reply #15 on: May 19, 2020, 12:04:00 pm »
On Windows, the plgblt api  is still the fasted way to rotate images at any angle.

A n*90 degree is fundamentally different (and way faster) than a "any angle" operation.

Note that flipping (mirror in y direction) and 180 rotation are different things.

Flipping is usually very cheap (change bottom up flag to top down, e.g. image.imageheight:=-image.imageheight;)

Mirror is more complicated to do quickly. I never needed it, so I never worked on it.

Note that I also have a pascal version of the looptiling rotate algorithm that also works for other bpp and allows to set different (8x8,16x16 etc) tilesizes.  Looptiling used to be about 4 times faster on Core 2 machines compared to naive coordinate inversion. I haven't retested with recent machines. And of course, it mostly matters for images > cachesize.

« Last Edit: May 19, 2020, 12:13:12 pm by marcov »

#### RedOctober

• Sr. Member
• Posts: 331
##### Re: I need to rotate a picture in a TImage 90°
« Reply #16 on: May 19, 2020, 05:57:08 pm »
Thanks to all contributors.  You all helped in solving this problem.  Here is the solution I am using now.  It's fast "enough", and the code is simple.

Code: Pascal  [Select][+][-]
1. ...
2. , BGRABitmap, BGRABitmapTypes, BGRATransform
3. ...
4.
5.
6. procedure GrabItRotate(const src_fnm: String; const dgr: Integer);
7. var bmp: TBGRABitmap;
8. begin
9.   bmp := TBGRABitmap.Create(src_fnm);
10.
11.   case dgr of
12.      90:BGRAReplace(bmp, bmp.RotateCW);
13.     180:begin
14.           bmp.HorizontalFlip;
15.           bmp.VerticalFlip;
16.         end;
17.     270:BGRAReplace(bmp, bmp.RotateCCW);
18.   end;
19.
20.   bmp.SaveToFile(src_fnm);
21. end;
22.
23.

• Hero Member
• Posts: 10492
##### Re: I need to rotate a picture in a TImage 90°
« Reply #17 on: May 19, 2020, 06:04:00 pm »
A n*90 degree is fundamentally different (and way faster) than a "any angle" operation.
Did you try my code...very old but near real time.. and I can port it back if required. http://members.chello.nl/t.koning8/kolsmoothrotate.zip
The plgblt api call is very fast on windows, much faster than presented here.
« Last Edit: May 19, 2020, 06:05:40 pm by Thaddy »
When you ask a question that is actually answered in the documentation, you are either lazy or a moron.

#### RedOctober

• Sr. Member
• Posts: 331
##### Re: I need to rotate a picture in a TImage 90°
« Reply #18 on: May 19, 2020, 06:05:24 pm »
Something went wrong with my other final reply post, so I am re-posting the same thing again.  Can the moderators remove the duplicate?  I cannot find a "delete" button.

Code: Pascal  [Select][+][-]
1. ...
2. uses BGRABitmap, BGRABitmapTypes, BGRATransform
3. ...
4. procedure GrabItRotate(const src_fnm: String; const dgr: Integer);
5. var bmp: TBGRABitmap;
6. begin
7.   bmp := TBGRABitmap.Create(src_fnm);
8.
9.   case dgr of
10.      90:BGRAReplace(bmp, bmp.RotateCW);
11.     180:begin
12.           bmp.HorizontalFlip;
13.           bmp.VerticalFlip;
14.         end;
15.     270:BGRAReplace(bmp, bmp.RotateCCW);
16.   end;
17.
18.   bmp.SaveToFile(src_fnm);
19. end;
20.

#### RedOctober

• Sr. Member
• Posts: 331
##### Re: I need to rotate a picture in a TImage 90°
« Reply #19 on: May 19, 2020, 06:06:41 pm »
I tried posting my final solution twice, and it failed twice.  So, thanks to all the contributors, my problem is solved.  I cannot post the solution.. something wrong with the site I assume.

#### RedOctober

• Sr. Member
• Posts: 331
##### Re: I need to rotate a picture in a TImage 90°
« Reply #20 on: May 19, 2020, 06:08:30 pm »
Thank you Thaddi, I'm out of time and I have a "good enough" solution, and have to get moving with other parts of the project.

#### marcov

• Global Moderator
• Hero Member
• Posts: 8734
• FPC developer.
##### Re: I need to rotate a picture in a TImage 90°
« Reply #21 on: May 19, 2020, 06:18:26 pm »
A n*90 degree is fundamentally different (and way faster) than a "any angle" operation.
Did you try my code...very old but near real time.. and I can port it back if required. http://members.chello.nl/t.koning8/kolsmoothrotate.zip
The plgblt api call is very fast on windows, much faster than presented here.

No. Do you have a gui less example? Or normal lazarus ?

#### DJMaster

• New Member
• Posts: 41
##### Re: I need to rotate a picture in a TImage 90°
« Reply #22 on: July 11, 2020, 09:32:36 am »
The following routines perform quick Bitmap clockwise rotations using scanlines.

It would be nice to include this code somewhere into Lazarus as standard goodies.

Code: Pascal  [Select][+][-]
1. uses
2.   lcltype;
3.
4. procedure Rotate90(Bitmap: TBitmap);
5. type
6.   TRGBArray = array[0..0] of TRGBTriple;
7.   pRGBArray = ^TRGBArray;
8. var
9.   oldRows, oldColumns: integer;
10.   rowIn, rowOut: pRGBArray;
11.   tmpBitmap: TBitmap;
12. begin
13.   tmpBitmap := TBitmap.Create;
14.
15.   tmpBitmap.Width := Bitmap.Height;
16.   tmpBitmap.Height := Bitmap.Width;
17.   tmpBitmap.PixelFormat := Bitmap.PixelFormat;
18.
19.   for oldColumns := 0 to Bitmap.Width - 1 do
20.   begin
21.     rowOut := tmpBitmap.ScanLine[oldColumns];
22.
23.     for oldRows := 0 to Bitmap.Height - 1 do
24.     begin
25.       rowIn := Bitmap.ScanLine[oldRows];
26.       rowOut[Bitmap.Height - oldRows - 1] := rowIn[oldColumns];
27.     end;
28.   end;
29.
30.   Bitmap.assign(tmpBitmap);
31.   tmpBitmap.free;
32. end;
33.
34. procedure Rotate180(Bitmap: TBitmap);
35. type
36.   TRGBArray = array[0..0] of TRGBTriple;
37.   pRGBArray = ^TRGBArray;
38. var
39.   countRows, countColumns: integer;
40.   rowIn,rowOut: pRGBArray;
41.   tmpBitmap: TBitmap;
42. begin
43.   tmpBitmap := TBitmap.Create;
44.
45.   tmpBitmap.Width := Bitmap.Width;
46.   tmpBitmap.Height := Bitmap.Height;
47.   tmpBitmap.PixelFormat := Bitmap.PixelFormat;
48.
49.   for countRows := 0 to Bitmap.Height - 1 do
50.   begin
51.     rowIn := Bitmap.ScanLine[countRows];
52.     rowOut := tmpBitmap.ScanLine[Bitmap.Height - countRows - 1];
53.
54.     for countColumns := 0 to Bitmap.Width - 1 do
55.       rowOut[Bitmap.Width - countColumns - 1] := rowIn[countColumns];
56.   end;
57.
58.   Bitmap.assign(tmpBitmap);
59.   tmpBitmap.free;
60. end;
61.
62. procedure Rotate270(Bitmap: TBitmap);
63. type
64.   TRGBArray = array[0..0] of TRGBTriple;
65.   pRGBArray = ^TRGBArray;
66. var
67.   oldRows, oldColumns: integer;
68.   rowIn, rowOut: pRGBArray;
69.   tmpBitmap: TBitmap;
70. begin
71.   tmpBitmap := TBitmap.Create;
72.
73.   tmpBitmap.Width := Bitmap.Height;
74.   tmpBitmap.Height := Bitmap.Width;
75.   tmpBitmap.PixelFormat := Bitmap.PixelFormat;
76.
77.   for oldColumns := 0 to Bitmap.Width - 1 do
78.   begin
79.     rowOut := tmpBitmap.ScanLine[oldColumns];
80.
81.     for oldRows := 0 to Bitmap.Height - 1 do
82.     begin
83.       rowIn := Bitmap.ScanLine[oldRows];
84.       rowOut[oldRows] := rowIn[Bitmap.Width - oldColumns - 1];
85.     end;
86.   end;
87.
88.   Bitmap.assign(tmpBitmap);
89.   tmpBitmap.free;
90. end;
91.

#### marcov

• Global Moderator
• Hero Member
• Posts: 8734
• FPC developer.
##### Re: I need to rotate a picture in a TImage 90°
« Reply #23 on: July 11, 2020, 05:17:40 pm »
The following routines perform quick Bitmap clockwise rotations using scanlines.

It would be nice to include this code somewhere into Lazarus as standard goodies.

I'm also working on something like that, converting old generic code to FPC 3.2+ generic functions

My current version is not just for RGB24, (but also for 1,2,4 byte images) and 4-10 times faster because it adds looptiling to the algorithm.

See http://www.stack.nl/~marcov/files/bitmaprotatetest.zip