fRotate.pas 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. unit fRotate;
  2. (* ***** BEGIN LICENSE BLOCK *****
  3. * Version: MPL 1.1 or LGPL 2.1 with linking exception
  4. *
  5. * The contents of this file are subject to the Mozilla Public License Version
  6. * 1.1 (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. * http://www.mozilla.org/MPL/
  9. *
  10. * Software distributed under the License is distributed on an "AS IS" basis,
  11. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. * for the specific language governing rights and limitations under the
  13. * License.
  14. *
  15. * Alternatively, the contents of this file may be used under the terms of the
  16. * Free Pascal modified version of the GNU Lesser General Public License
  17. * Version 2.1 (the "FPC modified LGPL License"), in which case the provisions
  18. * of this license are applicable instead of those above.
  19. * Please see the file LICENSE.txt for additional information concerning this
  20. * license.
  21. *
  22. * The Original Code is Rotate Example
  23. *
  24. * The Initial Developer of the Original Code is
  25. * Alex A. Denisov
  26. *
  27. * Portions created by the Initial Developer are Copyright (C) 2000-2005
  28. * the Initial Developer. All Rights Reserved.
  29. *
  30. * Contributor(s):
  31. *
  32. * ***** END LICENSE BLOCK ***** *)
  33. interface
  34. {$I GR32.inc}
  35. uses
  36. {$IFNDEF FPC} Windows, {$ELSE} LCLIntf, LResources, {$ENDIF}
  37. SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, Math,
  38. GR32, GR32_Image, GR32_Transforms, GR32_RangeBars;
  39. type
  40. TFormRotateExample = class(TForm)
  41. Angle: TGaugeBar;
  42. Src: TImage32;
  43. Dst: TImage32;
  44. procedure FormCreate(Sender: TObject);
  45. procedure AngleChange(Sender: TObject);
  46. public
  47. procedure ScaleRot(Alpha: Single);
  48. end;
  49. var
  50. FormRotateExample: TFormRotateExample;
  51. implementation
  52. {$IFDEF FPC}
  53. {$R *.lfm}
  54. {$ELSE}
  55. {$R *.dfm}
  56. {$ENDIF}
  57. uses
  58. GR32_Math,
  59. {$IFDEF Darwin}
  60. MacOSAll,
  61. {$ENDIF}
  62. {$IFNDEF FPC}
  63. JPEG;
  64. {$ELSE}
  65. LazJPG;
  66. {$ENDIF}
  67. // TFormRotateExample
  68. procedure TFormRotateExample.FormCreate(Sender: TObject);
  69. var
  70. ResStream: TResourceStream;
  71. JPEG: TJPEGImage;
  72. begin
  73. // load example image
  74. JPEG := TJPEGImage.Create;
  75. try
  76. ResStream := TResourceStream.Create(HInstance, 'Delphi', RT_RCDATA);
  77. try
  78. JPEG.LoadFromStream(ResStream);
  79. finally
  80. ResStream.Free;
  81. end;
  82. Src.Bitmap.Assign(JPEG);
  83. finally
  84. JPEG.Free;
  85. end;
  86. Dst.Bitmap.SetSize(Src.Bitmap.Width, Src.Bitmap.Height);
  87. // a workaround to the edge antialiasing problem
  88. SetBorderTransparent(Src.Bitmap, Src.Bitmap.BoundsRect);
  89. // show the picture
  90. ScaleRot(0);
  91. end;
  92. procedure TFormRotateExample.ScaleRot(Alpha: Single);
  93. var
  94. SrcR: Integer;
  95. SrcB: Integer;
  96. T: TAffineTransformation;
  97. Sn, Cn: TFloat;
  98. Sx, Sy, Scale: Single;
  99. begin
  100. SrcR := Src.Bitmap.Width - 1;
  101. SrcB := Src.Bitmap.Height - 1;
  102. T := TAffineTransformation.Create;
  103. T.SrcRect := FloatRect(0, 0, SrcR + 1, SrcB + 1);
  104. try
  105. // shift the origin
  106. T.Clear;
  107. // move the origin to a center for scaling and rotation
  108. T.Translate(-SrcR * 0.5, -SrcB * 0.5);
  109. T.Rotate(0, 0, Alpha);
  110. Alpha := Alpha * PI / 180;
  111. // get the width and height of rotated image (without scaling)
  112. GR32_Math.SinCos(Alpha, Sn, Cn);
  113. Sx := Abs(SrcR * Cn) + Abs(SrcB * Sn);
  114. Sy := Abs(SrcR * Sn) + Abs(SrcB * Cn);
  115. // calculate a new scale so that the image fits in original boundaries
  116. Sx := Src.Bitmap.Width / Sx;
  117. Sy := Src.Bitmap.Height / Sy;
  118. Scale := Min(Sx, Sy);
  119. T.Scale(Scale);
  120. // move the origin back
  121. T.Translate(SrcR * 0.5, SrcB * 0.5);
  122. // transform the bitmap
  123. Dst.BeginUpdate;
  124. Dst.Bitmap.Clear(clBlack32);
  125. Transform(Dst.Bitmap, Src.Bitmap, T);
  126. Dst.EndUpdate;
  127. Dst.Repaint;
  128. finally
  129. T.Free;
  130. end;
  131. end;
  132. procedure TFormRotateExample.AngleChange(Sender: TObject);
  133. begin
  134. ScaleRot(-Angle.Position);
  135. end;
  136. end.