Recent

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

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • 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: 452
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.  

Thaddy

  • Hero Member
  • *****
  • Posts: 14203
  • Probably until I exterminate Putin.
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 »
Specialize a type, not a var.

RedOctober

  • Sr. Member
  • ****
  • Posts: 452
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: 452
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: 452
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

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • 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: 44
    • DJMaster on GitHub
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

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • 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

 

TinyPortal © 2005-2018