ClipForm.pas 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. {
  2. Clipping Demo
  3. Vampyre Imaging Library
  4. http://imaginglib.sourceforge.net
  5. I used this demo during fixing of clipping for CopyRect/StretchRect functions.
  6. You have a source and destination images on the form and few movable and
  7. resizable bevels that represent source, destnation, and clipping rectangle.
  8. Fiddle with them as you want and then click CopyRect Test or StretchRect Test
  9. button. New form will be shown with results. One image created by
  10. Imaging's Copy/Stretch rect functions (wrapped in TBaseImage here)
  11. and the second created by WinAPI's BitBlt and StretchBlt functions.
  12. Copied images should look exactly the same and stretched ones should
  13. have the same clipping and very similar looks (Imaging's stretch is filtered,
  14. WinAPI's not).
  15. Demo shows usage of high level Imaging classes (TBaseImage->TSingleImage)
  16. and VCL component support (TImagingBitmap). Needs JVCL library to compile.
  17. }
  18. unit ClipForm;
  19. interface
  20. uses
  21. Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  22. Dialogs, ExtCtrls, JvExExtCtrls, JvMovableBevel, StdCtrls, Buttons,
  23. ImagingTypes,
  24. Imaging,
  25. ImagingClasses,
  26. ImagingComponents,
  27. ImagingCanvases,
  28. ImagingFormats,
  29. ImagingUtility;
  30. type
  31. TMainForm = class(TForm)
  32. PanelConf: TPanel;
  33. ImageSrc: TImage;
  34. ImageDst: TImage;
  35. SelDst: TJvMovableBevel;
  36. SelSrc: TJvMovableBevel;
  37. PanelCmd: TPanel;
  38. Button1: TButton;
  39. Button2: TButton;
  40. Button3: TButton;
  41. Button4: TButton;
  42. ClipDst: TJvMovableBevel;
  43. Button5: TButton;
  44. Button6: TButton;
  45. CheckGenCanvas: TCheckBox;
  46. procedure BtnLoadImagesClick(Sender: TObject);
  47. procedure FormCreate(Sender: TObject);
  48. procedure FormDestroy(Sender: TObject);
  49. procedure Button1Click(Sender: TObject);
  50. procedure Button2Click(Sender: TObject);
  51. procedure Button3Click(Sender: TObject);
  52. procedure Button4Click(Sender: TObject);
  53. procedure Button5Click(Sender: TObject);
  54. procedure Button6Click(Sender: TObject);
  55. public
  56. SrcImage, DstImage: TSingleImage;
  57. SrcBitmap, DstBitmap: TImagingBitmap;
  58. procedure DoTest(Stretch, CanvasDraw: Boolean);
  59. end;
  60. const
  61. DefaultSrc = 'Vezyr.png';
  62. DefaultDst = 'Tigers.jpg';
  63. ForceFormat = ifA8R8G8B8;
  64. var
  65. MainForm: TMainForm;
  66. implementation
  67. uses
  68. ResultsForm;
  69. {$R *.dfm}
  70. function GetTestImage(const FileName: string): string;
  71. begin
  72. Result := ExtractFileDir(ExtractFileDir(ExtractFileDir(GetAppDir))) +
  73. PathDelim + 'Demos' + PathDelim + 'Data' + PathDelim + FileName;
  74. end;
  75. procedure TMainForm.FormCreate(Sender: TObject);
  76. begin
  77. // Create working images
  78. SrcImage := TSingleImage.Create;
  79. DstImage := TSingleImage.Create;
  80. // Create our bitmaps which will be assigned to TImage components.
  81. // Standard TBitmap could be used but our bitmaps can be assigned directly
  82. // from TSingleImage.
  83. SrcBitmap := TImagingBitmap.Create;
  84. DstBitmap := TImagingBitmap.Create;
  85. ImageSrc.Picture.Graphic := SrcBitmap;
  86. ImageDst.Picture.Graphic := DstBitmap;
  87. BtnLoadImagesClick(Self);
  88. end;
  89. procedure TMainForm.FormDestroy(Sender: TObject);
  90. begin
  91. // Free used images
  92. SrcImage.Free;
  93. DstImage.Free;
  94. // Free bitmaps asigned to TImage too - it wont free them automatically
  95. SrcBitmap.Free;
  96. DstBitmap.Free;
  97. end;
  98. procedure TMainForm.BtnLoadImagesClick(Sender: TObject);
  99. begin
  100. // Load test images
  101. SrcImage.LoadFromFile(GetTestImage(DefaultSrc));
  102. DstImage.LoadFromFile(GetTestImage(DefaultDst));
  103. // Change their format to A8R8G8B8 (for faster drawing later)
  104. SrcImage.Format := ForceFormat;
  105. DstImage.Format := ForceFormat;
  106. // Resize them to fit in TImages on form
  107. SrcImage.Resize(ImageSrc.Width, ImageSrc.Height, rfNearest);
  108. DstImage.Resize(ImageDst.Width, ImageDst.Height, rfNearest);
  109. // Finally assign them to those TImages
  110. ImageSrc.Picture.Graphic.Assign(SrcImage);
  111. ImageDst.Picture.Graphic.Assign(DstImage);
  112. end;
  113. procedure TMainForm.Button1Click(Sender: TObject);
  114. begin
  115. SelSrc.SetBounds(ImageSrc.Left, ImageSrc.Top, ImageSrc.Width, ImageSrc.Height);
  116. SelDst.SetBounds(ImageDst.Left, ImageDst.Top, ImageSrc.Width, ImageSrc.Height);
  117. ClipDst.SetBounds(ImageDst.Left - 20, ImageDst.Top - 20, ImageDst.Width + 40, ImageDst.Height + 40);
  118. end;
  119. procedure TMainForm.Button2Click(Sender: TObject);
  120. begin
  121. SelSrc.SetBounds(ImageSrc.Left, ImageSrc.Top, ImageSrc.Width, ImageSrc.Height);
  122. SelDst.SetBounds(ImageDst.Left, ImageDst.Top, ImageDst.Width, ImageDst.Height);
  123. ClipDst.SetBounds(ImageDst.Left - 20, ImageDst.Top - 20, ImageDst.Width + 40, ImageDst.Height + 40);
  124. end;
  125. procedure TMainForm.Button3Click(Sender: TObject);
  126. begin
  127. DoTest(False, False);
  128. end;
  129. procedure TMainForm.Button4Click(Sender: TObject);
  130. begin
  131. DoTest(True, False);
  132. end;
  133. procedure TMainForm.Button5Click(Sender: TObject);
  134. begin
  135. DoTest(False, True);
  136. end;
  137. procedure TMainForm.Button6Click(Sender: TObject);
  138. begin
  139. DoTest(True, True);
  140. end;
  141. procedure TMainForm.DoTest(Stretch, CanvasDraw: Boolean);
  142. var
  143. Result: TSingleImage;
  144. SrcBounds, DstBounds, DstClip: TRect;
  145. SrcBmp, DstBmp: TImagingBitmap;
  146. Rgn: HRGN;
  147. SrcCanvas, DestCanvas: TImagingCanvas;
  148. begin
  149. // First use Imaging to copy/stretch images ----------------
  150. // Create result image and get rects from movable bevels on the form
  151. Result := TSingleImage.CreateFromImage(DstImage);
  152. SrcBounds := Rect(SelSrc.Left - ImageSrc.Left, SelSrc.Top - ImageSrc.Top,
  153. SelSrc.Width, SelSrc.Height);
  154. DstBounds := Rect(SelDst.Left - ImageDst.Left, SelDst.Top - ImageDst.Top,
  155. SelDst.Width, SelDst.Height);
  156. DstClip := Rect(ClipDst.Left - ImageDst.Left, ClipDst.Top - ImageDst.Top,
  157. ClipDst.Left - ImageDst.Left + ClipDst.Width, ClipDst.Top - ImageDst.Top + ClipDst.Height);
  158. if not CanvasDraw then
  159. begin
  160. if Stretch then
  161. begin
  162. // Clips rects for stretching
  163. ImagingUtility.ClipStretchBounds(SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, SrcBounds.Bottom,
  164. DstBounds.Left, DstBounds.Top, DstBounds.Right, DstBounds.Bottom, SrcImage.Width, SrcImage.Height, DstClip);
  165. // Call image's stretch method
  166. SrcImage.StretchTo(SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, SrcBounds.Bottom,
  167. Result, DstBounds.Left, DstBounds.Top, DstBounds.Right, DstBounds.Bottom, rfBilinear);
  168. end
  169. else
  170. begin
  171. // Clips rects for copying
  172. ImagingUtility.ClipCopyBounds(SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, SrcBounds.Bottom,
  173. DstBounds.Left, DstBounds.Top, SrcImage.Width, SrcImage.Height, DstClip);
  174. // Call image's copy method
  175. SrcImage.CopyTo(SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, SrcBounds.Bottom,
  176. Result, DstBounds.Left, DstBounds.Top);
  177. end;
  178. end
  179. else
  180. begin
  181. if CheckGenCanvas.Checked then
  182. begin
  183. SrcCanvas := TImagingCanvas.CreateForImage(SrcImage);
  184. DestCanvas := TImagingCanvas.CreateForImage(Result);
  185. end
  186. else
  187. begin
  188. SrcCanvas := FindBestCanvasForImage(SrcImage).CreateForImage(SrcImage);
  189. DestCanvas := FindBestCanvasForImage(Result).CreateForImage(Result);
  190. end;
  191. if Stretch then
  192. begin
  193. // Clips rects for stretching
  194. ImagingUtility.ClipStretchBounds(SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, SrcBounds.Bottom,
  195. DstBounds.Left, DstBounds.Top, DstBounds.Right, DstBounds.Bottom, SrcImage.Width, SrcImage.Height, DstClip);
  196. // Call stretch method
  197. SrcCanvas.StretchDrawAlpha(Rect(SrcBounds.Left, SrcBounds.Top, SrcBounds.Left + SrcBounds.Right, SrcBounds.Top + SrcBounds.Bottom),
  198. DestCanvas, Rect(DstBounds.Left, DstBounds.Top, DstBounds.Left + DstBounds.Right, DstBounds.Top + DstBounds.Bottom),
  199. rfBilinear);
  200. end
  201. else
  202. begin
  203. // Clips rects for copying
  204. ImagingUtility.ClipCopyBounds(SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, SrcBounds.Bottom,
  205. DstBounds.Left, DstBounds.Top, SrcImage.Width, SrcImage.Height, DstClip);
  206. // Call draw method
  207. SrcCanvas.DrawAlpha(Rect(SrcBounds.Left, SrcBounds.Top, SrcBounds.Left + SrcBounds.Right, SrcBounds.Top + SrcBounds.Bottom),
  208. DestCanvas, DstBounds.Left, DstBounds.Top);
  209. end;
  210. SrcCanvas.Free;
  211. DestCanvas.Free;
  212. end;
  213. // Assign Imaging result to TImage on Result form
  214. ResultForm.ImageMy.Picture.Graphic.Assign(Result);
  215. // Now use WinAPI to copy/stretch images ----------------------
  216. // Create bitmaps and assign source and dest images to them
  217. SrcBmp := TImagingBitmap.Create;
  218. SrcBmp.Assign(SrcImage);
  219. DstBmp := TImagingBitmap.Create;
  220. DstBmp.Assign(DstImage);
  221. // Get fresh bounds
  222. SrcBounds := Rect(SelSrc.Left - ImageSrc.Left, SelSrc.Top - ImageSrc.Top,
  223. SelSrc.Width, SelSrc.Height);
  224. DstBounds := Rect(SelDst.Left - ImageDst.Left, SelDst.Top - ImageDst.Top,
  225. SelDst.Width, SelDst.Height);
  226. // Now create and set clipping region
  227. Rgn := CreateRectRgn(DstClip.Left, DstClip.Top, DstClip.Right, DstClip.Bottom);
  228. SelectClipRgn(DstBmp.Canvas.Handle, Rgn);
  229. // Now stretch or copy
  230. if Stretch then
  231. begin
  232. StretchBlt(DstBmp.Canvas.Handle, DstBounds.Left, DstBounds.Top, DstBounds.Right, DstBounds.Bottom,
  233. SrcBmp.Canvas.Handle, SrcBounds.Left, SrcBounds.Top, SrcBounds.Right, SrcBounds.Bottom, SRCCOPY);
  234. end
  235. else
  236. begin
  237. BitBlt(DstBmp.Canvas.Handle, DstBounds.Left, DstBounds.Top, SrcBounds.Right, SrcBounds.Bottom,
  238. SrcBmp.Canvas.Handle, SrcBounds.Left, SrcBounds.Top, SRCCOPY);
  239. end;
  240. // Assign Imaging result to TImage on Result form
  241. ResultForm.ImageWin.Picture.Graphic.Assign(DstBmp);
  242. Result.Free;
  243. SrcBmp.Free;
  244. DstBmp.Free;
  245. //SelectClipRgn(DstBmp.Canvas.Handle, 0);
  246. //DeleteObject(Rgn);
  247. // Show results
  248. ResultForm.ShowModal;
  249. end;
  250. end.