ushiftcolors.pas 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit UShiftColors;
  3. {$mode objfpc}{$H+}
  4. interface
  5. uses
  6. Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
  7. StdCtrls, ComCtrls, Spin, ExtCtrls, BGRABitmap, LazPaintType, LCScaleDPI,
  8. ufilterconnector, uscripting;
  9. type
  10. { TFShiftColors }
  11. TFShiftColors = class(TForm)
  12. Button_Cancel: TButton;
  13. Button_OK: TButton;
  14. CheckBox_GSBA: TCheckBox;
  15. FloatSpinEdit_Hue: TFloatSpinEdit;
  16. FloatSpinEdit_Saturation: TFloatSpinEdit;
  17. Label1: TLabel;
  18. Label2: TLabel;
  19. TimerDrawPendingRows: TTimer;
  20. TrackBar_Hue: TTrackBar;
  21. TrackBar_Saturation: TTrackBar;
  22. procedure Button_OKClick(Sender: TObject);
  23. procedure CheckBox_GSBAChange(Sender: TObject);
  24. procedure FloatSpinEdit_HueChange(Sender: TObject);
  25. procedure FloatSpinEdit_SaturationChange(Sender: TObject);
  26. procedure FormCreate(Sender: TObject);
  27. procedure FormShow(Sender: TObject);
  28. procedure TimerDrawPendingRowsTimer(Sender: TObject);
  29. procedure TrackBar_Change(Sender: TObject);
  30. private
  31. { private declarations }
  32. FInitialized: boolean;
  33. FInstance: TLazPaintCustomInstance;
  34. FFilterConnector: TFilterConnector;
  35. FUpdatingSpinEdit: boolean;
  36. FOddRows: boolean;
  37. FPendingRows: boolean;
  38. function GetChosenHueShiftF: single;
  39. function GetChosenSatShiftF: single;
  40. procedure SetChosenHueShiftF(AValue: single);
  41. procedure SetChosenSatShiftF(AValue: single);
  42. procedure UpdateSpinEdit;
  43. function GetChosenHueShift: integer;
  44. procedure OnTryStopAction({%H-}sender: TFilterConnector);
  45. procedure SetChosenHueShift(AValue: integer);
  46. procedure LoadParameters;
  47. procedure HalfApplyChosenShift;
  48. procedure ParametersChanged;
  49. public
  50. { public declarations }
  51. function ShowModal: integer; override;
  52. function ShowModal(AInstance: TLazPaintCustomInstance; AParameters: TVariableSet): integer;
  53. property ChosenHueShift: integer read GetChosenHueShift write SetChosenHueShift;
  54. property ChosenHueShiftF: single read GetChosenHueShiftF write SetChosenHueShiftF;
  55. property ChosenSatShiftF: single read GetChosenSatShiftF write SetChosenSatShiftF;
  56. end;
  57. implementation
  58. uses umac, BGRABitmapTypes, uresourcestrings, UColorFilters;
  59. { TFShiftColors }
  60. procedure TFShiftColors.FormCreate(Sender: TObject);
  61. begin
  62. ScaleControl(Self,OriginalDPI);
  63. CheckFloatSpinEdit(FloatSpinEdit_Saturation);
  64. CheckFloatSpinEdit(FloatSpinEdit_Hue);
  65. CheckOKCancelBtns(Button_OK,Button_Cancel);
  66. TrackBar_Hue.Min := 0;
  67. TrackBar_Hue.Max := TrackBar_Hue.Width and not 3;
  68. TrackBar_Hue.Position := TrackBar_Hue.Max div 2;
  69. TrackBar_Hue.Frequency := TrackBar_Hue.Max div 4;
  70. TrackBar_Saturation.Max := TrackBar_Saturation.Width and not 3;
  71. TrackBar_Saturation.Position := TrackBar_Saturation.Max div 2;
  72. TrackBar_Saturation.Frequency := TrackBar_Saturation.Max div 4;
  73. FInitialized := true;
  74. UpdateSpinEdit;
  75. end;
  76. procedure TFShiftColors.FormShow(Sender: TObject);
  77. begin
  78. LoadParameters;
  79. HalfApplyChosenShift;
  80. HalfApplyChosenShift;
  81. FPendingRows:= false;
  82. Top := FInstance.MainFormBounds.Top;
  83. end;
  84. procedure TFShiftColors.TimerDrawPendingRowsTimer(Sender: TObject);
  85. begin
  86. TimerDrawPendingRows.Enabled := false;
  87. if FPendingRows then
  88. begin
  89. HalfApplyChosenShift;
  90. FPendingRows:= false;
  91. end;
  92. Button_OK.Enabled := true;
  93. end;
  94. procedure TFShiftColors.TrackBar_Change(Sender: TObject);
  95. begin
  96. if FInitialized then
  97. begin
  98. UpdateSpinEdit;
  99. ParametersChanged;
  100. end;
  101. end;
  102. procedure TFShiftColors.UpdateSpinEdit;
  103. begin
  104. if FUpdatingSpinEdit then exit;
  105. FUpdatingSpinEdit:= true;
  106. FloatSpinEdit_Hue.Value := ChosenHueShiftF;
  107. FloatSpinEdit_Saturation.Value := ChosenSatShiftF;
  108. FloatSpinEdit_Hue.Update;
  109. FloatSpinEdit_Saturation.Update;
  110. FUpdatingSpinEdit:= false;
  111. end;
  112. function TFShiftColors.GetChosenHueShiftF: single;
  113. begin
  114. result := round(ChosenHueShift/65536*3600)/10;
  115. end;
  116. function TFShiftColors.GetChosenSatShiftF: single;
  117. begin
  118. result := round((TrackBar_Saturation.Position/TrackBar_Saturation.Max*4-2)*1000)/1000;
  119. end;
  120. procedure TFShiftColors.SetChosenHueShiftF(AValue: single);
  121. begin
  122. ChosenHueShift := round(AValue*65536/360);
  123. end;
  124. procedure TFShiftColors.SetChosenSatShiftF(AValue: single);
  125. begin
  126. TrackBar_Saturation.Position := round((AValue+2)/4*TrackBar_Saturation.Max);
  127. end;
  128. procedure TFShiftColors.OnTryStopAction(sender: TFilterConnector);
  129. begin
  130. if self.visible then Close;
  131. end;
  132. function TFShiftColors.GetChosenHueShift: integer;
  133. begin
  134. result := round((TrackBar_Hue.Position/TrackBar_Hue.Max-0.5)*65536);
  135. end;
  136. procedure TFShiftColors.SetChosenHueShift(AValue: integer);
  137. begin
  138. TrackBar_Hue.Position := round((AValue/65536+0.5)*TrackBar_Hue.Max);
  139. end;
  140. procedure TFShiftColors.LoadParameters;
  141. var OldInitialized: boolean;
  142. begin
  143. If Assigned(FFilterConnector) then
  144. begin
  145. OldInitialized := FInitialized;
  146. FInitialized := false;
  147. if FFilterConnector.Parameters.IsDefined('Hue') then
  148. ChosenHueShiftF := FFilterConnector.Parameters.Floats['Hue'];
  149. if FFilterConnector.Parameters.IsDefined('Saturation') then
  150. ChosenSatShiftF := FFilterConnector.Parameters.Floats['Saturation'];
  151. if FFilterConnector.Parameters.IsDefined('Correction') then
  152. CheckBox_GSBA.Checked := FFilterConnector.Parameters.Booleans['Correction'];
  153. UpdateSpinEdit;
  154. FInitialized := OldInitialized;
  155. end;
  156. end;
  157. function TFShiftColors.ShowModal: integer;
  158. begin
  159. TimerDrawPendingRows.Enabled:= false;
  160. if (FFilterConnector = nil) or (FFilterConnector.ActiveLayer = nil) then
  161. begin
  162. if FInstance <> nil then
  163. FInstance.ShowMessage(rsLazPaint,rsNoActiveLayer) else
  164. ShowMessage(rsNoActiveLayer);
  165. result := mrAbort
  166. end
  167. else
  168. Result:=inherited ShowModal;
  169. TimerDrawPendingRows.Enabled:= false;
  170. end;
  171. function TFShiftColors.ShowModal(AInstance: TLazPaintCustomInstance; AParameters: TVariableSet): integer;
  172. var gsbaOptionFromConfig: boolean;
  173. topmostInfo: TTopMostInfo;
  174. h, s: Double; corr: boolean;
  175. begin
  176. try
  177. FFilterConnector := TFilterConnector.Create(AInstance,AParameters,false);
  178. FFilterConnector.OnTryStopAction := @OnTryStopAction;
  179. except
  180. on ex: exception do
  181. begin
  182. AInstance.ShowError('ShiftColors',ex.Message);
  183. result := mrAbort;
  184. exit;
  185. end;
  186. end;
  187. try
  188. FInstance := AInstance;
  189. if AParameters.Booleans['Validate'] then
  190. begin
  191. if AParameters.IsDefined('Hue') then h := AParameters.Floats['Hue']
  192. else h := FloatSpinEdit_Hue.Value;
  193. if AParameters.IsDefined('Saturation') then s := AParameters.Floats['Saturation']
  194. else s := FloatSpinEdit_Saturation.Value;
  195. if AParameters.IsDefined('Correction') then corr := AParameters.Booleans['Correction']
  196. else corr := AInstance.Config.DefaultUseGSBA;
  197. ShiftColors(FFilterConnector, h, s, corr);
  198. FFilterConnector.ValidateAction;
  199. result := mrOk;
  200. end else
  201. begin
  202. if AParameters.IsDefined('Correction') then
  203. begin
  204. gsbaOptionFromConfig:= false;
  205. self.CheckBox_GSBA.Checked := AParameters.Booleans['Correction'];
  206. end else
  207. begin
  208. gsbaOptionFromConfig:= true;
  209. self.CheckBox_GSBA.Checked := AInstance.Config.DefaultUseGSBA;
  210. end;
  211. topmostInfo := AInstance.HideTopmost;
  212. try
  213. result := self.ShowModal;
  214. except
  215. on ex: exception do
  216. begin
  217. AInstance.ShowError('ShiftColors',ex.Message);
  218. result := mrAbort;
  219. end;
  220. end;
  221. AInstance.ShowTopmost(topmostInfo);
  222. if (result = mrOK) and gsbaOptionFromConfig then
  223. AInstance.Config.SetDefaultUseGSBA(self.CheckBox_GSBA.Checked);
  224. end;
  225. finally
  226. FreeAndNil(FFilterConnector);
  227. FInstance := nil;
  228. end;
  229. end;
  230. procedure TFShiftColors.Button_OKClick(Sender: TObject);
  231. begin
  232. Button_OK.Enabled := false;
  233. if FPendingRows then
  234. begin
  235. HalfApplyChosenShift;
  236. FPendingRows := false;
  237. end;
  238. FFilterConnector.ValidateAction;
  239. FFilterConnector.Parameters.Floats['Hue'] := FloatSpinEdit_Hue.Value;
  240. FFilterConnector.Parameters.Floats['Saturation'] := FloatSpinEdit_Saturation.Value;
  241. FFilterConnector.Parameters.Booleans['Correction'] := CheckBox_GSBA.Checked;
  242. end;
  243. procedure TFShiftColors.CheckBox_GSBAChange(Sender: TObject);
  244. begin
  245. if FInitialized and Visible then ParametersChanged;
  246. end;
  247. procedure TFShiftColors.FloatSpinEdit_HueChange(Sender: TObject);
  248. begin
  249. if FUpdatingSpinEdit then exit;
  250. FUpdatingSpinEdit := true;
  251. ChosenHueShiftF:= FloatSpinEdit_Hue.Value;
  252. FUpdatingSpinEdit := false;
  253. end;
  254. procedure TFShiftColors.FloatSpinEdit_SaturationChange(Sender: TObject);
  255. begin
  256. if FUpdatingSpinEdit then exit;
  257. FUpdatingSpinEdit := true;
  258. ChosenSatShiftF := FloatSpinEdit_Saturation.Value;
  259. FUpdatingSpinEdit := false;
  260. end;
  261. procedure TFShiftColors.HalfApplyChosenShift;
  262. begin
  263. ShiftColors(FFilterConnector,ChosenHueShiftF,ChosenSatShiftF,CheckBox_GSBA.Checked,not FOddRows,FOddRows);
  264. FOddRows:= not FOddRows;
  265. end;
  266. procedure TFShiftColors.ParametersChanged;
  267. begin
  268. Button_OK.Enabled := false;
  269. HalfApplyChosenShift;
  270. FPendingRows:= true;
  271. TimerDrawPendingRows.Enabled := true;
  272. end;
  273. {$R *.lfm}
  274. end.