uimageaction.pas 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054
  1. // SPDX-License-Identifier: GPL-3.0-only
  2. unit UImageAction;
  3. {$mode objfpc}{$H+}
  4. interface
  5. uses
  6. Classes, SysUtils, FPimage, LazPaintType, BGRABitmap, UImage, UTool,
  7. UScripting, ULayerAction, UImageType, BGRABitmapTypes, BGRALayerOriginal,
  8. BGRASVGOriginal, BGRALayers;
  9. type
  10. { TImageActions }
  11. TImageActions = class
  12. private
  13. FInstance: TLazPaintCustomInstance;
  14. function GetCurrentTool: TPaintToolType;
  15. function GetImage: TLazPaintImage;
  16. function GetToolManager: TToolManager;
  17. procedure ChooseTool(ATool: TPaintToolType; AAsFromGui: boolean = true);
  18. procedure RegisterScripts(ARegister: Boolean);
  19. function GenericScriptFunction(AVars: TVariableSet): TScriptResult;
  20. function ScriptGetAllLayersId(AVars: TVariableSet): TScriptResult;
  21. function ScriptGetLayerIndex(AVars: TVariableSet): TScriptResult;
  22. function ScriptImageMoveLayerIndex(AVars: TVariableSet): TScriptResult;
  23. function ScriptLayerFromFile(AVars: TVariableSet): TScriptResult;
  24. function ScriptImageGetRegistry(AVars: TVariableSet): TScriptResult;
  25. function ScriptLayerGetId(AVars: TVariableSet): TScriptResult;
  26. function ScriptLayerGetRegistry(AVars: TVariableSet): TScriptResult;
  27. function ScriptLayerSaveAs(AVars: TVariableSet): TScriptResult;
  28. function ScriptLayerSelectId(AVars: TVariableSet): TScriptResult;
  29. function ScriptLayerAddNew(AVars: TVariableSet): TScriptResult;
  30. function ScriptImageSetRegistry(AVars: TVariableSet): TScriptResult;
  31. function ScriptLayerSetRegistry(AVars: TVariableSet): TScriptResult;
  32. function ScriptPasteAsNewLayer(AVars: TVariableSet): TScriptResult;
  33. function ScriptLayerDuplicate(AVars: TVariableSet): TScriptResult;
  34. function ScriptPutImage(AVars: TVariableSet): TScriptResult;
  35. function ScriptGetImage(AVars: TVariableSet): TScriptResult;
  36. function ScriptLayerFill(AVars: TVariableSet): TScriptResult;
  37. function ScriptGetFrameIndex(AVars: TVariableSet): TScriptResult;
  38. procedure ReleaseSelection;
  39. function ScriptSelectLayerIndex(AVars: TVariableSet): TScriptResult;
  40. function ScriptClearAlpha(AVars: TVariableSet): TScriptResult;
  41. function ScriptFillBackground(AVars: TVariableSet): TScriptResult;
  42. public
  43. constructor Create(AInstance: TLazPaintCustomInstance);
  44. destructor Destroy; override;
  45. procedure ClearAlpha;
  46. procedure FillBackground;
  47. procedure ClearAlpha(AColor: TBGRAPixel);
  48. procedure FillBackground(AColor: TBGRAPixel);
  49. function SmartZoom3: boolean;
  50. procedure Undo;
  51. procedure Redo;
  52. procedure DoBegin;
  53. function DoEnd: boolean;
  54. procedure SetCurrentBitmap(bmp: TBGRABitmap; AUndoable: boolean;
  55. ACaption: string = ''; AOpacity: byte = 255);
  56. procedure SetCurrentBitmap(bmp: TBGRACustomLayeredBitmap; AUndoable: boolean);
  57. procedure CropToSelectionAndLayer;
  58. procedure CropToSelection;
  59. procedure Flatten;
  60. procedure TakeScreenshot(ARect: TRect);
  61. procedure HorizontalFlip(AOption: TFlipOption);
  62. procedure VerticalFlip(AOption: TFlipOption);
  63. procedure RotateCW;
  64. procedure RotateCCW;
  65. procedure Rotate180;
  66. procedure LinearNegativeAll;
  67. procedure NegativeAll;
  68. procedure SwapRedBlueAll;
  69. procedure InvertSelection;
  70. procedure Deselect;
  71. procedure CopySelection;
  72. procedure CutSelection;
  73. procedure RetrieveSelection;
  74. procedure DeleteSelection;
  75. procedure RemoveSelection;
  76. procedure Paste;
  77. function PasteAsNewLayer: integer;
  78. procedure SelectAll;
  79. procedure SelectionFit;
  80. function NewLayer: boolean; overload;
  81. function NewLayer(ALayer: TBGRABitmap; AName: string; ABlendOp: TBlendOperation; AOpacity: byte = 255): boolean; overload;
  82. function NewLayer(ALayer: TBGRABitmap; AName: string; AOffset: TPoint; ABlendOp: TBlendOperation; AOpacity: byte = 255): boolean; overload;
  83. function NewLayer(ALayer: TBGRALayerCustomOriginal; AName: string; ABlendOp: TBlendOperation; AMatrix: TAffineMatrix; AOpacity: byte = 255): boolean; overload;
  84. function DuplicateLayer: boolean;
  85. procedure RasterizeLayer;
  86. procedure MergeLayerOver;
  87. function RemoveLayer: boolean;
  88. procedure EditSelection(ACallback: TModifyImageCallback);
  89. procedure Import3DObject(AFilenameUTF8: string);
  90. function GetPixel(X,Y: Integer): TBGRAPixel;
  91. function PutImage(X,Y: integer; AImage: TBGRACustomBitmap; AMode: TDrawMode; AOpacity: byte): boolean;
  92. function LayerFill(AColor: TBGRAPixel; AMode: TDrawMode): boolean;
  93. function TryAddLayerFromFile(AFilenameUTF8: string; ALoadedImage: TBGRABitmap = nil): ArrayOfLayerId;
  94. function AddLayerFromBitmap(ABitmap: TBGRABitmap; AName: string): boolean;
  95. function AddLayerFromOriginal(AOriginal: TBGRALayerCustomOriginal; AName: string): boolean;
  96. function AddLayerFromOriginal(AOriginal: TBGRALayerCustomOriginal; AName: string; AMatrix: TAffineMatrix; ABlendOp: TBlendOperation = boTransparent; AOpacity: byte = 255): boolean;
  97. function ChangeLayeredImageCanvasSize(layeredBmp: TLazPaintImage; newWidth,
  98. newHeight: integer; anchor: string; background: TBGRAPixel;
  99. repeatImage: boolean; flipMode: boolean): TBGRALayeredBitmap;
  100. procedure ChangeCanvasSize(AWidth, AHeight: integer; AAnchor: string;
  101. ARepeatImage, AFlipMode: boolean);
  102. function LoadSelection(AFilenameUTF8: string; ALoadedImage: PImageEntry = nil): boolean;
  103. property Image: TLazPaintImage read GetImage;
  104. property ToolManager: TToolManager read GetToolManager;
  105. property CurrentTool: TPaintToolType read GetCurrentTool;
  106. end;
  107. implementation
  108. uses Controls, Dialogs, UResourceStrings, UObject3D,
  109. ULoadImage, UGraph, UClipboard, Types, BGRAGradientOriginal,
  110. BGRATransform, ULoading, math, LCVectorClipboard, LCVectorOriginal, LCVectorRectShapes,
  111. BGRAUTF8, UFileSystem, Forms, UTranslation;
  112. { TImageActions }
  113. function TImageActions.GetImage: TLazPaintImage;
  114. begin
  115. result := FInstance.Image;
  116. end;
  117. function TImageActions.GetCurrentTool: TPaintToolType;
  118. begin
  119. if FInstance.ToolManager.CurrentTool = nil then
  120. result := ptHand
  121. else
  122. result := FInstance.ToolManager.GetCurrentToolType;
  123. end;
  124. function TImageActions.GetToolManager: TToolManager;
  125. begin
  126. result := FInstance.ToolManager;
  127. end;
  128. procedure TImageActions.ChooseTool(ATool: TPaintToolType; AAsFromGui: boolean);
  129. begin
  130. FInstance.ChooseTool(ATool, AAsFromGui);
  131. end;
  132. procedure TImageActions.RegisterScripts(ARegister: Boolean);
  133. var Scripting: TScriptContext;
  134. begin
  135. Scripting := FInstance.ScriptContext;
  136. Scripting.RegisterScriptFunction('ImageCrop',@GenericScriptFunction,ARegister);
  137. Scripting.RegisterScriptFunction('ImageCropLayer',@GenericScriptFunction,ARegister);
  138. Scripting.RegisterScriptFunction('ImageFlatten',@GenericScriptFunction,ARegister);
  139. Scripting.RegisterScriptFunction('ImageClearAlpha',@ScriptClearAlpha,ARegister);
  140. Scripting.RegisterScriptFunction('ImageFillBackground',@ScriptFillBackground,ARegister);
  141. Scripting.RegisterScriptFunction('ImageSmartZoom3',@GenericScriptFunction,ARegister);
  142. Scripting.RegisterScriptFunction('ImageHorizontalFlip',@GenericScriptFunction,ARegister);
  143. Scripting.RegisterScriptFunction('ImageVerticalFlip',@GenericScriptFunction,ARegister);
  144. Scripting.RegisterScriptFunction('SelectionHorizontalFlip',@GenericScriptFunction,ARegister);
  145. Scripting.RegisterScriptFunction('SelectionVerticalFlip',@GenericScriptFunction,ARegister);
  146. Scripting.RegisterScriptFunction('ImageRotateCW',@GenericScriptFunction,ARegister);
  147. Scripting.RegisterScriptFunction('ImageRotateCCW',@GenericScriptFunction,ARegister);
  148. Scripting.RegisterScriptFunction('ImageRotate180',@GenericScriptFunction,ARegister);
  149. Scripting.RegisterScriptFunction('ImageLinearNegative',@GenericScriptFunction,ARegister);
  150. Scripting.RegisterScriptFunction('ImageNegative',@GenericScriptFunction,ARegister);
  151. Scripting.RegisterScriptFunction('ImageSwapRedBlue',@GenericScriptFunction,ARegister);
  152. Scripting.RegisterScriptFunction('EditUndo',@GenericScriptFunction,ARegister);
  153. Scripting.RegisterScriptFunction('EditRedo',@GenericScriptFunction,ARegister);
  154. Scripting.RegisterScriptFunction('EditDoBegin',@GenericScriptFunction,ARegister);
  155. Scripting.RegisterScriptFunction('EditDoEnd',@GenericScriptFunction,ARegister);
  156. Scripting.RegisterScriptFunction('EditInvertSelection',@GenericScriptFunction,ARegister);
  157. Scripting.RegisterScriptFunction('EditDeselect',@GenericScriptFunction,ARegister);
  158. Scripting.RegisterScriptFunction('EditCopy',@GenericScriptFunction,ARegister);
  159. Scripting.RegisterScriptFunction('EditCut',@GenericScriptFunction,ARegister);
  160. Scripting.RegisterScriptFunction('EditDeleteSelection',@GenericScriptFunction,ARegister);
  161. Scripting.RegisterScriptFunction('EditPaste',@GenericScriptFunction,ARegister);
  162. Scripting.RegisterScriptFunction('EditPasteAsNewLayer',@ScriptPasteAsNewLayer,ARegister);
  163. Scripting.RegisterScriptFunction('EditSelectAll',@GenericScriptFunction,ARegister);
  164. Scripting.RegisterScriptFunction('EditSelectionFit',@GenericScriptFunction,ARegister);
  165. Scripting.RegisterScriptFunction('IsSelectionMaskEmpty',@GenericScriptFunction,ARegister);
  166. Scripting.RegisterScriptFunction('IsSelectionLayerEmpty',@GenericScriptFunction,ARegister);
  167. Scripting.RegisterScriptFunction('IsLayerEmpty',@GenericScriptFunction,ARegister);
  168. Scripting.RegisterScriptFunction('IsLayerTransparent',@GenericScriptFunction,ARegister);
  169. Scripting.RegisterScriptFunction('LayerHorizontalFlip',@GenericScriptFunction,ARegister);
  170. Scripting.RegisterScriptFunction('LayerVerticalFlip',@GenericScriptFunction,ARegister);
  171. Scripting.RegisterScriptFunction('LayerGetId',@ScriptLayerGetId,ARegister);
  172. Scripting.RegisterScriptFunction('LayerGetName',@GenericScriptFunction,ARegister);
  173. Scripting.RegisterScriptFunction('LayerGetOpacity',@GenericScriptFunction,ARegister);
  174. Scripting.RegisterScriptFunction('LayerGetBlendOp',@GenericScriptFunction,ARegister);
  175. Scripting.RegisterScriptFunction('LayerGetVisible',@GenericScriptFunction,ARegister);
  176. Scripting.RegisterScriptFunction('LayerSelectId',@ScriptLayerSelectId,ARegister);
  177. Scripting.RegisterScriptFunction('LayerSetName',@GenericScriptFunction,ARegister);
  178. Scripting.RegisterScriptFunction('LayerSetOpacity',@GenericScriptFunction,ARegister);
  179. Scripting.RegisterScriptFunction('LayerSetBlendOp',@GenericScriptFunction,ARegister);
  180. Scripting.RegisterScriptFunction('LayerSetVisible',@GenericScriptFunction,ARegister);
  181. Scripting.RegisterScriptFunction('LayerAddNew',@ScriptLayerAddNew,ARegister);
  182. Scripting.RegisterScriptFunction('LayerFromFile',@ScriptLayerFromFile,ARegister);
  183. Scripting.RegisterScriptFunction('LayerSaveAs',@ScriptLayerSaveAs,ARegister);
  184. Scripting.RegisterScriptFunction('LayerDuplicate',@ScriptLayerDuplicate,ARegister);
  185. Scripting.RegisterScriptFunction('LayerRasterize',@GenericScriptFunction,ARegister);
  186. Scripting.RegisterScriptFunction('LayerMergeOver',@GenericScriptFunction,ARegister);
  187. Scripting.RegisterScriptFunction('LayerRemoveCurrent',@GenericScriptFunction,ARegister);
  188. Scripting.RegisterScriptFunction('LayerGetRegistry',@ScriptLayerGetRegistry,ARegister);
  189. Scripting.RegisterScriptFunction('LayerSetRegistry',@ScriptLayerSetRegistry,ARegister);
  190. Scripting.RegisterScriptFunction('ImageGetRegistry',@ScriptImageGetRegistry,ARegister);
  191. Scripting.RegisterScriptFunction('ImageSetRegistry',@ScriptImageSetRegistry,ARegister);
  192. Scripting.RegisterScriptFunction('ImageMoveLayerIndex',@ScriptImageMoveLayerIndex,ARegister);
  193. Scripting.RegisterScriptFunction('GetLayerIndex',@ScriptGetLayerIndex,ARegister);
  194. Scripting.RegisterScriptFunction('GetAllLayersId',@ScriptGetAllLayersId,ARegister);
  195. Scripting.RegisterScriptFunction('SelectLayerIndex',@ScriptSelectLayerIndex,ARegister);
  196. Scripting.RegisterScriptFunction('GetLayerCount',@GenericScriptFunction,ARegister);
  197. Scripting.RegisterScriptFunction('GetFrameIndex',@ScriptGetFrameIndex,ARegister);
  198. Scripting.RegisterScriptFunction('GetFrameCount',@GenericScriptFunction,ARegister);
  199. Scripting.RegisterScriptFunction('GetPixel',@GenericScriptFunction,ARegister);
  200. Scripting.RegisterScriptFunction('GetImageWidth',@GenericScriptFunction,ARegister);
  201. Scripting.RegisterScriptFunction('GetImageHeight',@GenericScriptFunction,ARegister);
  202. Scripting.RegisterScriptFunction('GetImageSize',@GenericScriptFunction,ARegister);
  203. Scripting.RegisterScriptFunction('PutImage',@ScriptPutImage,ARegister);
  204. Scripting.RegisterScriptFunction('GetImage',@ScriptGetImage,ARegister);
  205. Scripting.RegisterScriptFunction('LayerFill',@ScriptLayerFill,ARegister);
  206. end;
  207. constructor TImageActions.Create(AInstance: TLazPaintCustomInstance);
  208. begin
  209. FInstance := AInstance;
  210. RegisterScripts(True);
  211. end;
  212. destructor TImageActions.Destroy;
  213. begin
  214. RegisterScripts(False);
  215. inherited Destroy;
  216. end;
  217. function TImageActions.GenericScriptFunction(AVars: TVariableSet): TScriptResult;
  218. var f: string;
  219. begin
  220. result := srOk;
  221. f := AVars.FunctionName;
  222. //for script purposes, Image always means the whole picture and Selection the selection
  223. if f = 'ImageHorizontalFlip' then HorizontalFlip(foWholePicture) else
  224. if f = 'ImageVerticalFlip' then VerticalFlip(foWholePicture) else
  225. if f = 'SelectionHorizontalFlip' then HorizontalFlip(foSelection) else
  226. if f = 'SelectionVerticalFlip' then VerticalFlip(foSelection) else
  227. //those script functions are the same as the menu actions
  228. if f = 'ImageSmartZoom3' then SmartZoom3 else
  229. if f = 'ImageCropLayer' then CropToSelectionAndLayer else
  230. if f = 'ImageCrop' then CropToSelection else
  231. if f = 'ImageFlatten' then Flatten else
  232. if f = 'ImageRotateCW' then RotateCW else
  233. if f = 'ImageRotateCCW' then RotateCCW else
  234. if f = 'ImageRotate180' then Rotate180 else
  235. if f = 'ImageLinearNegative' then LinearNegativeAll else
  236. if f = 'ImageNegative' then NegativeAll else
  237. if f = 'ImageSwapRedBlue' then SwapRedBlueAll else
  238. if f = 'EditUndo' then Undo else
  239. if f = 'EditRedo' then Redo else
  240. if f = 'EditDoBegin' then DoBegin else
  241. if f = 'EditDoEnd' then AVars.Booleans['Result'] := DoEnd else
  242. if f = 'EditInvertSelection' then InvertSelection else
  243. if f = 'EditDeselect' then Deselect else
  244. if f = 'EditCopy' then CopySelection else
  245. if f = 'EditCut' then CutSelection else
  246. if f = 'EditDeleteSelection' then DeleteSelection else
  247. if f = 'EditPaste' then Paste else
  248. if f = 'EditSelectAll' then SelectAll else
  249. if f = 'EditSelectionFit' then SelectionFit else
  250. if f = 'IsSelectionMaskEmpty' then AVars.Booleans['Result'] := Image.SelectionMaskEmpty else
  251. if f = 'IsSelectionLayerEmpty' then AVars.Booleans['Result'] := Image.SelectionLayerIsEmpty else
  252. if f = 'IsLayerEmpty' then AVars.Booleans['Result'] := Image.CurrentLayerEmpty else
  253. if f = 'IsLayerTransparent' then AVars.Booleans['Result'] := Image.CurrentLayerTransparent else
  254. if f = 'LayerHorizontalFlip' then HorizontalFlip(foCurrentLayer) else
  255. if f = 'LayerVerticalFlip' then VerticalFlip(foCurrentLayer) else
  256. if f = 'LayerGetName' then AVars.Strings['Result'] := Image.LayerName[Image.CurrentLayerIndex] else
  257. if f = 'LayerGetOpacity' then AVars.Integers['Result'] := Image.LayerOpacity[Image.CurrentLayerIndex] else
  258. if f = 'LayerGetBlendOp' then AVars.Strings['Result'] := BlendOperationStr[Image.BlendOperation[Image.CurrentLayerIndex]] else
  259. if f = 'LayerGetVisible' then AVars.Booleans['Result'] := Image.LayerVisible[Image.CurrentLayerIndex] else
  260. if f = 'LayerSetName' then Image.LayerName[Image.CurrentLayerIndex] := AVars.Strings['Name'] else
  261. if f = 'LayerSetOpacity' then Image.LayerOpacity[Image.CurrentLayerIndex] := min(255, max(0, AVars.Integers['Opacity'])) else
  262. if f = 'LayerSetBlendOp' then Image.BlendOperation[Image.CurrentLayerIndex] := StrToBlendOperation(AVars.Strings['BlendOp']) else
  263. if f = 'LayerSetVisible' then Image.LayerVisible[Image.CurrentLayerIndex] := AVars.Booleans['Visible'] else
  264. if f = 'LayerRasterize' then RasterizeLayer else
  265. if f = 'LayerMergeOver' then MergeLayerOver else
  266. if f = 'LayerRemoveCurrent' then begin if not RemoveLayer then result := srException end else
  267. if f = 'GetLayerCount' then AVars.Integers['Result']:= Image.NbLayers else
  268. if f = 'GetFrameCount' then AVars.Integers['Result']:= Image.FrameCount else
  269. if f = 'GetPixel' then AVars.Pixels['Result']:= GetPixel(AVars.Integers['X'],AVars.Integers['Y']) else
  270. if f = 'GetImageSize' then AVars.Points2D['Result']:= PointF(Image.Width,Image.Height) else
  271. if f = 'GetImageWidth' then AVars.Integers['Result']:= Image.Width else
  272. if f = 'GetImageHeight' then AVars.Integers['Result']:= Image.Height else
  273. result := srFunctionNotDefined;
  274. end;
  275. function TImageActions.ScriptGetAllLayersId(AVars: TVariableSet): TScriptResult;
  276. var
  277. idList: TScriptVariableReference;
  278. i: Integer;
  279. begin
  280. idList := AVars.AddGuidList('Result');
  281. for i := 0 to Image.NbLayers-1 do
  282. if not AVars.AppendGuid(idList, Image.LayerGuid[i]) then
  283. exit(srException);
  284. result := srOk;
  285. end;
  286. function TImageActions.ScriptGetLayerIndex(AVars: TVariableSet): TScriptResult;
  287. var
  288. idx: Integer;
  289. layerGuid: TGUID;
  290. begin
  291. if AVars.IsDefined('LayerId') then
  292. begin
  293. if not TryStringToGUID('{'+AVars.Strings['LayerId']+'}', layerGuid) then
  294. exit(srInvalidParameters);
  295. idx := Image.GetLayerIndexByGuid(layerGuid);
  296. if idx <> -1 then
  297. AVars.Integers['Result']:= idx+1
  298. else
  299. AVars.Remove('Result');
  300. end else
  301. AVars.Integers['Result']:= Image.CurrentLayerIndex+1;
  302. result := srOk;
  303. end;
  304. function TImageActions.ScriptImageMoveLayerIndex(AVars: TVariableSet): TScriptResult;
  305. begin
  306. try
  307. Image.MoveLayer(AVars.Integers['FromIndex']-1, AVars.Integers['ToIndex']-1);
  308. result := srOk;
  309. except
  310. on ex:exception do
  311. result := srException;
  312. end;
  313. end;
  314. function TImageActions.ScriptLayerFromFile(AVars: TVariableSet): TScriptResult;
  315. var
  316. ids: ArrayOfLayerId;
  317. i: Integer;
  318. guidList: TScriptVariableReference;
  319. begin
  320. if not AVars.IsDefined('FileName') then exit(srInvalidParameters) else
  321. begin
  322. ids := TryAddLayerFromFile(AVars.Strings['FileName']);
  323. if length(ids) = 0 then exit(srException) else
  324. begin
  325. if not AVars.IgnoreResult then
  326. begin
  327. guidList := AVars.AddGuidList('Result');
  328. for i := 0 to high(ids) do
  329. AVars.AppendGuid(guidList, Image.LayerGuid[Image.GetLayerIndexById(ids[i])]);
  330. end;
  331. exit(srOk);
  332. end;
  333. end;
  334. end;
  335. function TImageActions.ScriptImageGetRegistry(AVars: TVariableSet): TScriptResult;
  336. var
  337. identifier: String;
  338. begin
  339. identifier := AVars.Strings['Identifier'];
  340. if length(identifier)=0 then exit(srInvalidParameters);
  341. AVars.Strings['Result'] := Image.GetRegistry(identifier);
  342. result := srOk;
  343. end;
  344. function TImageActions.ScriptLayerGetId(AVars: TVariableSet): TScriptResult;
  345. begin
  346. AVars.Guids['Result'] := Image.LayerGuid[Image.CurrentLayerIndex];
  347. result := srOk;
  348. end;
  349. function TImageActions.ScriptLayerGetRegistry(AVars: TVariableSet): TScriptResult;
  350. var
  351. identifier: String;
  352. begin
  353. identifier := AVars.Strings['Identifier'];
  354. if length(identifier)=0 then exit(srInvalidParameters);
  355. AVars.Strings['Result'] := Image.GetLayerRegistry(Image.CurrentLayerIndex, identifier);
  356. result := srOk;
  357. end;
  358. function TImageActions.ScriptLayerSaveAs(AVars: TVariableSet): TScriptResult;
  359. var
  360. name, ext: String;
  361. layerCopy: TBGRABitmap;
  362. layerIdx, origIdx: Integer;
  363. writer: TFPCustomImageWriter;
  364. imgFormat, imgFormatFromName: TBGRAImageFormat;
  365. streamOut: TStream;
  366. layeredCopy: TBGRALayeredBitmap;
  367. begin
  368. name := AVars.Strings['FileName'];
  369. imgFormatFromName := SuggestImageFormat(name);
  370. if AVars.Strings['Format'] = '' then
  371. imgFormat := imgFormatFromName
  372. else
  373. imgFormat := SuggestImageFormat(AVars.Strings['Format']);
  374. ext := UTF8LowerCase(ExtractFileExt(name));
  375. if imgFormat = ifUnknown then
  376. begin
  377. if ext = '.tmp' then
  378. imgFormat := ifPng
  379. else
  380. exit(srInvalidParameters);
  381. end;
  382. //wont overwrite a file that is probably not an image
  383. if FileManager.FileExists(name) and (imgFormatFromName = ifUnknown) then
  384. exit(srInvalidParameters);
  385. streamOut := FileManager.CreateFileStream(name, fmCreate);
  386. try
  387. layerIdx := Image.CurrentLayerIndex;
  388. if imgFormatFromName in[ifLazPaint, ifPhoxo, ifSvg, ifOpenRaster] then
  389. begin
  390. layeredCopy := TBGRALayeredBitmap.Create(Image.Width,Image.Height);
  391. try
  392. if Image.LayerOriginalDefined[layerIdx] and Image.LayerOriginalKnown[layerIdx] then
  393. begin
  394. origIdx := layeredCopy.AddOriginal(Image.LayerOriginal[layerIdx], false);
  395. layeredCopy.AddLayerFromOriginal(layeredCopy.Original[origIdx].Guid,
  396. Image.LayerOriginalMatrix[layerIdx], Image.BlendOperation[layerIdx],
  397. Image.LayerOpacity[layerIdx]);
  398. layeredCopy.LayerName[0] := Image.LayerName[layerIdx];
  399. end;
  400. layeredCopy.RenderOriginalsIfNecessary;
  401. layeredCopy.SaveToStreamAs(streamOut, SuggestImageExtension(imgFormat));
  402. finally
  403. layeredCopy.Free;
  404. end;
  405. end else
  406. begin
  407. layerCopy := TBGRABitmap.Create(Image.Width, Image.Height);
  408. layerCopy.FillTransparent;
  409. writer := CreateBGRAImageWriter(imgFormat, true);
  410. try
  411. layerCopy.PutImage(Image.LayerOffset[layerIdx].x, Image.LayerOffset[layerIdx].y,
  412. Image.LayerBitmap[layerIdx], dmSet);
  413. layerCopy.SaveToStream(streamOut, writer);
  414. result := srOk;
  415. AVars.Strings['Result'] := name;
  416. except
  417. on ex: Exception do
  418. begin
  419. FInstance.ShowError(rsSave, ex.Message);
  420. result := srException;
  421. end;
  422. end;
  423. layerCopy.Free;
  424. writer.Free;
  425. end;
  426. finally
  427. streamOut.Free;
  428. end;
  429. end;
  430. function TImageActions.ScriptLayerSelectId(AVars: TVariableSet): TScriptResult;
  431. var
  432. idx: Integer;
  433. layerGuid: TGUID;
  434. begin
  435. layerGuid := AVars.Guids['Id'];
  436. if layerGuid = GUID_NULL then exit(srInvalidParameters);
  437. idx := Image.GetLayerIndexByGuid(layerGuid);
  438. if idx = -1 then exit(srInvalidParameters)
  439. else if not Image.SetCurrentLayerByIndex(idx) then exit(srException)
  440. else exit(srOk);
  441. end;
  442. function TImageActions.ScriptLayerAddNew(AVars: TVariableSet): TScriptResult;
  443. begin
  444. if not NewLayer then result := srException
  445. else
  446. begin
  447. if not AVars.IgnoreResult then
  448. AVars.Guids['Result'] := Image.LayerGuid[Image.CurrentLayerIndex];
  449. result := srOk;
  450. end;
  451. end;
  452. function TImageActions.ScriptImageSetRegistry(AVars: TVariableSet): TScriptResult;
  453. var
  454. identifier: String;
  455. begin
  456. identifier := AVars.Strings['Identifier'];
  457. if length(identifier)=0 then exit(srInvalidParameters);
  458. if not AVars.IsDefined('Value') then exit(srInvalidParameters);
  459. Image.SetRegistry(identifier, AVars.Strings['Value']);
  460. result := srOk;
  461. end;
  462. function TImageActions.ScriptLayerSetRegistry(AVars: TVariableSet): TScriptResult;
  463. var
  464. identifier: String;
  465. begin
  466. identifier := AVars.Strings['Identifier'];
  467. if length(identifier)=0 then exit(srInvalidParameters);
  468. if not AVars.IsDefined('Value') then exit(srInvalidParameters);
  469. Image.SetLayerRegistry(Image.CurrentLayerIndex, identifier, AVars.Strings['Value']);
  470. result := srOk;
  471. end;
  472. function TImageActions.ScriptPasteAsNewLayer(AVars: TVariableSet): TScriptResult;
  473. var
  474. id, idx: Integer;
  475. begin
  476. id := PasteAsNewLayer;
  477. if (id >= 0) and not AVars.IgnoreResult then
  478. begin
  479. idx := Image.GetLayerIndexById(id);
  480. AVars.Guids['Result'] := Image.LayerGuid[idx];
  481. end
  482. else AVars.Remove('Result');
  483. result := srOk;
  484. end;
  485. function TImageActions.ScriptLayerDuplicate(AVars: TVariableSet): TScriptResult;
  486. begin
  487. if not DuplicateLayer then result := srException else
  488. begin
  489. if not AVars.IgnoreResult then
  490. AVars.Guids['Result'] := Image.LayerGuid[Image.CurrentLayerIndex];
  491. result := srOk;
  492. end;
  493. end;
  494. function TImageActions.ScriptPutImage(AVars: TVariableSet): TScriptResult;
  495. var
  496. x, y, width, height, opacity, yb, dataPos, xb: integer;
  497. dataStr, modeStr: String;
  498. mode: TDrawMode;
  499. bmp: TBGRABitmap;
  500. p: PBGRAPixel;
  501. function HexDigit(APos: integer): byte;
  502. begin
  503. result := ord(dataStr[APos]);
  504. if result < ord('0') then result := 0
  505. else if result <= ord('9') then dec(result, ord('0'))
  506. else if result < ord('A') then result := 9
  507. else if result <= ord('F') then result := result - ord('A') + 10
  508. else result := 15;
  509. end;
  510. function HexValue(APos: integer): byte;
  511. begin
  512. result := (HexDigit(APos) shl 4) + HexDigit(APos+1);
  513. end;
  514. begin
  515. x := AVars.Integers['X'];
  516. y := AVars.Integers['Y'];
  517. width := AVars.Integers['Width'];
  518. height := AVars.Integers['Height'];
  519. dataStr := AVars.Strings['Data'];
  520. modeStr := AVars.Strings['Mode'];
  521. opacity := AVars.Integers['Opacity'];
  522. case modeStr of
  523. 'dmDrawWithTransparency': mode := dmDrawWithTransparency;
  524. 'dmLinearBlend': mode := dmLinearBlend;
  525. 'dmSet': mode := dmSet;
  526. 'dmSetExceptTransparent': mode := dmSetExceptTransparent;
  527. 'dmXor': mode := dmXor;
  528. else exit(srInvalidParameters);
  529. end;
  530. if (opacity < 0) or (opacity > 255) then exit(srInvalidParameters);
  531. if length(dataStr)<>width*height*8 then exit(srInvalidParameters);
  532. if (width = 0) or (height = 0) then exit(srOk);
  533. if opacity = 0 then exit(srOk);
  534. bmp := TBGRABitmap.Create(width,height);
  535. try
  536. dataPos := 1;
  537. for yb := 0 to height-1 do
  538. begin
  539. p := bmp.ScanLine[yb];
  540. for xb := 0 to width-1 do
  541. begin
  542. p^.alpha := HexValue(dataPos+6);
  543. if p^.alpha = 0 then p^ := BGRAPixelTransparent
  544. else
  545. begin
  546. p^.red := HexValue(dataPos);
  547. p^.green := HexValue(dataPos+2);
  548. p^.blue := HexValue(dataPos+4);
  549. end;
  550. inc(dataPos,8);
  551. inc(p);
  552. end;
  553. end;
  554. bmp.InvalidateBitmap;
  555. if PutImage(x,y,bmp,mode,opacity) then
  556. begin
  557. result := srOk;
  558. FInstance.UpdateWindows;
  559. end
  560. else
  561. result := srException;
  562. finally
  563. bmp.Free;
  564. end;
  565. end;
  566. function TImageActions.ScriptGetImage(AVars: TVariableSet): TScriptResult;
  567. var
  568. str: string;
  569. strPos: integer;
  570. procedure writeStrHex(AValue: byte);
  571. const digits : array[0..15] of char = '0123456789ABCDEF';
  572. begin
  573. str[strPos] := digits[AValue shr 4];
  574. str[strPos+1] := digits[AValue and 15];
  575. inc(strPos, 2);
  576. end;
  577. var
  578. x, y, width, height, yb, xb: Integer;
  579. copy, img: TBGRABitmap;
  580. ofs: TPoint;
  581. p: PBGRAPixel;
  582. begin
  583. if not AVars.IsDefined('X') then
  584. x := 0 else x := AVars.Integers['X'];
  585. if not AVars.IsDefined('Y') then
  586. y := 0 else y := AVars.Integers['Y'];
  587. if not AVars.IsDefined('Width') then
  588. width := Image.Width-x else width := AVars.Integers['Width'];
  589. if not AVars.IsDefined('Height') then
  590. height := Image.Height-y else height := AVars.Integers['Height'];
  591. if (width > MaxImageWidth) or (height > MaxImageHeight) then exit(srException);
  592. if Image.SelectionLayerIsEmpty then
  593. begin
  594. copy := TBGRABitmap.Create(width, height);
  595. ofs := Image.LayerOffset[Image.CurrentLayerIndex];
  596. copy.PutImage(ofs.X, ofs.Y, Image.LayerBitmap[Image.CurrentLayerIndex], dmSet);
  597. img := copy
  598. end else
  599. begin
  600. copy := nil;
  601. img := Image.SelectionLayerReadonly;
  602. end;
  603. try
  604. str := '';
  605. setlength(str, img.width*img.height*8);
  606. strPos := 1;
  607. for yb := 0 to img.Height-1 do
  608. begin
  609. p := img.ScanLine[yb];
  610. for xb := img.Width-1 downto 0 do
  611. begin
  612. writeStrHex(p^.red);
  613. writeStrHex(p^.green);
  614. writeStrHex(p^.blue);
  615. writeStrHex(p^.alpha);
  616. inc(p);
  617. end;
  618. end;
  619. finally
  620. copy.Free;
  621. end;
  622. AVars.Strings['Result'] := str;
  623. result := srOk;
  624. end;
  625. function TImageActions.ScriptLayerFill(AVars: TVariableSet): TScriptResult;
  626. var
  627. modeStr: String;
  628. mode: TDrawMode;
  629. begin
  630. modeStr := AVars.Strings['Mode'];
  631. case modeStr of
  632. 'dmDrawWithTransparency': mode := dmDrawWithTransparency;
  633. 'dmLinearBlend': mode := dmLinearBlend;
  634. 'dmSet': mode := dmSet;
  635. 'dmSetExceptTransparent': mode := dmSetExceptTransparent;
  636. 'dmXor': mode := dmXor;
  637. else exit(srInvalidParameters);
  638. end;
  639. if LayerFill(AVars.Pixels['Color'], mode) then
  640. begin
  641. result := srOk;
  642. FInstance.UpdateWindows;
  643. end
  644. else
  645. result := srException;
  646. end;
  647. function TImageActions.ScriptGetFrameIndex(AVars: TVariableSet): TScriptResult;
  648. begin
  649. if Image.FrameIndex <> -1 then
  650. AVars.Integers['Result']:= Image.FrameIndex+1
  651. else
  652. AVars.Remove('Result');
  653. result := srOk;
  654. end;
  655. procedure TImageActions.ClearAlpha;
  656. var
  657. c: TBGRAPixel;
  658. begin
  659. c := ToolManager.BackColor;
  660. c.alpha := 255;
  661. ClearAlpha(c);
  662. end;
  663. procedure TImageActions.FillBackground;
  664. var
  665. c: TBGRAPixel;
  666. begin
  667. c := ToolManager.BackColor;
  668. c.alpha := 255;
  669. FillBackground(c);
  670. end;
  671. procedure TImageActions.ClearAlpha(AColor: TBGRAPixel);
  672. var n: integer;
  673. p: PBGRAPixel;
  674. LayerAction: TLayerAction;
  675. begin
  676. if not Image.CheckNoAction then exit;
  677. LayerAction := nil;
  678. try
  679. LayerAction := Image.CreateAction(true);
  680. LayerAction.SelectedImageLayer.ReplaceColor(BGRAPixelTransparent, AColor);
  681. p := LayerAction.SelectedImageLayer.Data;
  682. for n := LayerAction.SelectedImageLayer.NbPixels-1 downto 0 do
  683. begin
  684. p^.alpha := 255;
  685. inc(p);
  686. end;
  687. LayerAction.SelectedImageLayer.InvalidateBitmap;
  688. Image.LayerMayChangeCompletely(LayerAction.SelectedImageLayer);
  689. LayerAction.Validate;
  690. except
  691. on ex:Exception do
  692. FInstance.ShowError('ClearAlpha',ex.Message);
  693. end;
  694. LayerAction.Free;
  695. end;
  696. procedure TImageActions.FillBackground(AColor: TBGRAPixel);
  697. var tempBmp: TBGRABitmap;
  698. LayerAction: TLayerAction;
  699. y: Integer;
  700. orig: TVectorOriginal;
  701. ab: TAffineBox;
  702. backRect: TRectShape;
  703. begin
  704. if not Image.CheckNoAction then exit;
  705. LayerAction := nil;
  706. try
  707. if Image.LayerOriginalClass[Image.CurrentLayerIndex] = TVectorOriginal then
  708. begin
  709. Image.CurrentState.DiscardOriginalDiff := false;
  710. try
  711. orig := Image.LayerOriginal[Image.CurrentLayerIndex] as TVectorOriginal;
  712. backRect := TRectShape.Create(nil);
  713. ab := AffineMatrixInverse(Image.LayerOriginalMatrix[Image.CurrentLayerIndex]) *
  714. TAffineBox.AffineBox(rectF(-0.5, -0.5, Image.Width-0.5, Image.Height-0.5));
  715. backRect.Origin := ab.Center;
  716. backRect.XAxis := backRect.Origin + (ab.TopRight - ab.TopLeft)*0.5;
  717. backRect.YAxis := backRect.Origin + (ab.BottomLeft - ab.TopLeft)*0.5;
  718. backRect.BackFill.SolidColor := AColor;
  719. orig.InsertShape(backRect, 0);
  720. finally
  721. Image.CurrentState.DiscardOriginalDiff := true;
  722. end;
  723. end else
  724. begin
  725. LayerAction := Image.CreateAction(True);
  726. tempBmp := TBGRABitmap.Create(LayerAction.SelectedImageLayer.Width,1);
  727. for y := 0 to LayerAction.SelectedImageLayer.Height-1 do
  728. begin
  729. tempBmp.Fill(AColor);
  730. tempBmp.PutImage(0,-y,LayerAction.SelectedImageLayer,dmDrawWithTransparency);
  731. LayerAction.SelectedImageLayer.PutImage(0,y,tempBmp,dmSet);
  732. end;
  733. tempBmp.Free;
  734. image.LayerMayChangeCompletely(LayerAction.SelectedImageLayer);
  735. LayerAction.Validate;
  736. end;
  737. except
  738. on ex:Exception do
  739. FInstance.ShowError('FillBackground',ex.Message);
  740. end;
  741. LayerAction.Free;
  742. end;
  743. function TImageActions.SmartZoom3: boolean;
  744. begin
  745. result := false;
  746. if (image.Width * 3 > MaxImageWidth) or
  747. (image.Height * 3 > MaxImageHeight) then
  748. begin
  749. FInstance.ShowMessage(rsLazPaint,rsImageTooBig);
  750. exit;
  751. end;
  752. ChooseTool(ptHand);
  753. try
  754. image.ApplySmartZoom3;
  755. result := true;
  756. except
  757. on ex:Exception do
  758. FInstance.ShowError('SmartZoom3',ex.Message);
  759. end;
  760. end;
  761. procedure TImageActions.Undo;
  762. var
  763. prevTool: TPaintToolType;
  764. begin
  765. try
  766. prevTool := CurrentTool;
  767. if CurrentTool in[ptMoveSelection,ptRotateSelection] then ChooseTool(ptHand);
  768. if ToolManager.ToolProvideCommand(tcFinish) then ToolManager.ToolCommand(tcFinish);
  769. if image.CanUndo then
  770. begin
  771. ToolManager.ToolCloseDontReopen;
  772. image.Undo;
  773. ToolManager.ToolOpen;
  774. end;
  775. if (prevTool in[ptMoveSelection,ptRotateSelection]) and
  776. not image.SelectionMaskEmpty then
  777. ChooseTool(prevTool, false);
  778. except
  779. on ex:Exception do
  780. FInstance.ShowError('Undo',ex.Message);
  781. end;
  782. end;
  783. procedure TImageActions.Redo;
  784. var
  785. prevTool: TPaintToolType;
  786. begin
  787. try
  788. prevTool := CurrentTool;
  789. if CurrentTool in[ptLayerMapping,ptMoveSelection,ptRotateSelection] then
  790. ChooseTool(ptHand);
  791. if image.CanRedo then
  792. begin
  793. ToolManager.ToolCloseDontReopen;
  794. image.Redo;
  795. ToolManager.ToolOpen;
  796. end;
  797. if (prevTool in[ptMoveSelection,ptRotateSelection]) and
  798. not image.SelectionMaskEmpty then
  799. ChooseTool(prevTool, false);
  800. except
  801. on ex:Exception do
  802. FInstance.ShowError('Redo',ex.Message);
  803. end;
  804. end;
  805. procedure TImageActions.DoBegin;
  806. begin
  807. if CurrentTool in[ptMoveSelection,ptRotateSelection] then ChooseTool(ptHand);
  808. if ToolManager.ToolProvideCommand(tcFinish) then ToolManager.ToolCommand(tcFinish);
  809. Image.DoBegin;
  810. end;
  811. function TImageActions.DoEnd: boolean;
  812. var
  813. found: boolean;
  814. begin
  815. if CurrentTool in[ptMoveSelection,ptRotateSelection] then ChooseTool(ptHand);
  816. if ToolManager.ToolProvideCommand(tcFinish) then ToolManager.ToolCommand(tcFinish);
  817. Image.DoEnd(found, result);
  818. if not found then raise exception.Create(rsEndWithoutMatchingBegin);
  819. end;
  820. procedure TImageActions.Import3DObject(AFilenameUTF8: string);
  821. var image3D: TBGRABitmap;
  822. begin
  823. try
  824. image3D := ShowObject3DDlg(FInstance, AFileNameUTF8, Image.Width, Image.Height);
  825. if image3D <> nil then
  826. begin
  827. if image3D.NbPixels <> 0 then
  828. NewLayer(image3d, ExtractFileName(AFilenameUTF8), boTransparent)
  829. else
  830. image3D.Free;
  831. end;
  832. except
  833. on ex:Exception do
  834. FInstance.ShowError('Import3DObject',ex.Message);
  835. end;
  836. end;
  837. function TImageActions.GetPixel(X, Y: Integer): TBGRAPixel;
  838. var
  839. ofs: TPoint;
  840. begin
  841. ofs := Image.LayerOffset[Image.CurrentLayerIndex];
  842. result := Image.LayerBitmap[Image.CurrentLayerIndex].GetPixel(X-ofs.X,y-ofs.Y);
  843. end;
  844. function TImageActions.PutImage(X, Y: integer; AImage: TBGRACustomBitmap;
  845. AMode: TDrawMode; AOpacity: byte): boolean;
  846. var
  847. LayerAction: TLayerAction;
  848. begin
  849. result := false;
  850. if not Image.CheckNoAction then exit;
  851. LayerAction := nil;
  852. try
  853. LayerAction := Image.CreateAction(true);
  854. LayerAction.ChangeBoundsNotified:= true;
  855. LayerAction.SelectedImageLayer.PutImage(X,Y,AImage,AMode,AOpacity);
  856. LayerAction.NotifyChange(LayerAction.SelectedImageLayer, RectWithSize(X,Y,AImage.Width,AImage.Height));
  857. LayerAction.Validate;
  858. result := true;
  859. except
  860. on ex:Exception do
  861. FInstance.ShowError('PutImage',ex.Message);
  862. end;
  863. LayerAction.Free;
  864. end;
  865. function TImageActions.LayerFill(AColor: TBGRAPixel; AMode: TDrawMode): boolean;
  866. var
  867. LayerAction: TLayerAction;
  868. begin
  869. if (AColor.alpha=0) and (AMode in[dmDrawWithTransparency,dmLinearBlend]) then exit(true);
  870. result := false;
  871. if not Image.CheckNoAction then exit;
  872. LayerAction := nil;
  873. try
  874. LayerAction := Image.CreateAction(true);
  875. LayerAction.ChangeBoundsNotified:= true;
  876. LayerAction.SelectedImageLayer.Fill(AColor, AMode);
  877. LayerAction.NotifyChange(LayerAction.SelectedImageLayer,
  878. rect(0,0,LayerAction.SelectedImageLayer.Width,
  879. LayerAction.SelectedImageLayer.Height));
  880. LayerAction.Validate;
  881. result := true;
  882. except
  883. on ex:Exception do
  884. FInstance.ShowError('LayerFill',ex.Message);
  885. end;
  886. LayerAction.Free;
  887. end;
  888. function TImageActions.LoadSelection(AFilenameUTF8: string; ALoadedImage: PImageEntry = nil): boolean;
  889. var
  890. newSelection: TBGRABitmap;
  891. LayerAction: TLayerAction;
  892. begin
  893. LayerAction := nil;
  894. result := false;
  895. try
  896. if Assigned(ALoadedImage) and Assigned(ALoadedImage^.bmp) then
  897. begin
  898. newSelection := ALoadedImage^.bmp;
  899. ALoadedImage^.Release;
  900. end
  901. else
  902. newSelection := LoadFlatImageUTF8(AFilenameUTF8).bmp;
  903. newSelection.InplaceGrayscale;
  904. if not (CurrentTool in[ptDeformation,ptLayerMapping,ptMoveSelection,ptRotateSelection]) then
  905. ChooseTool(ptMoveSelection);
  906. if Image.CheckNoAction then
  907. begin
  908. LayerAction := Image.CreateAction;
  909. LayerAction.RemoveSelection;
  910. LayerAction.QuerySelection;
  911. LayerAction.CurrentSelection.PutImage(0,0,newSelection,dmSet);
  912. LayerAction.NotifyChange(Image.SelectionMask,rect(0,0,newSelection.Width,newSelection.Height));
  913. LayerAction.Validate;
  914. result := true;
  915. end;
  916. except
  917. on ex: exception do
  918. FInstance.ShowError('LoadSelection',ex.Message);
  919. end;
  920. FreeAndNil(newSelection);
  921. LayerAction.Free;
  922. end;
  923. procedure TImageActions.CropToSelectionAndLayer;
  924. var partial: TBGRABitmap; r: TRect; top: TTopMostInfo;
  925. begin
  926. if not image.CheckNoAction then exit;
  927. if not image.CheckCurrentLayerVisible then exit;
  928. try
  929. if image.SelectionMaskEmpty then
  930. begin
  931. FInstance.ShowMessage(rsCrop, rsEmptySelection);
  932. exit;
  933. end;
  934. if (CurrentTool in[ptRotateSelection,ptMoveSelection,ptDeformation,ptLayerMapping]) then
  935. ChooseTool(ptHand);
  936. partial := image.MakeCroppedLayer;
  937. if partial <> nil then
  938. begin
  939. r := partial.GetImageBounds;
  940. if (r.right > r.left) and (r.bottom > r.top) then
  941. begin
  942. if (r.left <> 0) or (r.top <> 0) or
  943. (r.right <> partial.width) or (r.bottom <> partial.height) then
  944. begin
  945. top := FInstance.HideTopmost;
  946. case MessageDlg(rsCrop,rsKeepEmptySpace,mtConfirmation,mbYesNo,0) of
  947. mrNo: BGRAReplace(partial, partial.GetPart(r));
  948. end;
  949. FInstance.ShowTopmost(top);
  950. end;
  951. SetCurrentBitmap(partial,true,image.LayerName[image.CurrentLayerIndex],image.LayerOpacity[image.CurrentLayerIndex]);
  952. end
  953. else
  954. partial.Free;
  955. end;
  956. except
  957. on ex:Exception do
  958. FInstance.ShowError('CropToSelectionAndLayer',ex.Message);
  959. end;
  960. end;
  961. procedure TImageActions.CropToSelection;
  962. var cropped: TLayeredBitmapAndSelection;
  963. r, subBounds: TRect;
  964. i,selectedLayer: integer;
  965. ofs: TPoint;
  966. tempLayer, flattened: TBGRABitmap;
  967. selectionIsRect: Boolean;
  968. top: TTopMostInfo;
  969. begin
  970. if not image.CheckNoAction then exit;
  971. try
  972. if image.SelectionMaskEmpty then
  973. begin
  974. FInstance.ShowMessage(rsCrop,rsEmptySelection);
  975. exit;
  976. end;
  977. if not image.SelectionMaskEmpty then
  978. begin
  979. r := image.SelectionMaskBounds;
  980. if (r.left = 0) and (r.Top = 0) and (r.right = image.width) and (r.Bottom =image.height) then exit;
  981. cropped := image.MakeLayeredBitmapAndSelectionCopy;
  982. BGRAReplace(cropped.selection,cropped.selection.GetPart(r));
  983. selectionIsRect := cropped.selection.Equals(BGRAWhite);
  984. if cropped.selectionLayer <> nil then BGRAReplace(cropped.selectionLayer,cropped.selectionLayer.GetPart(r));
  985. selectedLayer := image.CurrentLayerIndex;
  986. for i := 0 to cropped.layeredBitmap.NbLayers-1 do
  987. begin
  988. tempLayer := TBGRABitmap.Create(r.Width,r.Height);
  989. if selectionIsRect and (cropped.layeredBitmap.LayerOriginalGuid[i]<>GUID_NULL) and
  990. cropped.layeredBitmap.LayerOriginalKnown[i] then
  991. begin
  992. ofs := cropped.layeredBitmap.LayerOffset[i];
  993. cropped.layeredBitmap.LayerOriginalMatrix[i] :=
  994. AffineMatrixTranslation(-r.Left, -r.Top)*
  995. cropped.layeredBitmap.LayerOriginalMatrix[i];
  996. cropped.layeredBitmap.RenderLayerFromOriginal(i);
  997. end else
  998. begin
  999. ofs := cropped.layeredBitmap.LayerOffset[i];
  1000. tempLayer.PutImage(ofs.x-r.Left,ofs.y-r.Top, cropped.layeredBitmap.LayerBitmap[i], dmSet);
  1001. tempLayer.ApplyMask(cropped.selection);
  1002. cropped.layeredBitmap.SetLayerBitmap(i, tempLayer, true);
  1003. cropped.layeredBitmap.LayerOffset[i] := Point(0,0);
  1004. end;
  1005. end;
  1006. if cropped.selectionLayer = nil then
  1007. begin
  1008. FreeAndNil(cropped.selection);
  1009. if (CurrentTool in [ptMoveSelection,ptRotateSelection]) then
  1010. ChooseTool(ptHand);
  1011. end;
  1012. cropped.layeredBitmap.SetSize(r.right-r.left,r.Bottom-r.top);
  1013. cropped.layeredBitmap.RemoveUnusedOriginals;
  1014. flattened := cropped.layeredBitmap.ComputeFlatImage;
  1015. subBounds := flattened.GetImageBounds;
  1016. flattened.Free;
  1017. if cropped.selectionLayer<>nil then
  1018. subBounds := RectUnion(subBounds, cropped.selectionLayer.GetImageBounds);
  1019. if (subBounds.Left > 0) or (subBounds.Top > 0) or
  1020. (subBounds.Right < cropped.layeredBitmap.Width) or (subBounds.Bottom < cropped.layeredBitmap.Height) then
  1021. begin
  1022. top := FInstance.HideTopmost;
  1023. case MessageDlg(rsCrop,rsKeepEmptySpace,mtConfirmation,mbYesNo,0) of
  1024. mrNo: begin
  1025. for i := 0 to cropped.layeredBitmap.NbLayers-1 do
  1026. begin
  1027. if cropped.layeredBitmap.LayerOriginalGuid[i]=GUID_NULL then
  1028. begin
  1029. ofs := cropped.layeredBitmap.LayerOffset[i];
  1030. cropped.layeredBitmap.LayerOffset[i] := Point(ofs.x-subBounds.Left,ofs.y-subBounds.Top);
  1031. end else
  1032. begin
  1033. cropped.layeredBitmap.LayerOriginalMatrix[i] :=
  1034. AffineMatrixTranslation(-subBounds.Left,-subBounds.Top)*
  1035. cropped.layeredBitmap.LayerOriginalMatrix[i];
  1036. cropped.layeredBitmap.RenderLayerFromOriginal(i);
  1037. end;
  1038. end;
  1039. cropped.layeredBitmap.SetSize(subBounds.Width, subBounds.Height);
  1040. end;
  1041. end;
  1042. FInstance.ShowTopmost(top);
  1043. end;
  1044. image.Assign(cropped,true,true);
  1045. image.SetCurrentLayerByIndex(selectedLayer);
  1046. end;
  1047. except
  1048. on ex:Exception do
  1049. FInstance.ShowError('CropToSelection',ex.Message);
  1050. end;
  1051. end;
  1052. procedure TImageActions.Flatten;
  1053. begin
  1054. ChooseTool(ptHand);
  1055. image.Flatten;
  1056. end;
  1057. procedure TImageActions.TakeScreenshot(ARect: TRect);
  1058. var
  1059. bmp: TBGRABitmap;
  1060. begin
  1061. bmp := TBGRABitmap.Create;
  1062. try
  1063. bmp.TakeScreenshot(ARect);
  1064. SetCurrentBitmap(bmp, false, 'Screenshot');
  1065. except on ex:Exception do
  1066. FInstance.ShowError('TakeScreenshot',ex.Message);
  1067. end;
  1068. end;
  1069. procedure TImageActions.SetCurrentBitmap(bmp: TBGRABitmap; AUndoable : boolean;
  1070. ACaption: string; AOpacity: byte);
  1071. begin
  1072. ToolManager.ToolCloseDontReopen;
  1073. try
  1074. image.Assign(bmp,True,AUndoable, ACaption,AOpacity);
  1075. finally
  1076. ToolManager.ToolOpen;
  1077. end;
  1078. end;
  1079. procedure TImageActions.SetCurrentBitmap(bmp: TBGRACustomLayeredBitmap;
  1080. AUndoable: boolean);
  1081. begin
  1082. ToolManager.ToolCloseDontReopen;
  1083. try
  1084. image.Assign(bmp,True,AUndoable);
  1085. finally
  1086. ToolManager.ToolOpen;
  1087. end;
  1088. end;
  1089. function TImageActions.TryAddLayerFromFile(AFilenameUTF8: string; ALoadedImage: TBGRABitmap = nil): ArrayOfLayerId;
  1090. function ComputeStretchMatrix(ASourceWidth, ASourceHeight: single): TAffineMatrix;
  1091. var
  1092. ratio: Single;
  1093. begin
  1094. ratio := max(ASourceWidth/Image.Width, ASourceHeight/Image.Height);
  1095. result := AffineMatrixTranslation(-ASourceWidth/2, -ASourceHeight/2);
  1096. if ratio > 1 then result := AffineMatrixScale(1/ratio, 1/ratio)*result;
  1097. result := AffineMatrixTranslation(Image.Width/2, Image.Height/2)*result;
  1098. end;
  1099. var
  1100. layeredBmp: TBGRACustomLayeredBitmap;
  1101. procedure ImportLayeredBmp;
  1102. var
  1103. m: TAffineMatrix;
  1104. i: Integer;
  1105. ofsF: TPointF;
  1106. bmpOrig: TBGRALayerImageOriginal;
  1107. doFound, somethingDone: boolean;
  1108. begin
  1109. m := ComputeStretchMatrix(layeredBmp.Width, layeredBmp.Height);
  1110. try
  1111. Image.DoBegin;
  1112. for i := 0 to layeredBmp.NbLayers-1 do
  1113. begin
  1114. if (layeredBmp.LayerOriginalGuid[i] <> GUID_NULL) and
  1115. layeredBmp.LayerOriginalKnown[i] then
  1116. begin
  1117. if not AddLayerFromOriginal(layeredBmp.LayerOriginal[i].Duplicate,
  1118. layeredBmp.LayerName[i], m*layeredBmp.LayerOriginalMatrix[i],
  1119. layeredBmp.BlendOperation[i], layeredBmp.LayerOpacity[i]) then break;
  1120. end else
  1121. begin
  1122. if IsAffineMatrixTranslation(m) then
  1123. begin
  1124. ofsF := m*PointF(layeredBmp.LayerOffset[i].x, layeredBmp.LayerOffset[i].y);
  1125. if not NewLayer(layeredBmp.GetLayerBitmapCopy(i), layeredBmp.LayerName[i],
  1126. Point(round(ofsF.X), round(ofsF.Y)),
  1127. layeredBmp.BlendOperation[i], layeredBmp.LayerOpacity[i]) then break;
  1128. end else
  1129. begin
  1130. bmpOrig := TBGRALayerImageOriginal.Create;
  1131. bmpOrig.AssignImage(layeredBmp.GetLayerBitmapDirectly(i));
  1132. if not AddLayerFromOriginal(bmpOrig, layeredBmp.LayerName[i],
  1133. m * AffineMatrixTranslation(layeredBmp.LayerOffset[i].x, layeredBmp.LayerOffset[i].y),
  1134. layeredBmp.BlendOperation[i], layeredBmp.LayerOpacity[i]) then break;
  1135. end;
  1136. end;
  1137. setlength(result, length(result)+1);
  1138. result[high(result)] := Image.LayerId[image.CurrentLayerIndex];
  1139. end;
  1140. finally
  1141. image.DoEnd(doFound, somethingDone);
  1142. end;
  1143. end;
  1144. var
  1145. imgFormat: TBGRAImageFormat;
  1146. s: TStream;
  1147. newPicture: TBGRABitmap;
  1148. flattened: TBGRABitmap;
  1149. ext: String;
  1150. begin
  1151. result := nil;
  1152. if not AbleToLoadUTF8(AFilenameUTF8) then
  1153. begin
  1154. FInstance.ShowMessage(rsOpen,rsFileExtensionNotSupported);
  1155. FreeAndNil(ALoadedImage);
  1156. exit;
  1157. end;
  1158. try
  1159. imgFormat := Image.DetectImageFormat(AFilenameUTF8);
  1160. case imgFormat of
  1161. ifLazPaint, ifOpenRaster, ifSvg, ifPaintDotNet, ifPhoxo:
  1162. begin
  1163. ext := UTF8LowerCase(ExtractFileExt(AFilenameUTF8));
  1164. layeredBmp := TryCreateLayeredBitmapReader(ext);
  1165. if layeredBmp is TBGRALayeredSVG then
  1166. with TBGRALayeredSVG(layeredBmp) do
  1167. begin
  1168. ContainerWidth := Image.Width;
  1169. ContainerHeight := Image.Height;
  1170. DPI:= Screen.PixelsPerInch;
  1171. DefaultLayerName:= rsLayer;
  1172. end;
  1173. try
  1174. s := FileManager.CreateFileStream(AFilenameUTF8, fmOpenRead or fmShareDenyWrite);
  1175. try
  1176. if Assigned(FInstance) then FInstance.StartLoadingImage(AFilenameUTF8);
  1177. try
  1178. layeredBmp.LoadFromStream(s);
  1179. finally
  1180. if Assigned(FInstance) then FInstance.EndLoadingImage;
  1181. end;
  1182. if layeredBmp.NbLayers > 1 then
  1183. begin
  1184. case QuestionDlg(rsOpen, AppendQuestionMark(rsFlattenImage), mtInformation,
  1185. [mrYes, rsYes, mrNo, rsNo, mrCancel, rsCancel], 0) of
  1186. mrYes: begin
  1187. flattened := layeredBmp.ComputeFlatImage;
  1188. FreeAndNil(layeredBmp);
  1189. layeredBmp:= TBGRALayeredBitmap.Create(flattened.Width, flattened.Height);
  1190. TBGRALayeredBitmap(layeredBmp).AddOwnedLayer(flattened);
  1191. ImportLayeredBmp;
  1192. end;
  1193. mrNo: ImportLayeredBmp;
  1194. end;
  1195. end else
  1196. ImportLayeredBmp;
  1197. finally
  1198. s.Free;
  1199. end;
  1200. finally
  1201. layeredBmp.Free;
  1202. end;
  1203. end
  1204. else
  1205. begin
  1206. if Assigned(ALoadedImage) then
  1207. begin
  1208. newPicture := ALoadedImage;
  1209. ALoadedImage := nil;
  1210. end
  1211. else
  1212. begin
  1213. if Assigned(FInstance) then FInstance.StartLoadingImage(AFilenameUTF8);
  1214. try
  1215. newPicture := LoadFlatImageUTF8(AFilenameUTF8).bmp;
  1216. finally
  1217. if Assigned(FInstance) then FInstance.EndLoadingImage;
  1218. end;
  1219. end;
  1220. AddLayerFromBitmap(newPicture, ExtractFileName(AFilenameUTF8));
  1221. setlength(result, 1);
  1222. result[0] := Image.LayerId[image.CurrentLayerIndex];
  1223. end;
  1224. end;
  1225. except
  1226. on ex: Exception do
  1227. begin
  1228. ALoadedImage.Free;
  1229. FInstance.ShowError('TryAddLayerFromFile',ex.Message);
  1230. end;
  1231. end;
  1232. end;
  1233. function TImageActions.AddLayerFromBitmap(ABitmap: TBGRABitmap; AName: string): boolean;
  1234. var
  1235. ratio: single;
  1236. xorMask: TBGRABitmap;
  1237. begin
  1238. if (ABitmap <> nil) and (ABitmap.Width > 0) and (ABitmap.Height > 0) then
  1239. begin
  1240. if CurrentTool in [ptDeformation,ptRotateSelection,ptMoveSelection,
  1241. ptLayerMapping,ptEditShape] then
  1242. ChooseTool(ptHand);
  1243. if image.CheckNoAction then
  1244. begin
  1245. if not Image.SelectionMaskEmpty then ReleaseSelection;
  1246. if (ABitmap.Width > Image.Width) or (ABitmap.Height > Image.Height) then
  1247. begin
  1248. ratio := 1;
  1249. if ABitmap.Width > Image.Width then ratio := Image.Width/ABitmap.Width;
  1250. if ABitmap.Height*ratio > Image.Height then ratio := Image.Height/ABitmap.Height;
  1251. ABitmap.ResampleFilter := rfBestQuality;
  1252. BGRAReplace(ABitmap, ABitmap.Resample(round(ABitmap.Width*ratio),round(ABitmap.Height*ratio)));
  1253. end;
  1254. if Assigned(ABitmap.XorMask) then
  1255. begin
  1256. xorMask := ABitmap.XorMask.Duplicate as TBGRABitmap;
  1257. xorMask.AlphaFill(255);
  1258. xorMask.ReplaceColor(BGRABlack,BGRAPixelTransparent);
  1259. ABitmap.DiscardXorMask;
  1260. end
  1261. else
  1262. xorMask := nil;
  1263. if NewLayer(ABitmap, AName, boTransparent) then
  1264. begin
  1265. if Assigned(xorMask) then
  1266. result := NewLayer(xorMask, AName + ' (xor)', boXor)
  1267. else
  1268. result := true;
  1269. end else
  1270. begin
  1271. xorMask.Free;
  1272. result := false;
  1273. end;
  1274. end else
  1275. begin
  1276. ABitmap.Free;
  1277. result := false;
  1278. end;
  1279. end else
  1280. begin
  1281. ABitmap.Free;
  1282. result := false;
  1283. end;
  1284. end;
  1285. function TImageActions.AddLayerFromOriginal(
  1286. AOriginal: TBGRALayerCustomOriginal; AName: string): boolean;
  1287. begin
  1288. result := AddLayerFromOriginal(AOriginal,AName,AffineMatrixIdentity);
  1289. end;
  1290. function TImageActions.AddLayerFromOriginal(AOriginal: TBGRALayerCustomOriginal;
  1291. AName: string; AMatrix: TAffineMatrix; ABlendOp: TBlendOperation; AOpacity: byte): boolean;
  1292. begin
  1293. if AOriginal <> nil then
  1294. begin
  1295. if CurrentTool in [ptDeformation,ptRotateSelection,ptMoveSelection,
  1296. ptLayerMapping,ptEditShape] then
  1297. ChooseTool(ptHand);
  1298. if image.CheckNoAction then
  1299. begin
  1300. if not Image.SelectionMaskEmpty then ReleaseSelection;
  1301. result := NewLayer(AOriginal, AName, ABlendOp, AMatrix, AOpacity);
  1302. end else
  1303. begin
  1304. AOriginal.Free;
  1305. result := false;
  1306. end;
  1307. end else
  1308. begin
  1309. AOriginal.Free;
  1310. result := false;
  1311. end;
  1312. end;
  1313. function TImageActions.ChangeLayeredImageCanvasSize(layeredBmp: TLazPaintImage; newWidth,
  1314. newHeight: integer; anchor: string; background: TBGRAPixel;
  1315. repeatImage: boolean; flipMode: boolean): TBGRALayeredBitmap;
  1316. var i,idx: integer;
  1317. orig: TBGRALayerCustomOriginal;
  1318. newOrigin: TPoint;
  1319. newBmp: TBGRABitmap;
  1320. begin
  1321. result := TBGRALayeredBitmap.Create;
  1322. for i := 0 to layeredbmp.NbLayers-1 do
  1323. begin
  1324. FInstance.ReportActionProgress(i*100 div layeredbmp.NbLayers);
  1325. newBmp := ChangeBitmapCanvasSize(layeredbmp.LayerBitmap[i],layeredbmp.LayerOffset[i],layeredBmp.Width,layeredBmp.Height, newwidth,newHeight,anchor,background,repeatImage,flipMode);
  1326. idx := result.AddOwnedLayer(newBmp,layeredBmp.BlendOperation[i],layeredbmp.LayerOpacity[i]);
  1327. result.LayerName[idx] := layeredbmp.LayerName[i];
  1328. result.LayerVisible[idx] := layeredbmp.LayerVisible[i];
  1329. if not repeatImage and layeredBmp.LayerOriginalDefined[i] and layeredBmp.LayerOriginalKnown[i] then
  1330. begin
  1331. orig := layeredBmp.LayerOriginal[i];
  1332. if Assigned(orig) then
  1333. begin
  1334. if result.IndexOfOriginal(orig)=-1 then result.AddOriginal(orig,false);
  1335. result.LayerOriginalGuid[idx] := orig.Guid;
  1336. newOrigin := ChangeCanvasSizeOrigin(layeredBmp.Width,layeredBmp.Height,newwidth,newHeight,anchor);
  1337. result.LayerOriginalMatrix[idx] := AffineMatrixTranslation(newOrigin.X,newOrigin.Y)*layeredBmp.LayerOriginalMatrix[i];
  1338. result.RenderLayerFromOriginal(idx);
  1339. end;
  1340. end;
  1341. end;
  1342. FInstance.ReportActionProgress(100);
  1343. end;
  1344. procedure TImageActions.ChangeCanvasSize(AWidth,AHeight: integer;
  1345. AAnchor: string; ARepeatImage, AFlipMode: boolean);
  1346. var result: TLayeredBitmapAndSelection;
  1347. begin
  1348. result.layeredBitmap := ChangeLayeredImageCanvasSize(Image,
  1349. AWidth,AHeight,AAnchor,BGRAPixelTransparent, ARepeatImage, AFlipMode);
  1350. if Image.SelectionMaskReadonly <> nil then
  1351. result.selection := ChangeBitmapCanvasSize(Image.SelectionMaskReadonly,
  1352. Point(0,0),Image.Width,Image.Height,
  1353. AWidth,AHeight,AAnchor,BGRABlack, ARepeatImage, AFlipMode)
  1354. else
  1355. result.selection := nil;
  1356. if Image.SelectionLayerReadonly <> nil then
  1357. result.selectionLayer := ChangeBitmapCanvasSize(Image.SelectionLayerReadonly,
  1358. Point(0,0),Image.Width,Image.Height,
  1359. AWidth,AHeight,AAnchor,BGRAPixelTransparent, ARepeatImage, AFlipMode)
  1360. else
  1361. result.selectionLayer := nil;
  1362. Image.Assign(result, true, true);
  1363. end;
  1364. procedure TImageActions.HorizontalFlip(AOption: TFlipOption);
  1365. begin
  1366. try
  1367. if (AOption = foCurrentLayer) then
  1368. image.HorizontalFlip(Image.CurrentLayerIndex) else
  1369. if ((AOption = foAuto) and not image.SelectionMaskEmpty) or (AOption = foSelection) then
  1370. begin
  1371. if not image.SelectionMaskEmpty then
  1372. begin
  1373. ChooseTool(ptMoveSelection);
  1374. if not Image.CheckNoAction then exit;
  1375. Image.SelectionTransform := AffineMatrixTranslation(+Image.Width/2,0)*AffineMatrixScale(-1,1)*AffineMatrixTranslation(-Image.Width/2,0)*Image.SelectionTransform;
  1376. end else
  1377. exit;
  1378. end else
  1379. if ((AOption = foAuto) and image.SelectionMaskEmpty) or (AOption = foWholePicture) then
  1380. image.HorizontalFlip;
  1381. except
  1382. on ex:Exception do
  1383. FInstance.ShowError('HorizontalFlip',ex.Message);
  1384. end;
  1385. end;
  1386. procedure TImageActions.VerticalFlip(AOption: TFlipOption);
  1387. begin
  1388. try
  1389. if (AOption = foCurrentLayer) then
  1390. image.VerticalFlip(Image.CurrentLayerIndex) else
  1391. if ((AOption = foAuto) and not image.SelectionMaskEmpty) or (AOption = foSelection) then
  1392. begin
  1393. if not image.SelectionMaskEmpty then
  1394. begin
  1395. ChooseTool(ptMoveSelection);
  1396. if not Image.CheckNoAction then exit;
  1397. Image.SelectionTransform := AffineMatrixTranslation(0,+Image.Height/2)*AffineMatrixScale(1,-1)*AffineMatrixTranslation(0,-Image.Height/2)*Image.SelectionTransform;
  1398. end else
  1399. exit;
  1400. end else
  1401. if ((AOption = foAuto) and image.SelectionMaskEmpty) or (AOption = foWholePicture) then
  1402. image.VerticalFlip;
  1403. except
  1404. on ex:Exception do
  1405. FInstance.ShowError('VerticalFlip',ex.Message);
  1406. end;
  1407. end;
  1408. procedure TImageActions.RotateCW;
  1409. begin
  1410. Image.RotateCW;
  1411. end;
  1412. procedure TImageActions.RotateCCW;
  1413. begin
  1414. Image.RotateCCW;
  1415. end;
  1416. procedure TImageActions.Rotate180;
  1417. begin
  1418. Image.Rotate180;
  1419. end;
  1420. procedure TImageActions.LinearNegativeAll;
  1421. begin
  1422. Image.LinearNegativeAll;
  1423. end;
  1424. procedure TImageActions.NegativeAll;
  1425. begin
  1426. Image.NegativeAll;
  1427. end;
  1428. procedure TImageActions.SwapRedBlueAll;
  1429. begin
  1430. Image.SwapRedBlue;
  1431. end;
  1432. procedure TImageActions.InvertSelection;
  1433. var LayerAction: TLayerAction;
  1434. p : PBGRAPixel;
  1435. n: integer;
  1436. begin
  1437. LayerAction := nil;
  1438. try
  1439. LayerAction := Image.CreateAction(false,true);
  1440. LayerAction.QuerySelection;
  1441. p := LayerAction.CurrentSelection.Data;
  1442. for n := LayerAction.CurrentSelection.NbPixels-1 downto 0 do
  1443. begin
  1444. if p^.alpha <> 255 then p^ := BGRABlack;
  1445. inc(p);
  1446. end;
  1447. LayerAction.CurrentSelection.InvalidateBitmap;
  1448. LayerAction.CurrentSelection.LinearNegative;
  1449. LayerAction.Validate;
  1450. Image.SelectionMaskMayChangeCompletely;
  1451. except
  1452. on ex:Exception do
  1453. FInstance.ShowError('InvertSelection',ex.Message);
  1454. end;
  1455. LayerAction.Free;
  1456. if Image.SelectionMaskEmpty then ChooseTool(ptHand) else
  1457. if not (CurrentTool in[ptSelectRect,ptSelectEllipse]) then ChooseTool(ptSelectRect);
  1458. end;
  1459. procedure TImageActions.Deselect;
  1460. begin
  1461. if (CurrentTool in[ptRotateSelection,ptMoveSelection]) then
  1462. ChooseTool(ptHand);
  1463. if not Image.CheckNoAction then exit;
  1464. try
  1465. if not image.SelectionMaskEmpty then ReleaseSelection;
  1466. except
  1467. on ex:Exception do
  1468. FInstance.ShowError('Deselect',ex.Message);
  1469. end;
  1470. end;
  1471. procedure TImageActions.CopySelection;
  1472. var layer, partial : TBGRABitmap; r: TRect;
  1473. LayerAction: TLayerAction;
  1474. bounds: TRect;
  1475. begin
  1476. LayerAction := nil;
  1477. try
  1478. if not image.CheckNoAction then exit;
  1479. bounds := Image.SelectionMaskBounds;
  1480. if IsRectEmpty(bounds) then exit;
  1481. LayerAction := Image.CreateAction(true,true);
  1482. LayerAction.ApplySelectionMask;
  1483. if Image.SelectionLayerIsEmpty then LayerAction.RetrieveSelection;
  1484. layer := LayerAction.GetOrCreateSelectionLayer;
  1485. r := layer.GetImageBounds; //bounds may have been changed
  1486. if (r.right > r.left) and (r.bottom > r.top) then
  1487. begin
  1488. partial := layer.GetPart(r) as TBGRABitmap;
  1489. CopyToClipboard(partial);
  1490. partial.Free;
  1491. end;
  1492. FreeAndNil(LayerAction);
  1493. except
  1494. on ex:Exception do
  1495. begin
  1496. FreeAndNil(LayerAction);
  1497. FInstance.ShowError('CopySelection',ex.Message);
  1498. end;
  1499. end;
  1500. end;
  1501. procedure TImageActions.CutSelection;
  1502. var LayerAction: TLayerAction;
  1503. begin
  1504. if image.SelectionMaskEmpty then exit;
  1505. if not image.CheckNoAction then exit;
  1506. LayerAction := nil;
  1507. try
  1508. CopySelection;
  1509. LayerAction := Image.CreateAction(false,true);
  1510. if (LayerAction.GetSelectionLayerIfExists = nil) or (LayerAction.GetSelectionLayerIfExists.Empty) then
  1511. LayerAction.EraseSelectionInBitmap;
  1512. LayerAction.RemoveSelection;
  1513. LayerAction.Validate;
  1514. except
  1515. on ex:Exception do
  1516. FInstance.ShowError('CutSelection',ex.Message);
  1517. end;
  1518. LayerAction.Free;
  1519. if (CurrentTool = ptRotateSelection) or
  1520. (CurrentTool = ptMoveSelection) then
  1521. ChooseTool(ptHand);
  1522. end;
  1523. procedure TImageActions.RetrieveSelection;
  1524. var LayerAction: TLayerAction;
  1525. r: TRect;
  1526. begin
  1527. if image.SelectionMaskEmpty then exit;
  1528. if not image.CheckNoAction then exit;
  1529. LayerAction := nil;
  1530. try
  1531. LayerAction := Image.CreateAction(false, true);
  1532. if LayerAction.RetrieveSelectionIfLayerEmpty(True) then
  1533. begin
  1534. r := Image.SelectionMaskBounds;
  1535. ComputeSelectionMask(LayerAction.GetOrCreateSelectionLayer,LayerAction.CurrentSelection,r);
  1536. LayerAction.NotifyChange(LayerAction.GetOrCreateSelectionLayer, r);
  1537. LayerAction.NotifyChange(LayerAction.CurrentSelection, r);
  1538. LayerAction.Validate;
  1539. end;
  1540. if image.SelectionLayerIsEmpty then MessagePopup(rsNothingToBeRetrieved,2000);
  1541. except on ex:exception do FInstance.ShowError('RetrieveSelection',ex.Message);
  1542. end;
  1543. LayerAction.Free;
  1544. end;
  1545. procedure TImageActions.DeleteSelection;
  1546. var LayerAction: TLayerAction;
  1547. doErase, wasSelecting: Boolean;
  1548. prevTool: TPaintToolType;
  1549. begin
  1550. if image.SelectionMaskEmpty then
  1551. begin
  1552. prevTool := ToolManager.GetCurrentToolType;
  1553. if (prevTool in [ptMoveLayer, ptZoomLayer, ptRotateLayer])
  1554. and (image.NbLayers > 1) then
  1555. begin
  1556. ChooseTool(ptHand, false);
  1557. Image.RemoveLayer;
  1558. ChooseTool(prevTool, false);
  1559. end;
  1560. exit;
  1561. end;
  1562. wasSelecting := ToolManager.GetCurrentToolType in [ptSelectPen..ptSelectSpline];
  1563. if wasSelecting then ToolManager.ToolCloseDontReopen
  1564. else if not image.CheckNoAction then exit;
  1565. LayerAction := nil;
  1566. try
  1567. doErase := Image.SelectionLayerIsEmpty;
  1568. LayerAction := Image.CreateAction(false, doErase);
  1569. if doErase then LayerAction.EraseSelectionInBitmap;
  1570. LayerAction.RemoveSelection;
  1571. LayerAction.Validate;
  1572. except
  1573. on ex:Exception do
  1574. FInstance.ShowError('DeleteSelection',ex.Message);
  1575. end;
  1576. LayerAction.Free;
  1577. if wasSelecting then ToolManager.ToolOpen
  1578. else if (CurrentTool = ptRotateSelection) or
  1579. (CurrentTool = ptMoveSelection) then
  1580. ChooseTool(ptHand);
  1581. end;
  1582. procedure TImageActions.RemoveSelection;
  1583. var LayerAction: TLayerAction;
  1584. begin
  1585. if image.SelectionMaskEmpty then exit;
  1586. if not image.CheckNoAction then exit;
  1587. LayerAction := nil;
  1588. try
  1589. LayerAction := Image.CreateAction;
  1590. LayerAction.RemoveSelection;
  1591. LayerAction.Validate;
  1592. except on ex:exception do FInstance.ShowError('RemoveSelection',ex.Message);
  1593. end;
  1594. LayerAction.Free;
  1595. if (CurrentTool = ptRotateSelection) or
  1596. (CurrentTool = ptMoveSelection) then
  1597. ChooseTool(ptHand);
  1598. end;
  1599. procedure TImageActions.ReleaseSelection;
  1600. var
  1601. layeraction: TLayerAction;
  1602. begin
  1603. if image.SelectionMaskEmpty then exit;
  1604. layeraction := image.CreateAction(true, true);
  1605. layeraction.ChangeBoundsNotified:= true;
  1606. layeraction.ReleaseSelection;
  1607. layeraction.Validate;
  1608. layeraction.Free;
  1609. end;
  1610. function TImageActions.ScriptSelectLayerIndex(AVars: TVariableSet): TScriptResult;
  1611. var
  1612. index: Int64;
  1613. begin
  1614. index := AVars.Integers['Index'];
  1615. if (AVars.Integers['Index'] < 1) or (AVars.Integers['Index'] > Image.NbLayers) then exit(srInvalidParameters);
  1616. if not Image.SetCurrentLayerByIndex(index-1) then result := srException
  1617. else result := srOk;
  1618. end;
  1619. function TImageActions.ScriptClearAlpha(AVars: TVariableSet): TScriptResult;
  1620. begin
  1621. if AVars.IsDefined('BackColor') then
  1622. ClearAlpha(AVars.Pixels['BackColor'])
  1623. else
  1624. ClearAlpha;
  1625. result := srOk;
  1626. end;
  1627. function TImageActions.ScriptFillBackground(AVars: TVariableSet): TScriptResult;
  1628. begin
  1629. if AVars.IsDefined('BackColor') then
  1630. FillBackground(AVars.Pixels['BackColor'])
  1631. else
  1632. FillBackground;
  1633. result := srOk;
  1634. end;
  1635. procedure TImageActions.Paste;
  1636. var partial: TBGRABitmap;
  1637. layeraction: TLayerAction;
  1638. pastePos: TPoint;
  1639. begin
  1640. try
  1641. if ClipboardHasShapes then
  1642. begin
  1643. ChooseTool(ptEditShape);
  1644. ToolManager.ToolCommand(tcPaste);
  1645. end else
  1646. begin
  1647. partial := GetBitmapFromClipboard;
  1648. if partial<>nil then
  1649. begin
  1650. if partial.NbPixels <> 0 then
  1651. begin
  1652. ToolManager.ToolCloseDontReopen;
  1653. DoBegin;
  1654. try
  1655. if (partial.Width > Image.Width) or
  1656. (partial.Height > Image.Height) then
  1657. begin
  1658. ChangeCanvasSize(max(partial.Width, Image.Width),
  1659. max(partial.Height, Image.Height), 'middle', false,false);
  1660. end;
  1661. layeraction := Image.CreateAction(true, true);
  1662. layeraction.ReleaseSelection;
  1663. layeraction.QuerySelection;
  1664. pastePos := Point((image.Width - partial.Width) div 2 - image.ImageOffset.X,
  1665. (image.Height - partial.Height) div 2 - image.ImageOffset.Y);
  1666. if pastePos.x+partial.width > image.width then pastePos.x := image.width-partial.width;
  1667. if pastePos.y+partial.Height > image.Height then pastePos.y := image.Height-partial.Height;
  1668. if pastePos.x < 0 then pastePos.x := 0;
  1669. if pastePos.y < 0 then pastePos.y := 0;
  1670. layeraction.GetOrCreateSelectionLayer.PutImage(pastePos.x,pastePos.y,partial,dmFastBlend);
  1671. ComputeSelectionMask(layeraction.GetOrCreateSelectionLayer,layeraction.currentSelection,
  1672. rect(pastePos.x,pastePos.y,pastePos.x+partial.Width,pastePos.y+partial.Height));
  1673. Image.SelectionMaskMayChange(rect(pastePos.x,pastePos.y,pastePos.x+partial.Width,pastePos.y+partial.Height));
  1674. layeraction.Validate;
  1675. layeraction.Free;
  1676. finally
  1677. DoEnd;
  1678. end;
  1679. ChooseTool(ptMoveSelection);
  1680. end;
  1681. partial.Free;
  1682. end;
  1683. end;
  1684. except
  1685. on ex:Exception do
  1686. FInstance.ShowError('Paste',ex.Message);
  1687. end;
  1688. end;
  1689. function TImageActions.PasteAsNewLayer: integer;
  1690. var partial: TBGRABitmap;
  1691. orig: TVectorOriginal;
  1692. begin
  1693. result := -1;
  1694. try
  1695. if ClipboardHasShapes then
  1696. begin
  1697. orig := TVectorOriginal.Create;
  1698. PasteShapesFromClipboard(orig, AffineMatrixIdentity, EmptyRectF);
  1699. if AddLayerFromOriginal(orig, '') then
  1700. result := Image.LayerId[Image.CurrentLayerIndex];
  1701. end else
  1702. begin
  1703. partial := GetBitmapFromClipboard;
  1704. if partial<>nil then
  1705. begin
  1706. if partial.NbPixels <> 0 then
  1707. begin
  1708. AddLayerFromBitmap(partial,'');
  1709. ChooseTool(ptMoveLayer);
  1710. result := Image.LayerId[Image.CurrentLayerIndex];
  1711. end
  1712. else
  1713. partial.Free;
  1714. end else
  1715. end;
  1716. except
  1717. on ex:Exception do
  1718. FInstance.ShowError('Paste',ex.Message);
  1719. end;
  1720. end;
  1721. procedure TImageActions.SelectAll;
  1722. var LayerAction : TLayerAction;
  1723. begin
  1724. try
  1725. LayerAction := Image.CreateAction;
  1726. LayerAction.QuerySelection;
  1727. LayerAction.currentSelection.Fill(BGRAWhite);
  1728. Image.SelectionMaskMayChangeCompletely;
  1729. LayerAction.Validate;
  1730. LayerAction.Free;
  1731. if not ToolManager.IsSelectingTool then ChooseTool(ptSelectRect);
  1732. except
  1733. on ex:Exception do
  1734. FInstance.ShowError('SelectAll',ex.Message);
  1735. end;
  1736. end;
  1737. procedure TImageActions.SelectionFit;
  1738. var LayerAction: TLayerAction;
  1739. bounds: TRect;
  1740. begin
  1741. if not image.CheckNoAction then exit;
  1742. try
  1743. LayerAction := Image.CreateAction(false,true);
  1744. LayerAction.ChangeBoundsNotified := true;
  1745. if image.SelectionMaskEmpty then
  1746. begin
  1747. bounds := rect(0,0,Image.width,image.height);
  1748. LayerAction.QuerySelection;
  1749. LayerAction.currentSelection.Fill(BGRAWhite);
  1750. LayerAction.NotifyChange(LayerAction.currentSelection, bounds);
  1751. Image.SelectionMaskMayChange(bounds);
  1752. end else
  1753. begin
  1754. bounds := image.SelectionLayerBounds;
  1755. Image.SelectionMaskMayChange(bounds);
  1756. LayerAction.ApplySelectionMask;
  1757. LayerAction.NotifyChange(LayerAction.GetSelectionLayerIfExists, bounds);
  1758. bounds := image.SelectionMaskBounds;
  1759. Image.SelectionMaskMayChange(bounds);
  1760. end;
  1761. if LayerAction.RetrieveSelectionIfLayerEmpty(True) then
  1762. begin
  1763. LayerAction.NotifyChange(LayerAction.GetSelectionLayerIfExists, bounds);
  1764. LayerAction.NotifyChange(LayerAction.SelectedImageLayer, bounds);
  1765. end;
  1766. ComputeSelectionMask(LayerAction.GetOrCreateSelectionLayer,LayerAction.currentSelection,bounds);
  1767. LayerAction.NotifyChange(LayerAction.CurrentSelection, bounds);
  1768. LayerAction.NotifyChange(LayerAction.GetOrCreateSelectionLayer, bounds);
  1769. LayerAction.Validate;
  1770. LayerAction.Free;
  1771. if image.SelectionMaskEmpty then
  1772. begin
  1773. if (CurrentTool = ptRotateSelection) or
  1774. (CurrentTool = ptMoveSelection) then
  1775. ChooseTool(ptHand);
  1776. end else
  1777. if not ToolManager.IsSelectingTool then ChooseTool(ptMoveSelection);
  1778. except
  1779. on ex:Exception do
  1780. FInstance.ShowError('SelectionFit',ex.Message);
  1781. end;
  1782. end;
  1783. function TImageActions.NewLayer: boolean;
  1784. {var top: TTopMostInfo;
  1785. res: integer;}
  1786. begin
  1787. {if not image.SelectionLayerIsEmpty then
  1788. begin
  1789. top := FInstance.HideTopmost;
  1790. res := MessageDlg(rsTransferSelectionToOtherLayer,mtConfirmation,[mbOk,mbCancel],0);
  1791. FInstance.ShowTopmost(top);
  1792. if res <> mrOk then exit;
  1793. end;}
  1794. if image.NbLayers < MaxLayersToAdd then
  1795. begin
  1796. if CurrentTool in[ptMoveLayer,ptRotateLayer,ptZoomLayer,ptLayerMapping,ptDeformation] then
  1797. ChooseTool(ptHand);
  1798. ToolManager.ToolCloseDontReopen;
  1799. Image.AddNewLayer;
  1800. ToolManager.ToolOpen;
  1801. FInstance.ScrollLayerStackOnItem(Image.CurrentLayerIndex);
  1802. result := true;
  1803. end else
  1804. result := false;
  1805. end;
  1806. function TImageActions.NewLayer(ALayer: TBGRABitmap; AName: string;
  1807. ABlendOp: TBlendOperation; AOpacity: byte): boolean;
  1808. begin
  1809. if image.NbLayers < MaxLayersToAdd then
  1810. begin
  1811. if CurrentTool in[ptMoveLayer,ptRotateLayer,ptZoomLayer,ptLayerMapping,ptDeformation] then
  1812. ChooseTool(ptHand);
  1813. ToolManager.ToolCloseDontReopen;
  1814. Image.AddNewLayer(ALayer, AName, ABlendOp, AOpacity);
  1815. ToolManager.ToolOpen;
  1816. FInstance.ScrollLayerStackOnItem(Image.CurrentLayerIndex);
  1817. result := true;
  1818. end else
  1819. begin
  1820. FInstance.ShowMessage(rsLayers, rsTooManyLayers);
  1821. ALayer.Free;
  1822. result := false;
  1823. end;
  1824. end;
  1825. function TImageActions.NewLayer(ALayer: TBGRABitmap; AName: string;
  1826. AOffset: TPoint; ABlendOp: TBlendOperation; AOpacity: byte): boolean;
  1827. begin
  1828. if image.NbLayers < MaxLayersToAdd then
  1829. begin
  1830. if CurrentTool in[ptMoveLayer,ptRotateLayer,ptZoomLayer,ptLayerMapping,ptDeformation] then
  1831. ChooseTool(ptHand);
  1832. ToolManager.ToolCloseDontReopen;
  1833. Image.AddNewLayer(ALayer, AName, AOffset, ABlendOp, AOpacity);
  1834. ToolManager.ToolOpen;
  1835. FInstance.ScrollLayerStackOnItem(Image.CurrentLayerIndex);
  1836. result := true;
  1837. end else
  1838. begin
  1839. FInstance.ShowMessage(rsLayers, rsTooManyLayers);
  1840. ALayer.Free;
  1841. result := false;
  1842. end;
  1843. end;
  1844. function TImageActions.NewLayer(ALayer: TBGRALayerCustomOriginal;
  1845. AName: string; ABlendOp: TBlendOperation; AMatrix: TAffineMatrix; AOpacity: byte): boolean;
  1846. begin
  1847. if image.NbLayers < MaxLayersToAdd then
  1848. begin
  1849. if CurrentTool in[ptMoveLayer,ptRotateLayer,ptZoomLayer,ptLayerMapping,ptDeformation] then
  1850. ChooseTool(ptHand);
  1851. ToolManager.ToolCloseDontReopen;
  1852. Image.AddNewLayer(ALayer, AName, ABlendOp, AMatrix, AOpacity);
  1853. ToolManager.ToolOpen;
  1854. FInstance.ScrollLayerStackOnItem(Image.CurrentLayerIndex);
  1855. result := true;
  1856. end else
  1857. begin
  1858. FInstance.ShowMessage(rsLayers, rsTooManyLayers);
  1859. ALayer.Free;
  1860. result := false;
  1861. end;
  1862. end;
  1863. function TImageActions.DuplicateLayer: boolean;
  1864. begin
  1865. if image.NbLayers < MaxLayersToAdd then
  1866. begin
  1867. Image.DuplicateLayer;
  1868. FInstance.ScrollLayerStackOnItem(Image.CurrentLayerIndex);
  1869. result := true;
  1870. end else
  1871. result := false;
  1872. end;
  1873. procedure TImageActions.RasterizeLayer;
  1874. begin
  1875. if CurrentTool in[ptMoveLayer,ptRotateLayer,ptZoomLayer,ptLayerMapping,ptDeformation] then
  1876. ChooseTool(ptHand);
  1877. ToolManager.ToolCloseDontReopen;
  1878. Image.RasterizeLayer;
  1879. ToolManager.ToolOpen;
  1880. FInstance.ScrollLayerStackOnItem(Image.CurrentLayerIndex);
  1881. end;
  1882. procedure TImageActions.MergeLayerOver;
  1883. begin
  1884. if (Image.CurrentLayerIndex <> -1) and (image.NbLayers > 1) then
  1885. begin
  1886. ChooseTool(ptHand);
  1887. Image.MergeLayerOver;
  1888. FInstance.ScrollLayerStackOnItem(Image.CurrentLayerIndex);
  1889. end;
  1890. end;
  1891. function TImageActions.RemoveLayer: boolean;
  1892. var idx: integer;
  1893. begin
  1894. if (Image.CurrentLayerIndex <> -1) and (Image.NbLayers > 1) then
  1895. begin
  1896. idx := Image.CurrentLayerIndex;
  1897. if CurrentTool in[ptMoveLayer,ptRotateLayer,ptZoomLayer,ptLayerMapping,ptDeformation] then
  1898. ChooseTool(ptHand);
  1899. ToolManager.ToolCloseDontReopen;
  1900. Image.RemoveLayer;
  1901. ToolManager.ToolOpen;
  1902. FInstance.ScrollLayerStackOnItem(idx);
  1903. result := true;
  1904. end else result := false;
  1905. end;
  1906. procedure TImageActions.EditSelection(ACallback: TModifyImageCallback);
  1907. var lSelection,lTemp: TBGRABitmap;
  1908. LayerAction: TLayerAction;
  1909. begin
  1910. if not image.CheckNoAction then exit;
  1911. try
  1912. LayerAction := Image.CreateAction;
  1913. try
  1914. LayerAction.QuerySelection;
  1915. lSelection:= LayerAction.currentSelection.Duplicate as TBGRABitmap;
  1916. lSelection.LinearAntialiasing := False;
  1917. lSelection.ConvertFromLinearRGB;
  1918. try
  1919. ACallback(lSelection);
  1920. except on ex:Exception do FInstance.ShowError('EditSelection',ex.Message);
  1921. end;
  1922. lSelection.InplaceGrayscale;
  1923. lTemp := TBGRABitmap.Create(lSelection.Width,lSelection.Height,BGRABlack);
  1924. lTemp.PutImage(0,0,lSelection,dmDrawWithTransparency);
  1925. lSelection.Free;
  1926. lSelection := lTemp;
  1927. lTemp := nil;
  1928. lSelection.ConvertToLinearRGB;
  1929. lSelection.LinearAntialiasing := True;
  1930. LayerAction.ReplaceCurrentSelection(lSelection);
  1931. LayerAction.Validate;
  1932. finally
  1933. LayerAction.Free;
  1934. Image.SelectionMaskMayChangeCompletely;
  1935. end;
  1936. except on ex:Exception do FInstance.ShowError('EditSelection',ex.Message);
  1937. end;
  1938. end;
  1939. end.