1 // SPDX-License-Identifier: GPL-3.0-only
2 unit UImageState;
3
4 {$mode objfpc}{$H+}
5
6 interface
7
8 uses
9 Classes, SysUtils, UStateType, BGRABitmap, BGRABitmapTypes, Types, BGRALayers,
10 UImageType, BGRAWriteLzp, BGRAReadLzp, FPimage, BGRALayerOriginal;
11
12 type
13 TBoundsState = (bsUndefined, bsWithinCurrent, bsDefined);
14
15 { TImageState }
16
17 TImageState = class(TState)
18 private
19 FLayeredBitmap: TBGRALayeredBitmap;
20 FOnActionDone: TNotifyEvent;
21 FOnActionProgress: TLayeredActionProgressEvent;
22 FOnOriginalChange: TEmbeddedOriginalChangeEvent;
23 FOnOriginalEditingChange: TEmbeddedOriginalEditingChangeEvent;
24 FOnOriginalLoadError: TEmbeddedOriginalLoadErrorEvent;
25 FOnSizeChanged: TNotifyEvent;
26 FSelectionMask: TBGRABitmap;
27 FLastSelectionMaskBoundsIsDefined,
28 FLastSelectionLayerBoundsIsDefined: TBoundsState;
29 FLastSelectionMaskBounds, FLastSelectionLayerBounds: TRect;
30 FSelectionTransform: TAffineMatrix;
GetBlendOpnull31 function GetBlendOp(Index: integer): TBlendOperation;
GetSelectedImageLayernull32 function GetSelectedImageLayer: TBGRABitmap;
GetCurrentLayerIndexnull33 function GetCurrentLayerIndex: integer;
GetSelectionMasknull34 function GetSelectionMask: TBGRABitmap;
GetHasOriginalsnull35 function GetHasOriginals: boolean;
GetHeightnull36 function GetHeight: integer;
GetLayerBitmapnull37 function GetLayerBitmap(Index: integer): TBGRABitmap;
GetLayerBitmapByIdnull38 function GetLayerBitmapById(AId: integer): TBGRABitmap;
GetLayerIdnull39 function GetLayerId(Index: integer): integer;
GetLayerNamenull40 function GetLayerName(Index: integer): string;
GetLayerOffsetnull41 function GetLayerOffset(Index: integer): TPoint;
GetLayerOpacitynull42 function GetLayerOpacity(Index: integer): byte;
GetLayerOriginalnull43 function GetLayerOriginal(Index: integer): TBGRALayerCustomOriginal;
GetLayerOriginalDefinednull44 function GetLayerOriginalDefined(Index: integer): boolean;
GetLayerOriginalKnownnull45 function GetLayerOriginalKnown(Index: integer): boolean;
GetLayerOriginalClassnull46 function GetLayerOriginalClass(Index: integer): TBGRALayerOriginalAny;
GetLayerOriginalMatrixnull47 function GetLayerOriginalMatrix(Index: integer): TAffineMatrix;
GetLayerVisiblenull48 function GetLayerVisible(Index: integer): boolean;
GetLinearBlendnull49 function GetLinearBlend: boolean;
GetNbLayersnull50 function GetNbLayers: integer;
GetWidthnull51 function GetWidth: integer;
52 procedure LayeredActionDone(Sender: TObject);
53 procedure LayeredActionProgress({%H-}ASender: TObject; AProgressPercent: integer);
54 procedure OriginalChange({%H-}ASender: TObject;
55 AOriginal: TBGRALayerCustomOriginal; var ADiff: TBGRAOriginalDiff);
56 procedure OriginalEditingChange({%H-}ASender: TObject;
57 AOriginal: TBGRALayerCustomOriginal);
58 procedure OriginalLoadError(ASender: TObject; AError: string;
59 var ARaise: boolean);
60 procedure SelectImageLayer(AValue: TBGRABitmap);
61 procedure SelectImageLayerByIndex(AValue: integer);
62 procedure SetLayeredBitmap(AValue: TBGRALayeredBitmap);
63 procedure SetLinearBlend(AValue: boolean);
64 procedure SetOnActionDone(AValue: TNotifyEvent);
65 procedure SetOnActionProgress(AValue: TLayeredActionProgressEvent);
66 procedure SetOnSizeChanged(AValue: TNotifyEvent);
67 procedure SetSelectionMask(AValue: TBGRABitmap);
MakeLayerNamenull68 function MakeLayerName: string;
69 procedure CheckSizeChanged(APrevSize: TSize);
GetSizenull70 function GetSize: TSize;
71 public
72 SelectionLayer: TBGRABitmap;
73 selectedLayerId: integer;
74 filenameUTF8: string;
75 DiscardOriginalDiff: boolean;
76
77 // generic state functions
78 constructor Create;
79 destructor Destroy; override;
Equalsnull80 function Equals(Obj: TObject): boolean; override;
81 procedure ApplyDifference(ADifference: TStateDifference); override;
82 procedure ReverseDifference(ADifference: TStateDifference); override;
Duplicatenull83 function Duplicate: TState; override;
84
85 // whole image
86 procedure SetSize(AWidth,AHeight: integer);
87 procedure NotifySizeChanged;
88 procedure Assign(AValue: TBGRABitmap; AOwned: boolean);
89 procedure Assign(AValue: TBGRACustomLayeredBitmap; AOwned: boolean);
90 procedure Assign(AValue: TImageState; AOwned: boolean);
91
RotateCWnull92 function RotateCW: TCustomImageDifference;
RotateCCWnull93 function RotateCCW: TCustomImageDifference;
Rotate180null94 function Rotate180: TCustomImageDifference;
HorizontalFlipnull95 function HorizontalFlip: TCustomImageDifference; overload;
VerticalFlipnull96 function VerticalFlip: TCustomImageDifference; overload;
97 procedure Resample(AWidth,AHeight: integer; AQuality: TResampleMode; AFilter: TResampleFilter);
98
99 // layer
100 procedure SetLayerBitmap(layer: integer; ABitmap: TBGRABitmap; AOwned: boolean);
HorizontalFlipnull101 function HorizontalFlip(ALayerIndex: integer): TCustomImageDifference; overload;
VerticalFlipnull102 function VerticalFlip(ALayerIndex: integer): TCustomImageDifference; overload;
103
104 // selection mask
105 procedure QuerySelectionMask;
106 procedure ReplaceSelection(ASelectionMask, ASelectionLayer: TBGRABitmap);
107 procedure RemoveSelection;
108
109 procedure DiscardSelectionMaskBounds(const AChangeRect: TRect);
110 procedure DiscardSelectionMaskBoundsCompletely;
GetSelectionMaskBoundsnull111 function GetSelectionMaskBounds: TRect;
SelectionMaskEmptynull112 function SelectionMaskEmpty: boolean;
SelectionMaskEmptyComputednull113 function SelectionMaskEmptyComputed: boolean;
GetTransformedSelectionMaskBoundsnull114 function GetTransformedSelectionMaskBounds: TRect;
115 procedure ComputeTransformedSelectionMask(out ANewMask: TBGRABitmap; out ALeft,ATop: integer);
116
117 // selection layer
GetOrCreateSelectionLayernull118 function GetOrCreateSelectionLayer: TBGRABitmap;
119 procedure ReplaceSelectionLayer(bmp: TBGRABitmap; AOwned: boolean);
120 procedure ComputeTransformedSelectionLayer(out ANewLayer: TBGRABitmap; out ALeft,ATop: integer);
121
122 procedure DiscardSelectionLayerBounds(const AChangeRect: TRect);
123 procedure DiscardSelectionLayerBoundsCompletely;
GetSelectionLayerBoundsnull124 function GetSelectionLayerBounds: TRect;
SelectionLayerEmptynull125 function SelectionLayerEmpty: boolean;
126
127 procedure PrepareForRendering;
ComputeFlatImageWithoutSelectionnull128 function ComputeFlatImageWithoutSelection(ASeparateXorMask: boolean): TBGRABitmap;
AssignWithUndonull129 function AssignWithUndo(AValue: TBGRACustomLayeredBitmap; AOwned: boolean; ASelectedLayerIndex: integer): TCustomImageDifference;
AssignWithUndonull130 function AssignWithUndo(AValue: TBGRACustomLayeredBitmap; AOwned: boolean; ASelectedLayerIndex: integer; ACurrentSelection: TBGRABitmap; ASelectionLayer:TBGRABitmap): TCustomImageDifference;
AssignWithUndonull131 function AssignWithUndo(AState: TImageState; AOwned: boolean): TCustomImageDifference;
GetUndoAfterAssignnull132 function GetUndoAfterAssign(ABackup: TImageState): TCustomImageDifference;
133 procedure LoadFromStream(AStream: TStream);
134 procedure SaveToStream(AStream: TStream);
135 procedure SaveToStreamAs(AStream: TStream; AFormat: TBGRAImageFormat);
136 procedure SaveOriginalToStream(AStream: TStream);
137 procedure SaveToFile(AFilenameUTF8: string);
AddNewLayernull138 function AddNewLayer(ALayer: TBGRABitmap; AName: string; AOffset: TPoint; ABlendOp: TBlendOperation; AOpacity: byte = 255): TCustomImageDifference;
AddNewLayernull139 function AddNewLayer(AOriginal: TBGRALayerCustomOriginal; AName: string; ABlendOp: TBlendOperation; AMatrix: TAffineMatrix; AOpacity: byte = 255): TCustomImageDifference;
DuplicateLayernull140 function DuplicateLayer: TCustomImageDifference;
MergerLayerOvernull141 function MergerLayerOver(ALayerOverIndex: integer): TCustomImageDifference;
MoveLayernull142 function MoveLayer(AFromIndex,AToIndex: integer): TCustomImageDifference;
RemoveLayernull143 function RemoveLayer: TCustomImageDifference;
DiscardOriginalnull144 function DiscardOriginal(ACreateUndo: boolean): TCustomImageDifference;
SwapRedBluenull145 function SwapRedBlue: TCustomImageDifference;
LinearNegativenull146 function LinearNegative: TCustomImageDifference;
Negativenull147 function Negative: TCustomImageDifference;
ClearLayernull148 function ClearLayer: TCustomImageDifference;
ComputeLayerOffsetDifferencenull149 function ComputeLayerOffsetDifference(AOffsetX, AOffsetY: integer): TCustomImageDifference;
ComputeSelectionTransformDifferencenull150 function ComputeSelectionTransformDifference: TCustomImageDifference;
ComputeLayerMatrixDifferencenull151 function ComputeLayerMatrixDifference(AIndex: integer; APrevMatrix, ANewMatrix: TAffineMatrix): TCustomImageDifference;
ComputeLayerDifferencenull152 function ComputeLayerDifference(APreviousImage: TBGRABitmap; APreviousImageDefined: boolean;
153 APreviousSelection: TBGRABitmap; APreviousSelectionDefined: boolean;
154 APreviousSelectionLayer: TBGRABitmap; APreviousSelectionLayerDefined: boolean): TCustomImageDifference; overload;
ComputeLayerDifferencenull155 function ComputeLayerDifference(APreviousImage: TBGRABitmap; APreviousImageChangeRect: TRect;
156 APreviousSelection: TBGRABitmap; APreviousSelectionChangeRect: TRect;
157 APreviousSelectionLayer: TBGRABitmap; APreviousSelectionLayerChangeRect: TRect): TCustomImageDifference; overload;
GetLayeredBitmapCopynull158 function GetLayeredBitmapCopy: TBGRALayeredBitmap;
ComputeFlatImagenull159 function ComputeFlatImage(AFromLayer, AToLayer: integer; ASeparateXorMask: boolean): TBGRABitmap;
ComputeFlatImagenull160 function ComputeFlatImage(ARect: TRect; AFromLayer, AToLayer: integer; ASeparateXorMask: boolean): TBGRABitmap;
SetLayerNamenull161 function SetLayerName(Index: integer; AValue: string): TCustomImageDifference;
SetLayerOpacitynull162 function SetLayerOpacity(Index: integer; AValue: byte): TCustomImageDifference;
SetLayerVisiblenull163 function SetLayerVisible(Index: integer; AValue: boolean): TCustomImageDifference;
SetLayerOffsetnull164 function SetLayerOffset(Index: integer; AValue: TPoint): TCustomImageDifference;
SetBlendOpnull165 function SetBlendOp(Index: integer; AValue: TBlendOperation): TCustomImageDifference;
166 procedure DrawLayers(ADest: TBGRABitmap; X,Y: Integer; AIconCursor: boolean; ADestinationEmpty: boolean = false);
167 property SelectedImageLayer: TBGRABitmap read GetSelectedImageLayer write SelectImageLayer;
168 property SelectedImageLayerIndex: integer read GetCurrentLayerIndex write SelectImageLayerByIndex;
169 property LayerOriginal[Index: integer]: TBGRALayerCustomOriginal read GetLayerOriginal;
170 property LayerOriginalDefined[Index: integer]: boolean read GetLayerOriginalDefined;
171 property LayerOriginalKnown[Index: integer]: boolean read GetLayerOriginalKnown;
172 property LayerOriginalClass[Index: integer]: TBGRALayerOriginalAny read GetLayerOriginalClass;
173 property LayerOriginalMatrix[Index: integer]: TAffineMatrix read GetLayerOriginalMatrix;
174 property LayerBitmap[Index: integer]: TBGRABitmap read GetLayerBitmap;
175 property LayerBitmapById[AId: integer]: TBGRABitmap read GetLayerBitmapById;
176 property BlendOperation[Index: integer]: TBlendOperation read GetBlendOp;
177 property LayerOpacity[Index: integer]: byte read GetLayerOpacity;
178 property LayerOffset[Index: integer]: TPoint read GetLayerOffset;
179 property LayerName[Index: integer]: string read GetLayerName;
180 property LayerId[Index: integer]: integer read GetLayerId;
181 property NbLayers: integer read GetNbLayers;
182 property Width: integer read GetWidth;
183 property Height: integer read GetHeight;
184 property LinearBlend: boolean read GetLinearBlend write SetLinearBlend;
185 property LayerVisible[Index: integer]: boolean read GetLayerVisible;
186 property HasOriginals: boolean read GetHasOriginals;
187 property SelectionMask: TBGRABitmap read GetSelectionMask write SetSelectionMask;
188 property LayeredBitmap: TBGRALayeredBitmap read FLayeredBitmap;
189 property SelectionTransform: TAffineMatrix read FSelectionTransform write FSelectionTransform;
190 property OnOriginalChange: TEmbeddedOriginalChangeEvent read FOnOriginalChange write FOnOriginalChange;
191 property OnOriginalEditingChange: TEmbeddedOriginalEditingChangeEvent read FOnOriginalEditingChange write FOnOriginalEditingChange;
192 property OnOriginalLoadError: TEmbeddedOriginalLoadErrorEvent read FOnOriginalLoadError write FOnOriginalLoadError;
193 property OnActionProgress: TLayeredActionProgressEvent read FOnActionProgress write SetOnActionProgress;
194 property OnActionDone: TNotifyEvent read FOnActionDone write SetOnActionDone;
195 property OnSizeChanged: TNotifyEvent read FOnSizeChanged write SetOnSizeChanged;
196 end;
197
198 implementation
199
200 uses BGRAStreamLayers, UImageDiff, BGRALzpCommon, UFileSystem, BGRATransform,
201 UResourceStrings, LCVectorOriginal, UGraph;
202
203 { TImageState }
204
GetSelectedImageLayernull205 function TImageState.GetSelectedImageLayer: TBGRABitmap;
206 var idx: integer;
207 begin
208 if LayeredBitmap = nil then
209 begin
210 result := nil;
211 exit;
212 end else
213 begin
214 idx := LayeredBitmap.GetLayerIndexFromId(selectedLayerId);
215 if idx = -1 then result := nil else
216 result := LayeredBitmap.LayerBitmap[idx]; //assume direct access to bitmap
217 end;
218 end;
219
GetBlendOpnull220 function TImageState.GetBlendOp(Index: integer): TBlendOperation;
221 begin
222 if LayeredBitmap = nil then
223 result := boTransparent
224 else
225 result := LayeredBitmap.BlendOperation[Index];
226 end;
227
GetLayerOriginalClassnull228 function TImageState.GetLayerOriginalClass(Index: integer): TBGRALayerOriginalAny;
229 begin
230 if LayeredBitmap = nil then
231 result := nil
232 else
233 result := LayeredBitmap.LayerOriginalClass[Index];
234 end;
235
GetCurrentLayerIndexnull236 function TImageState.GetCurrentLayerIndex: integer;
237 begin
238 if LayeredBitmap = nil then
239 begin
240 result := -1;
241 end else
242 result := LayeredBitmap.GetLayerIndexFromId(selectedLayerId);
243 end;
244
TImageState.GetSelectionMasknull245 function TImageState.GetSelectionMask: TBGRABitmap;
246 begin
247 result := FSelectionMask;
248 if Assigned(result) then result.LinearAntialiasing := true;
249 end;
250
TImageState.GetHasOriginalsnull251 function TImageState.GetHasOriginals: boolean;
252 var
253 i: Integer;
254 begin
255 if LayeredBitmap= nil then
256 result := false
257 else
258 begin
259 for i := 0 to NbLayers-1 do
260 if LayerOriginalDefined[i] then
261 exit(true);
262 result := false
263 end;
264 end;
265
TImageState.GetHeightnull266 function TImageState.GetHeight: integer;
267 begin
268 if LayeredBitmap= nil then
269 result := 0
270 else
271 result := LayeredBitmap.Height;
272 end;
273
GetLayerBitmapnull274 function TImageState.GetLayerBitmap(Index: integer): TBGRABitmap;
275 begin
276 result := LayeredBitmap.LayerBitmap[Index];
277 end;
278
GetLayerBitmapByIdnull279 function TImageState.GetLayerBitmapById(AId: integer): TBGRABitmap;
280 var idx: integer;
281 begin
282 idx := LayeredBitmap.GetLayerIndexFromId(AId);
283 if idx = -1 then
284 result := nil
285 else
286 result := LayeredBitmap.LayerBitmap[idx];
287 end;
288
TImageState.GetLayerIdnull289 function TImageState.GetLayerId(Index: integer): integer;
290 begin
291 if LayeredBitmap = nil then
292 result := -1
293 else
294 result := LayeredBitmap.LayerUniqueId[index];
295 end;
296
GetLayerNamenull297 function TImageState.GetLayerName(Index: integer): string;
298 begin
299 if LayeredBitmap = nil then
300 result := ''
301 else
302 result := LayeredBitmap.LayerName[index];
303 end;
304
GetLayerOffsetnull305 function TImageState.GetLayerOffset(Index: integer): TPoint;
306 begin
307 if LayeredBitmap = nil then
308 result := point(0,0)
309 else
310 result := LayeredBitmap.LayerOffset[index];
311 end;
312
TImageState.GetLayerOpacitynull313 function TImageState.GetLayerOpacity(Index: integer): byte;
314 begin
315 if LayeredBitmap = nil then
316 result := 255
317 else
318 result := LayeredBitmap.LayerOpacity[index];
319 end;
320
TImageState.GetLayerOriginalnull321 function TImageState.GetLayerOriginal(Index: integer): TBGRALayerCustomOriginal;
322 begin
323 if LayeredBitmap = nil then
324 result := nil
325 else
326 result := LayeredBitmap.LayerOriginal[Index];
327 end;
328
GetLayerOriginalDefinednull329 function TImageState.GetLayerOriginalDefined(Index: integer): boolean;
330 begin
331 if LayeredBitmap = nil then
332 result := false
333 else
334 result := LayeredBitmap.LayerOriginalGuid[Index] <> GUID_NULL;
335 end;
336
TImageState.GetLayerOriginalKnownnull337 function TImageState.GetLayerOriginalKnown(Index: integer): boolean;
338 begin
339 if LayeredBitmap = nil then
340 result := false
341 else
342 result := LayeredBitmap.LayerOriginalKnown[Index];
343 end;
344
TImageState.GetLayerOriginalMatrixnull345 function TImageState.GetLayerOriginalMatrix(Index: integer): TAffineMatrix;
346 begin
347 if LayeredBitmap = nil then
348 result := AffineMatrixIdentity
349 else
350 result := LayeredBitmap.LayerOriginalMatrix[Index];
351 end;
352
GetLayerVisiblenull353 function TImageState.GetLayerVisible(Index: integer): boolean;
354 begin
355 if LayeredBitmap = nil then
356 result := false
357 else
358 result := LayeredBitmap.LayerVisible[Index];
359 end;
360
GetLinearBlendnull361 function TImageState.GetLinearBlend: boolean;
362 begin
363 if LayeredBitmap = nil then
364 result := true
365 else
366 result := LayeredBitmap.LinearBlend;
367 end;
368
TImageState.GetNbLayersnull369 function TImageState.GetNbLayers: integer;
370 begin
371 if LayeredBitmap = nil then
372 result := 0
373 else
374 result := LayeredBitmap.NbLayers;
375 end;
376
GetWidthnull377 function TImageState.GetWidth: integer;
378 begin
379 if LayeredBitmap= nil then
380 result := 0
381 else
382 result := LayeredBitmap.Width;
383 end;
384
385 procedure TImageState.LayeredActionDone(Sender: TObject);
386 begin
387 if Assigned(FOnActionDone) then
388 FOnActionDone(self);
389 end;
390
391 procedure TImageState.LayeredActionProgress(ASender: TObject;
392 AProgressPercent: integer);
393 begin
394 if Assigned(FOnActionProgress) then
395 FOnActionProgress(self, AProgressPercent);
396 end;
397
398 procedure TImageState.OriginalChange(ASender: TObject;
399 AOriginal: TBGRALayerCustomOriginal; var ADiff: TBGRAOriginalDiff);
400 begin
401 If Assigned(FOnOriginalChange) then
402 begin
403 if DiscardOriginalDiff then FreeAndNil(ADiff);
404 FOnOriginalChange(self, AOriginal, ADiff);
405 end;
406 end;
407
408 procedure TImageState.OriginalEditingChange(ASender: TObject;
409 AOriginal: TBGRALayerCustomOriginal);
410 begin
411 If Assigned(FOnOriginalEditingChange) then
412 FOnOriginalEditingChange(self, AOriginal);
413 end;
414
415 procedure TImageState.OriginalLoadError(ASender: TObject; AError: string;
416 var ARaise: boolean);
417 begin
418 If Assigned(FOnOriginalLoadError) then
419 FOnOriginalLoadError(self, AError, ARaise);
420 end;
421
422 procedure TImageState.SelectImageLayer(AValue: TBGRABitmap);
423 var
424 i: Integer;
425 begin
426 if LayeredBitmap = nil then exit;
427
428 for i := 0 to NbLayers-1 do
429 if LayeredBitmap.LayerBitmap[i] = AValue then
430 begin
431 selectedLayerId := LayeredBitmap.LayerUniqueId[i];
432 exit;
433 end;
434 selectedLayerId := -1;
435 end;
436
437 procedure TImageState.SelectImageLayerByIndex(AValue: integer);
438 begin
439 if (LayeredBitmap = nil) or (AValue < 0) or (AValue >= LayeredBitmap.NbLayers) then
440 begin
441 selectedLayerId := -1;
442 end else
443 begin
444 selectedLayerId := LayeredBitmap.LayerUniqueId[AValue];
445 LayeredBitmap.Unfreeze(AValue);
446 end;
447 end;
448
449 procedure TImageState.SetLayeredBitmap(AValue: TBGRALayeredBitmap);
450 begin
451 if FLayeredBitmap=AValue then Exit;
452
453 if Assigned(FLayeredBitmap) then
454 begin
455 FLayeredBitmap.OnOriginalChange:= nil;
456 FLayeredBitmap.OnOriginalEditingChange:= nil;
457 FLayeredBitmap.OnActionProgress:= nil;
458 FLayeredBitmap.OnActionDone:= nil;
459 FLayeredBitmap.OnOriginalLoadError:= nil;
460 end;
461 FLayeredBitmap:=AValue;
462 if Assigned(FLayeredBitmap) then
463 begin
464 FLayeredBitmap.OnOriginalChange:= @OriginalChange;
465 FLayeredBitmap.OnOriginalEditingChange:= @OriginalEditingChange;
466 FLayeredBitmap.OnActionProgress:= @LayeredActionProgress;
467 FLayeredBitmap.OnActionDone:=@LayeredActionDone;
468 FLayeredBitmap.OnOriginalLoadError:=@OriginalLoadError;
469 end;
470 end;
471
TImageState.SetLayerNamenull472 function TImageState.SetLayerName(Index: integer; AValue: string): TCustomImageDifference;
473 begin
474 if LayeredBitmap <> nil then
475 begin
476 if LayerName[Index] <> AValue then
477 result := TSetLayerNameStateDifference.Create(self,LayeredBitmap.LayerUniqueId[index],AValue)
478 else
479 result := nil;
480 end
481 else
482 result := nil;
483 end;
484
SetLayerOffsetnull485 function TImageState.SetLayerOffset(Index: integer; AValue: TPoint
486 ): TCustomImageDifference;
487 begin
488 if LayeredBitmap <> nil then
489 begin
490 if (LayerOffset[index].x <> AValue.x) or (LayerOffset[index].y <> AValue.y) then
491 result := TSetLayerOffsetStateDifference.Create(self,LayeredBitmap.LayerUniqueId[index],AValue)
492 else
493 result := nil;
494 end
495 else
496 result := nil;
497 end;
498
SetLayerOpacitynull499 function TImageState.SetLayerOpacity(Index: integer; AValue: byte
500 ): TCustomImageDifference;
501 begin
502 if LayeredBitmap <> nil then
503 begin
504 if LayerOpacity[index] <> AValue then
505 result := TSetLayerOpacityStateDifference.Create(self,LayeredBitmap.LayerUniqueId[index],AValue)
506 else
507 result := nil;
508 end
509 else
510 result := nil;
511 end;
512
SetLayerVisiblenull513 function TImageState.SetLayerVisible(Index: integer; AValue: boolean
514 ): TCustomImageDifference;
515 begin
516 if LayeredBitmap <> nil then
517 begin
518 if LayerVisible[Index] <> AValue then
519 result := TSetLayerVisibleStateDifference.Create(self,LayeredBitmap.LayerUniqueId[index],AValue)
520 else
521 result := nil;
522 end
523 else
524 result := nil;
525 end;
526
SetBlendOpnull527 function TImageState.SetBlendOp(Index: integer; AValue: TBlendOperation
528 ): TCustomImageDifference;
529 begin
530 if LayeredBitmap <> nil then
531 begin
532 if BlendOperation[index] <> Avalue then
533 result := TSetLayerBlendOpStateDifference.Create(self,LayeredBitmap.LayerUniqueId[index],AValue)
534 else
535 result := nil;
536 end
537 else
538 result := nil;
539 end;
540
541 procedure TImageState.SetLinearBlend(AValue: boolean);
542 begin
543 if LayeredBitmap <> nil then
544 LayeredBitmap.LinearBlend := AValue;
545 end;
546
547 procedure TImageState.SetOnActionDone(AValue: TNotifyEvent);
548 begin
549 if FOnActionDone=AValue then Exit;
550 FOnActionDone:=AValue;
551 end;
552
553 procedure TImageState.SetOnActionProgress(AValue: TLayeredActionProgressEvent);
554 begin
555 if FOnActionProgress=AValue then Exit;
556 FOnActionProgress:=AValue;
557 end;
558
559 procedure TImageState.SetOnSizeChanged(AValue: TNotifyEvent);
560 begin
561 if FOnSizeChanged=AValue then Exit;
562 FOnSizeChanged:=AValue;
563 end;
564
565 procedure TImageState.SetSelectionMask(AValue: TBGRABitmap);
566 begin
567 If AValue = FSelectionMask then exit;
568 FSelectionMask := AValue;
569 DiscardSelectionMaskBoundsCompletely;
570 end;
571
MakeLayerNamenull572 function TImageState.MakeLayerName: string;
573
LayerNameUsednull574 function LayerNameUsed(AName: string): Boolean;
575 var
576 j: Integer;
577 begin
578 if LayeredBitmap = nil then
579 result := false else
580 begin
581 for j := 0 to NbLayers-1 do
582 if trim(LayerName[j]) = trim(AName) then exit(true);
583 result := false;
584 end;
585 end;
586
587 var i: integer;
588 begin
589 for i := 1 to 1000 do
590 begin
591 result := rsLayer + inttostr(i);
592 if not LayerNameUsed(result) and not LayerNameUsed('Layer' + inttostr(i)) then exit;
593 end;
594 end;
595
596 procedure TImageState.CheckSizeChanged(APrevSize: TSize);
597 begin
598 if GetSize <> APrevSize then NotifySizeChanged;
599 end;
600
GetSizenull601 function TImageState.GetSize: TSize;
602 begin
603 if Assigned(FLayeredBitmap) then
604 result := Size(FLayeredBitmap.Width, FLayeredBitmap.Height)
605 else result := Size(0,0);
606 end;
607
608 procedure TImageState.SetLayerBitmap(layer: integer; ABitmap: TBGRABitmap;
609 AOwned: boolean);
610 begin
611 if LayeredBitmap <> nil then
612 LayeredBitmap.SetLayerBitmap(layer,ABitmap,AOwned);
613 end;
614
GetOrCreateSelectionLayernull615 function TImageState.GetOrCreateSelectionLayer: TBGRABitmap;
616 begin
617 if SelectionMask = nil then
618 raise Exception.Create(rsNoActiveSelection) else
619 begin
620 if SelectionLayer = nil then
621 begin
622 SelectionLayer := TBGRABitmap.Create(Width,Height);
623 FLastSelectionLayerBounds := EmptyRect;
624 FLastSelectionLayerBoundsIsDefined := bsDefined;
625 end;
626 result := SelectionLayer;
627 end;
628 end;
629
630 procedure TImageState.ReplaceSelectionLayer(bmp: TBGRABitmap; AOwned: boolean);
631 begin
632 if (SelectionMask <> nil) then
633 begin
634 if AOwned or (bmp= nil) then
635 begin
636 if (SelectionLayer <> nil) and (SelectionLayer <> bmp) then FreeAndNil(SelectionLayer);
637 SelectionLayer := bmp;
638 end
639 else
640 begin
641 if SelectionLayer <> nil then FreeAndNil(SelectionLayer);
642 SelectionLayer := bmp.Duplicate(True) as TBGRABitmap;
643 end;
644 end else
645 begin
646 if (bmp = nil) then FreeAndNil(SelectionLayer);
647 if AOwned and (bmp <>nil) then bmp.Free; //ignore if there is no active selection
648 end;
649 end;
650
651 procedure TImageState.ComputeTransformedSelectionLayer(out
652 ANewLayer: TBGRABitmap; out ALeft, ATop: integer);
653 var
654 r: TRect;
655 begin
656 if SelectionLayer = nil then
657 begin
658 ANewLayer := nil;
659 ALeft := 0;
660 ATop := 0;
661 end else
662 begin
663 r := SelectionLayer.GetImageAffineBounds(FSelectionTransform, GetSelectionLayerBounds);
664 ANewLayer := TBGRABitmap.Create(r.Width,r.Height);
665 ANewLayer.PutImageAffine(AffineMatrixTranslation(-r.Left,-r.Top)*FSelectionTransform, SelectionLayer, rfHalfCosine);
666 ALeft := r.Left;
667 ATop := r.Top;
668 end;
669 end;
670
671 procedure TImageState.DiscardSelectionLayerBounds(const AChangeRect: TRect);
672 begin
673 if FLastSelectionLayerBoundsIsDefined in[bsDefined,bsWithinCurrent] then
674 begin
675 FLastSelectionLayerBounds := RectUnion(FLastSelectionLayerBounds, AChangeRect);
676 FLastSelectionLayerBoundsIsDefined := bsWithinCurrent;
677 end;
678 end;
679
680 procedure TImageState.DiscardSelectionLayerBoundsCompletely;
681 begin
682 FLastSelectionLayerBoundsIsDefined := bsUndefined;
683 end;
684
GetSelectionLayerBoundsnull685 function TImageState.GetSelectionLayerBounds: TRect;
686 begin
687 if FLastSelectionLayerBoundsIsDefined = bsDefined then
688 result := FLastSelectionLayerBounds
689 else
690 if SelectionLayer = nil then
691 begin
692 result := EmptyRect;
693 FLastSelectionLayerBounds := result;
694 FLastSelectionLayerBoundsIsDefined := bsDefined;
695 end else
696 begin
697 if FLastSelectionLayerBoundsIsDefined = bsWithinCurrent then
698 result := SelectionLayer.GetImageBoundsWithin(FLastSelectionLayerBounds)
699 else result := SelectionLayer.GetImageBounds;
700 FLastSelectionLayerBounds := result;
701 FLastSelectionLayerBoundsIsDefined := bsDefined;
702 end;
703 end;
704
SelectionLayerEmptynull705 function TImageState.SelectionLayerEmpty: boolean;
706 begin
707 result := IsRectEmpty(GetSelectionLayerBounds);
708 end;
709
710 procedure TImageState.SetSize(AWidth, AHeight: integer);
711 var
712 prevSize: TSize;
713 begin
714 if LayeredBitmap <> nil then
715 begin
716 prevSize := GetSize;
717 LayeredBitmap.SetSize(AWidth,AHeight);
718 CheckSizeChanged(prevSize);
719 end;
720 end;
721
722 procedure TImageState.NotifySizeChanged;
723 begin
724 if Assigned(OnSizeChanged) then OnSizeChanged(self);
725 end;
726
727 procedure TImageState.PrepareForRendering;
728 begin
729 if LayeredBitmap <> nil then
730 LayeredBitmap.FreezeExceptOneLayer(SelectedImageLayerIndex);
731 end;
732
ComputeFlatImageWithoutSelectionnull733 function TImageState.ComputeFlatImageWithoutSelection(ASeparateXorMask: boolean): TBGRABitmap;
734 begin
735 if LayeredBitmap <> nil then
736 result := LayeredBitmap.ComputeFlatImage(ASeparateXorMask)
737 else
738 result := TBGRABitmap.Create(Width,Height);
739 end;
740
741 procedure TImageState.Assign(AValue: TBGRABitmap; AOwned: boolean);
742 var
743 xorMask: TBGRABitmap;
744 idx: Integer;
745 prevSize: TSize;
746 begin
747 prevSize := GetSize;
748
749 if LayeredBitmap = nil then
750 SetLayeredBitmap(TBGRALayeredBitmap.Create);
751
752 LayeredBitmap.Clear;
753 LayeredBitmap.SetSize(AValue.Width,AValue.Height);
754 if AOwned then
755 begin
756 idx := LayeredBitmap.AddOwnedLayer(AValue);
757 LayeredBitmap.LayerName[idx] := MakeLayerName;
758 if Assigned(AValue.XorMask) then
759 begin
760 xorMask := TBGRABitmap.Create(AValue.XorMask);
761 xorMask.AlphaFill(255);
762 xorMask.ReplaceColor(BGRABlack,BGRAPixelTransparent);
763 LayeredBitmap.LayerName[LayeredBitmap.AddOwnedLayer(xorMask,boXor)] := 'Xor';
764 AValue.DiscardXorMask;
765 end;
766 end
767 else
768 begin
769 idx := LayeredBitmap.AddLayer(AValue);
770 LayeredBitmap.LayerName[idx] := MakeLayerName;
771 if Assigned(AValue.XorMask) then
772 begin
773 xorMask := AValue.XorMask.Duplicate as TBGRABitmap;
774 xorMask.AlphaFill(255);
775 xorMask.ReplaceColor(BGRABlack,BGRAPixelTransparent);
776 LayeredBitmap.LayerName[LayeredBitmap.AddOwnedLayer(xorMask,boXor)] := 'Xor';
777 end;
778 end;
779 SelectedImageLayerIndex := 0;
780
781 CheckSizeChanged(prevSize);
782 end;
783
784 procedure TImageState.Assign(AValue: TBGRACustomLayeredBitmap; AOwned: boolean);
785 var
786 prevSize: TSize;
787 begin
788 if AOwned and (AValue is TBGRALayeredBitmap) then
789 begin
790 prevSize := GetSize;
791 FreeAndNil(FLayeredBitmap);
792 SetLayeredBitmap(TBGRALayeredBitmap(AValue));
793 CheckSizeChanged(prevSize);
794 end else
795 begin
796 LayeredBitmap.Assign(AValue, true, true);
797 if AOwned then AValue.Free;
798 end;
799 if NbLayers > 0 then
800 begin
801 SelectedImageLayerIndex := 0
802 end
803 else
804 SelectedImageLayerIndex := -1;
805 end;
806
807 procedure TImageState.Assign(AValue: TImageState; AOwned: boolean);
808 var
809 layered: TBGRALayeredBitmap;
810 begin
811 layered := AValue.LayeredBitmap;
812 Assign(layered, AOwned);
813 if AOwned then AValue.SetLayeredBitmap(nil);
814 BGRAReplace(FSelectionMask, AValue.SelectionMask);
815 if AOwned then AValue.SelectionMask := nil;
816 BGRAReplace(SelectionLayer, AValue.SelectionLayer);
817 if AOwned then AValue.SelectionLayer := nil;
818 if AOwned then AValue.Free;
819 end;
820
821 procedure TImageState.RemoveSelection;
822 begin
823 FreeAndNil(SelectionLayer);
824 FreeAndNil(FSelectionMask);
825 FSelectionTransform := AffineMatrixIdentity;
826 end;
827
828 procedure TImageState.ReplaceSelection(ASelectionMask,
829 ASelectionLayer: TBGRABitmap);
830 begin
831 if ASelectionMask<>FSelectionMask then
832 begin
833 FSelectionMask.Free;
834 FSelectionMask := ASelectionMask;
835 end;
836 if ASelectionLayer<>SelectionLayer then
837 begin
838 SelectionLayer.Free;
839 SelectionLayer := ASelectionLayer;
840 end;
841 end;
842
TImageState.AssignWithUndonull843 function TImageState.AssignWithUndo(AValue: TBGRACustomLayeredBitmap;
844 AOwned: boolean; ASelectedLayerIndex: integer): TCustomImageDifference;
845 begin
846 if LayeredBitmap = nil then
847 result := nil
848 else
849 result := TAssignStateDifference.Create(self, AValue, AOwned, ASelectedLayerIndex);
850 end;
851
TImageState.AssignWithUndonull852 function TImageState.AssignWithUndo(AValue: TBGRACustomLayeredBitmap;
853 AOwned: boolean; ASelectedLayerIndex: integer; ACurrentSelection: TBGRABitmap;
854 ASelectionLayer: TBGRABitmap): TCustomImageDifference;
855 begin
856 if LayeredBitmap = nil then
857 result := nil
858 else
859 result := TAssignStateDifference.Create(self, AValue, AOwned, ASelectedLayerIndex, ACurrentSelection, ASelectionLayer);
860 end;
861
TImageState.AssignWithUndonull862 function TImageState.AssignWithUndo(AState: TImageState; AOwned: boolean): TCustomImageDifference;
863 begin
864 result := AssignWithUndo(AState.LayeredBitmap, AOwned, SelectedImageLayerIndex, AState.SelectionMask, AState.SelectionLayer);
865 if AOwned then AState.Free;
866 end;
867
GetUndoAfterAssignnull868 function TImageState.GetUndoAfterAssign(ABackup: TImageState): TCustomImageDifference;
869 begin
870 if LayeredBitmap = nil then
871 result := nil
872 else
873 result := TAssignStateDifferenceAfter.Create(self, ABackup);
874 end;
875
876 procedure TImageState.LoadFromStream(AStream: TStream);
877 var loadedLayerIndex: integer;
878 loadedLayeredBitmap: TBGRALayeredBitmap;
879 begin
880 loadedLayeredBitmap := LoadLayersFromStream(AStream, loadedLayerIndex, False);
881 Assign(loadedLayeredBitmap,True);
882 SelectedImageLayerIndex:= loadedLayerIndex;
883 end;
884
885 procedure TImageState.SaveToStream(AStream: TStream);
886 begin
887 SaveLayersToStream(AStream, LayeredBitmap, SelectedImageLayerIndex, lzpRLE);
888 end;
889
890 procedure TImageState.SaveToStreamAs(AStream: TStream; AFormat: TBGRAImageFormat);
891 var
892 i: Integer;
893 curGuid: TGuid;
894 begin
895 if LayeredBitmap <> nil then
896 begin
897 if AFormat = ifLazPaint then
898 begin
899 curGuid := LayeredBitmap.LayerOriginalGuid[GetCurrentLayerIndex];
900 for i := 0 to LayeredBitmap.OriginalCount-1 do
901 if LayeredBitmap.OriginalGuid[i] <> curGuid then
902 LayeredBitmap.UnloadOriginal(i);
903 end;
904 LayeredBitmap.SaveToStreamAs(AStream, SuggestImageExtension(AFormat));
905 end;
906 end;
907
908 procedure TImageState.SaveOriginalToStream(AStream: TStream);
909 begin
910 LayeredBitmap.SaveOriginalToStream(
911 LayeredBitmap.LayerOriginalGuid[SelectedImageLayerIndex],
912 AStream);
913 end;
914
915 procedure TImageState.SaveToFile(AFilenameUTF8: string);
916 var
917 s: TStream;
918 begin
919 if LayeredBitmap <> nil then
920 begin
921 s := FileManager.CreateFileStream(AFilenameUTF8, fmCreate);
922 try
923 LayeredBitmap.SaveToStream(s);
924 finally
925 s.Free;
926 end;
927 end;
928 end;
929
TImageState.AddNewLayernull930 function TImageState.AddNewLayer(ALayer: TBGRABitmap; AName: string; AOffset: TPoint; ABlendOp: TBlendOperation; AOpacity: byte): TCustomImageDifference;
931 var
932 idxLayer: Integer;
933 begin
934 if AName = '' then AName := MakeLayerName;
935 //no undo if no previous image
936 if LayeredBitmap = nil then
937 begin
938 SetLayeredBitmap(TBGRALayeredBitmap.Create);
939 idxLayer := LayeredBitmap.AddOwnedLayer(ALayer, ABlendOp, AOpacity);
940 LayeredBitmap.LayerOffset[idxLayer] := AOffset;
941 LayeredBitmap.LayerName[idxLayer] := AName;
942 result := nil;
943 end else
944 begin
945 result := TAddLayerStateDifference.Create(self, ALayer, AName, AOffset, ABlendOp, AOpacity);
946 ALayer.Free;
947 end;
948 end;
949
TImageState.AddNewLayernull950 function TImageState.AddNewLayer(AOriginal: TBGRALayerCustomOriginal;
951 AName: string; ABlendOp: TBlendOperation; AMatrix: TAffineMatrix; AOpacity: byte): TCustomImageDifference;
952 var
953 idx: Integer;
954 begin
955 if AName = '' then AName := MakeLayerName;
956 //no undo if no previous image
957 if LayeredBitmap = nil then
958 begin
959 SetLayeredBitmap(TBGRALayeredBitmap.Create);
960 idx := LayeredBitmap.AddLayerFromOwnedOriginal(AOriginal, ABlendOp, AOpacity);
961 LayeredBitmap.LayerOriginalMatrix[idx] := AMatrix;
962 LayeredBitmap.LayerName[idx] := AName;
963 LayeredBitmap.RenderLayerFromOriginal(idx);
964 result := nil;
965 end else
966 result := TAddLayerFromOwnedOriginalStateDifference.Create(self, AOriginal, AName, ABlendOp, AMatrix, AOpacity);
967 end;
968
DuplicateLayernull969 function TImageState.DuplicateLayer: TCustomImageDifference;
970 begin
971 if LayeredBitmap = nil then
972 result := nil
973 else
974 result := TDuplicateLayerStateDifference.Create(self, true);
975 end;
976
MergerLayerOvernull977 function TImageState.MergerLayerOver(ALayerOverIndex: integer): TCustomImageDifference;
978 begin
979 if (LayeredBitmap = nil) or (ALayerOverIndex <= 0) or (ALayerOverIndex >= LayeredBitmap.NbLayers) then
980 result := nil
981 else
982 result := TMergeLayerOverStateDifference.Create(self, ALayerOverIndex);
983 end;
984
TImageState.MoveLayernull985 function TImageState.MoveLayer(AFromIndex, AToIndex: integer): TCustomImageDifference;
986 begin
987 if LayeredBitmap = nil then
988 result := nil
989 else
990 result := TMoveLayerStateDifference.Create(self, AFromIndex, AToIndex);
991 end;
992
TImageState.RemoveLayernull993 function TImageState.RemoveLayer: TCustomImageDifference;
994 begin
995 if LayeredBitmap = nil then
996 result := nil
997 else
998 begin
999 result := TRemoveLayerStateDifference.Create(self, True);
1000 end;
1001 end;
1002
DiscardOriginalnull1003 function TImageState.DiscardOriginal(ACreateUndo: boolean): TCustomImageDifference;
1004 begin
1005 if ACreateUndo then
1006 result := TDiscardOriginalDifference.Create(self, SelectedImageLayerIndex, true)
1007 else
1008 begin
1009 LayeredBitmap.LayerOriginalGuid[SelectedImageLayerIndex] := GUID_NULL;
1010 LayeredBitmap.LayerOriginalMatrix[SelectedImageLayerIndex] := AffineMatrixIdentity;
1011 LayeredBitmap.RemoveUnusedOriginals;
1012 end;
1013 end;
1014
HorizontalFlipnull1015 function TImageState.HorizontalFlip: TCustomImageDifference;
1016 begin
1017 if LayeredBitmap = nil then
1018 result := nil
1019 else
1020 result := TInversibleStateDifference.Create(self, iaHorizontalFlip);
1021 end;
1022
HorizontalFlipnull1023 function TImageState.HorizontalFlip(ALayerIndex: integer): TCustomImageDifference;
1024 begin
1025 if LayeredBitmap = nil then
1026 result := nil
1027 else
1028 result := TInversibleStateDifference.Create(self, iaHorizontalFlipLayer, ALayerIndex);
1029 end;
1030
TImageState.VerticalFlipnull1031 function TImageState.VerticalFlip: TCustomImageDifference;
1032 begin
1033 if LayeredBitmap = nil then
1034 result := nil
1035 else
1036 result := TInversibleStateDifference.Create(self, iaVerticalFlip);
1037 end;
1038
TImageState.VerticalFlipnull1039 function TImageState.VerticalFlip(ALayerIndex: integer): TCustomImageDifference;
1040 begin
1041 if LayeredBitmap = nil then
1042 result := nil
1043 else
1044 result := TInversibleStateDifference.Create(self, iaVerticalFlipLayer, ALayerIndex);
1045 end;
1046
1047 procedure TImageState.QuerySelectionMask;
1048 begin
1049 if SelectionMask = nil then
1050 begin
1051 SelectionMask := TBGRABitmap.Create(Width,Height, BGRABlack);
1052 FLastSelectionMaskBoundsIsDefined := bsDefined;
1053 FLastSelectionMaskBounds := EmptyRect;
1054 end;
1055 end;
1056
1057 procedure TImageState.DiscardSelectionMaskBounds(const AChangeRect: TRect);
1058 begin
1059 if FLastSelectionMaskBoundsIsDefined in[bsDefined,bsWithinCurrent] then
1060 begin
1061 FLastSelectionMaskBounds := RectUnion(FLastSelectionMaskBounds, AChangeRect);
1062 FLastSelectionMaskBoundsIsDefined := bsWithinCurrent;
1063 end;
1064 end;
1065
1066 procedure TImageState.DiscardSelectionMaskBoundsCompletely;
1067 begin
1068 FLastSelectionMaskBoundsIsDefined := bsUndefined;
1069 end;
1070
GetSelectionMaskBoundsnull1071 function TImageState.GetSelectionMaskBounds: TRect;
1072 begin
1073 if FLastSelectionMaskBoundsIsDefined = bsDefined then
1074 result := FLastSelectionMaskBounds
1075 else
1076 if SelectionMask = nil then
1077 begin
1078 result := EmptyRect;
1079 FLastSelectionMaskBounds := result;
1080 FLastSelectionMaskBoundsIsDefined := bsDefined;
1081 end else
1082 begin
1083 if FLastSelectionMaskBoundsIsDefined = bsWithinCurrent then
1084 result := SelectionMask.GetImageBoundsWithin(FLastSelectionMaskBounds, cGreen)
1085 else result := SelectionMask.GetImageBounds(cGreen);
1086 FLastSelectionMaskBounds := result;
1087 FLastSelectionMaskBoundsIsDefined := bsDefined;
1088 end;
1089 end;
1090
SelectionMaskEmptynull1091 function TImageState.SelectionMaskEmpty: boolean;
1092 begin
1093 result := IsRectEmpty(GetSelectionMaskBounds);
1094 end;
1095
SelectionMaskEmptyComputednull1096 function TImageState.SelectionMaskEmptyComputed: boolean;
1097 begin
1098 result := FLastSelectionMaskBoundsIsDefined = bsDefined;
1099 end;
1100
TImageState.GetTransformedSelectionMaskBoundsnull1101 function TImageState.GetTransformedSelectionMaskBounds: TRect;
1102 begin
1103 if SelectionMaskEmpty then
1104 result := EmptyRect
1105 else
1106 begin
1107 result := SelectionMask.GetImageAffineBounds(SelectionTransform, GetSelectionMaskBounds);
1108 end;
1109 end;
1110
1111 procedure TImageState.ComputeTransformedSelectionMask(out ANewMask: TBGRABitmap; out ALeft,ATop: integer);
1112 var
1113 r: TRect;
1114 begin
1115 if SelectionMask = nil then
1116 begin
1117 ANewMask := nil;
1118 ALeft := 0;
1119 ATop := 0;
1120 end else
1121 begin
1122 r := SelectionMask.GetImageAffineBounds(FSelectionTransform, GetSelectionMaskBounds);
1123 ANewMask := TBGRABitmap.Create(r.Width,r.Height,BGRABlack);
1124 ANewMask.PutImageAffine(AffineMatrixTranslation(-r.Left,-r.Top)*FSelectionTransform, SelectionMask, rfHalfCosine, dmLinearBlend);
1125 ALeft := r.Left;
1126 ATop := r.Top;
1127 end;
1128 end;
1129
TImageState.SwapRedBluenull1130 function TImageState.SwapRedBlue: TCustomImageDifference;
1131 var
1132 newImg: TBGRALayeredBitmap;
1133 newLayer: TBGRABitmap;
1134 idxLayer, i: Integer;
1135 begin
1136 if LayeredBitmap = nil then
1137 result := nil
1138 else
1139 begin
1140 if HasOriginals then
1141 begin
1142 newImg := TBGRALayeredBitmap.Create(Width,Height);
1143 for i := 0 to NbLayers-1 do
1144 begin
1145 newLayer := TBGRABitmap.Create(Width,Height);
1146 newLayer.PutImage(LayerOffset[i].x,LayerOffset[i].y, LayerBitmap[i], dmSet);
1147 newLayer.SwapRedBlue;
1148 idxLayer := newImg.AddOwnedLayer(newLayer, BlendOperation[i], LayerOpacity[i]);
1149 newImg.LayerName[idxLayer] := LayerName[i];
1150 end;
1151 result := AssignWithUndo(newImg, true, SelectedImageLayerIndex);
1152 end else
1153 result := TInversibleStateDifference.Create(self, iaSwapRedBlue);
1154 end;
1155 end;
1156
TImageState.LinearNegativenull1157 function TImageState.LinearNegative: TCustomImageDifference;
1158 var
1159 newImg: TBGRALayeredBitmap;
1160 newLayer: TBGRABitmap;
1161 idxLayer, i: Integer;
1162 begin
1163 if LayeredBitmap = nil then
1164 result := nil
1165 else
1166 begin
1167 if HasOriginals then
1168 begin
1169 newImg := TBGRALayeredBitmap.Create(Width,Height);
1170 for i := 0 to NbLayers-1 do
1171 begin
1172 newLayer := TBGRABitmap.Create(Width,Height);
1173 newLayer.PutImage(LayerOffset[i].x,LayerOffset[i].y, LayerBitmap[i], dmSet);
1174 newLayer.LinearNegative;
1175 idxLayer := newImg.AddOwnedLayer(newLayer, BlendOperation[i], LayerOpacity[i]);
1176 newImg.LayerName[idxLayer] := LayerName[i];
1177 end;
1178 result := AssignWithUndo(newImg, true, SelectedImageLayerIndex);
1179 end else
1180 result := TInversibleStateDifference.Create(self, iaLinearNegative);
1181 end;
1182 end;
1183
TImageState.Negativenull1184 function TImageState.Negative: TCustomImageDifference;
1185 var
1186 newImg: TBGRALayeredBitmap;
1187 newLayer: TBGRABitmap;
1188 idxLayer, i: Integer;
1189 begin
1190 newImg := TBGRALayeredBitmap.Create(Width,Height);
1191 for i := 0 to NbLayers-1 do
1192 begin
1193 newLayer := TBGRABitmap.Create(Width,Height);
1194 newLayer.PutImage(LayerOffset[i].x,LayerOffset[i].y, LayerBitmap[i], dmSet);
1195 newLayer.Negative;
1196 idxLayer := newImg.AddOwnedLayer(newLayer, BlendOperation[i], LayerOpacity[i]);
1197 newImg.LayerName[idxLayer] := LayerName[i];
1198 end;
1199 result := AssignWithUndo(newImg, true, SelectedImageLayerIndex);
1200 end;
1201
TImageState.ClearLayernull1202 function TImageState.ClearLayer: TCustomImageDifference;
1203 begin
1204 if (LayeredBitmap = nil) or SelectedImageLayer.Empty then
1205 result := nil
1206 else
1207 begin
1208 result := TReplaceLayerByCustomOriginalDifference.Create(self,
1209 SelectedImageLayerIndex, true,
1210 TVectorOriginal.Create);
1211 end;
1212 end;
1213
RotateCWnull1214 function TImageState.RotateCW: TCustomImageDifference;
1215 begin
1216 if LayeredBitmap = nil then
1217 result := nil
1218 else
1219 result := TInversibleStateDifference.Create(self, iaRotateCW);
1220 end;
1221
TImageState.RotateCCWnull1222 function TImageState.RotateCCW: TCustomImageDifference;
1223 begin
1224 if LayeredBitmap = nil then
1225 result := nil
1226 else
1227 result := TInversibleStateDifference.Create(self, iaRotateCCW);
1228 end;
1229
TImageState.Rotate180null1230 function TImageState.Rotate180: TCustomImageDifference;
1231 begin
1232 if LayeredBitmap = nil then
1233 result := nil
1234 else
1235 result := TInversibleStateDifference.Create(self, iaRotate180);
1236 end;
1237
TImageState.ComputeLayerOffsetDifferencenull1238 function TImageState.ComputeLayerOffsetDifference(AOffsetX, AOffsetY: integer): TCustomImageDifference;
1239 begin
1240 result := TApplyLayerOffsetStateDifference.Create(self, LayeredBitmap.LayerUniqueId[SelectedImageLayerIndex], AOffsetX,AOffsetY, false);
1241 end;
1242
TImageState.ComputeSelectionTransformDifferencenull1243 function TImageState.ComputeSelectionTransformDifference: TCustomImageDifference;
1244 begin
1245 result := TSelectionTransformDifference.Create(self, false);
1246 end;
1247
TImageState.ComputeLayerMatrixDifferencenull1248 function TImageState.ComputeLayerMatrixDifference(AIndex: integer; APrevMatrix,
1249 ANewMatrix: TAffineMatrix): TCustomImageDifference;
1250 begin
1251 result := TSetLayerMatrixDifference.Create(self, LayeredBitmap.LayerUniqueId[AIndex], APrevMatrix,ANewMatrix);
1252 end;
1253
ComputeLayerDifferencenull1254 function TImageState.ComputeLayerDifference(APreviousImage: TBGRABitmap;
1255 APreviousImageDefined: boolean; APreviousSelection: TBGRABitmap;
1256 APreviousSelectionDefined: boolean; APreviousSelectionLayer: TBGRABitmap;
1257 APreviousSelectionLayerDefined: boolean): TCustomImageDifference;
1258 begin
1259 if LayeredBitmap = nil then
1260 result := nil
1261 else
1262 result := TImageLayerStateDifference.Create(self, APreviousImage, APreviousImageDefined,
1263 APreviousSelection, APreviousSelectionDefined, APreviousSelectionLayer, APreviousSelectionLayerDefined);
1264 end;
1265
ComputeLayerDifferencenull1266 function TImageState.ComputeLayerDifference(APreviousImage: TBGRABitmap;
1267 APreviousImageChangeRect: TRect; APreviousSelection: TBGRABitmap;
1268 APreviousSelectionChangeRect: TRect; APreviousSelectionLayer: TBGRABitmap;
1269 APreviousSelectionLayerChangeRect: TRect): TCustomImageDifference;
1270 begin
1271 if LayeredBitmap = nil then
1272 result := nil
1273 else
1274 result := TImageLayerStateDifference.Create(self, APreviousImage, APreviousImageChangeRect,
1275 APreviousSelection, APreviousSelectionChangeRect, APreviousSelectionLayer, APreviousSelectionLayerChangeRect);
1276 end;
1277
TImageState.GetLayeredBitmapCopynull1278 function TImageState.GetLayeredBitmapCopy: TBGRALayeredBitmap;
1279 begin
1280 result := LayeredBitmap.Duplicate;
1281 end;
1282
ComputeFlatImagenull1283 function TImageState.ComputeFlatImage(AFromLayer, AToLayer: integer; ASeparateXorMask: boolean): TBGRABitmap;
1284 begin
1285 result := LayeredBitmap.ComputeFlatImage(AFromLayer,AToLayer,ASeparateXorMask);
1286 end;
1287
ComputeFlatImagenull1288 function TImageState.ComputeFlatImage(ARect: TRect; AFromLayer,
1289 AToLayer: integer; ASeparateXorMask: boolean): TBGRABitmap;
1290 begin
1291 result := LayeredBitmap.ComputeFlatImage(ARect,AFromLayer,AToLayer,ASeparateXorMask);
1292 end;
1293
1294 procedure TImageState.DrawLayers(ADest: TBGRABitmap; X, Y: Integer; AIconCursor: boolean; ADestinationEmpty: boolean);
1295 begin
1296 if LayeredBitmap <> nil then
1297 LayeredBitmap.Draw(ADest,X,Y, AIconCursor, ADestinationEmpty);
1298 end;
1299
1300 constructor TImageState.Create;
1301 begin
1302 FLayeredBitmap := nil;
1303 SelectionMask := nil;
1304 SelectionLayer := nil;
1305 selectedLayerId := -1;
1306 FLastSelectionMaskBoundsIsDefined := bsUndefined;
1307 FLastSelectionLayerBoundsIsDefined := bsUndefined;
1308 FSelectionTransform := AffineMatrixIdentity;
1309 DiscardOriginalDiff := true;
1310 end;
1311
1312 destructor TImageState.Destroy;
1313 begin
1314 LayeredBitmap.Free;
1315 SelectionMask.free;
1316 SelectionLayer.Free;
1317 inherited Destroy;
1318 end;
1319
Equalsnull1320 function TImageState.Equals(Obj: TObject): boolean;
1321 var other: TImageState;
1322 selectedLayerIndex, otherSelectedLayerIndex: integer;
1323 begin
1324 if obj is TImageState then
1325 begin
1326 other := obj as TImageState;
1327 result := false;
1328 if selectedLayerId <> -1 then //compare active layer (where modifications are expected to be)
1329 begin
1330 selectedLayerIndex := LayeredBitmap.GetLayerIndexFromId(selectedLayerId);
1331 otherSelectedLayerIndex := other.LayeredBitmap.GetLayerIndexFromId(selectedLayerId);
1332 if (selectedLayerIndex <> -1) and (otherSelectedLayerIndex <> -1) then
1333 if not other.LayeredBitmap.LayerBitmap[otherSelectedLayerIndex].Equals(LayeredBitmap.LayerBitmap[selectedLayerIndex]) then exit;
1334 end;
1335 if (other.SelectionMask = nil) and (SelectionMask <> nil) and not SelectionMask.Equals(BGRABlack) then exit;
1336 if (other.SelectionMask <> nil) and (SelectionMask = nil) and not other.SelectionMask.Equals(BGRABlack) then exit;
1337 if (other.SelectionMask <> nil) and (SelectionMask <> nil) and not other.SelectionMask.Equals(SelectionMask) then exit;
1338 if (other.SelectionLayer = nil) and (SelectionLayer <> nil) and not SelectionLayer.Empty then exit;
1339 if (other.SelectionLayer <> nil) and (SelectionLayer = nil) and not other.SelectionLayer.Empty then exit;
1340 if (other.SelectionLayer <> nil) and (SelectionLayer <> nil) and not other.SelectionLayer.Equals(SelectionLayer) then exit;
1341 if (other.filenameUTF8 <> filenameUTF8) then exit;
1342 result := true;
1343 end
1344 else
1345 Result:=inherited Equals(Obj);
1346 end;
1347
1348 procedure TImageState.ApplyDifference(ADifference: TStateDifference);
1349 begin
1350 ADifference.ApplyTo(self);
1351 end;
1352
1353 procedure TImageState.ReverseDifference(ADifference: TStateDifference);
1354 begin
1355 ADifference.UnapplyTo(self);
1356 end;
1357
TImageState.Duplicatenull1358 function TImageState.Duplicate: TState;
1359 var copy: TImageState;
1360 begin
1361 copy := TImageState.Create;
1362 copy.SetLayeredBitmap(DuplicateLayeredBitmap(LayeredBitmap));
1363 copy.SelectionMask := DuplicateBitmap(SelectionMask);
1364 copy.SelectionLayer := DuplicateBitmap(SelectionLayer);
1365 copy.selectedLayerId := selectedLayerId;
1366 result := copy;
1367 end;
1368
1369 procedure TImageState.Resample(AWidth, AHeight: integer;
1370 AQuality: TResampleMode; AFilter: TResampleFilter);
1371 begin
1372 LayeredBitmap.Resample(AWidth,AHeight,AQuality,AFilter);
1373 if SelectionMask <> nil then
1374 begin
1375 SelectionMask.ResampleFilter := AFilter;
1376 BGRAReplace(FSelectionMask, FSelectionMask.Resample(AWidth, AHeight,AQuality));
1377 end;
1378 if SelectionLayer <> nil then
1379 begin
1380 SelectionLayer.ResampleFilter := AFilter;
1381 BGRAReplace(SelectionLayer, SelectionLayer.Resample(AWidth, AHeight,AQuality));
1382 end;
1383 end;
1384
1385 end.
1386
1387