Changeset 521 for GraphicTest/Packages/bgrabitmap/bgraanimatedgif.pas
- Timestamp:
- Apr 17, 2019, 12:58:41 AM (5 years ago)
- Location:
- GraphicTest
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest
- Property svn:ignore
-
old new 8 8 GraphicTest.lps 9 9 GraphicTest.dbg 10 heaptrclog.trc
-
- Property svn:ignore
-
GraphicTest/Packages/bgrabitmap/bgraanimatedgif.pas
r494 r521 39 39 40 40 procedure CheckFrameIndex(AIndex: integer); 41 function GetAverageDelayMs: integer; 41 42 function GetCount: integer; 42 43 function GetFrameDelayMs(AIndex: integer): integer; … … 81 82 EraseColor: TColor; 82 83 BackgroundMode: TGifBackgroundMode; 83 84 constructor Create(filenameUTF8: string); 85 constructor Create(stream: TStream); 86 constructor Create; override; 84 LoopCount: Word; 85 LoopDone: Integer; 86 87 constructor Create(filenameUTF8: string); overload; 88 constructor Create(stream: TStream); overload; 89 constructor Create(stream: TStream; AMaxImageCount: integer); overload; 90 constructor Create; overload; override; 87 91 function Duplicate: TBGRAAnimatedGif; 88 92 function AddFrame(AImage: TFPCustomImage; X,Y: integer; ADelayMs: integer; 89 93 ADisposeMode: TDisposeMode = dmErase; AHasLocalPalette: boolean = false) : integer; 90 procedure InsertFrame(AIndex: integer; AImage: T BGRABitmap; X,Y: integer; ADelayMs: integer;94 procedure InsertFrame(AIndex: integer; AImage: TFPCustomImage; X,Y: integer; ADelayMs: integer; 91 95 ADisposeMode: TDisposeMode = dmErase; AHasLocalPalette: boolean = false); 96 procedure DeleteFrame(AIndex: integer; AEnsureNextFrameDoesNotChange: boolean); 97 98 //add a frame that replaces completely the previous one 99 function AddFullFrame(AImage: TFPCustomImage; ADelayMs: integer; 100 AHasLocalPalette: boolean = true): integer; 101 procedure InsertFullFrame(AIndex: integer; 102 AImage: TFPCustomImage; ADelayMs: integer; 103 AHasLocalPalette: boolean = true); 104 procedure ReplaceFullFrame(AIndex: integer; 105 AImage: TFPCustomImage; ADelayMs: integer; 106 AHasLocalPalette: boolean = true); 92 107 93 108 {TGraphic} 94 procedure LoadFromStream(Stream: TStream); override; 95 procedure SaveToStream(Stream: TStream); override; 109 procedure LoadFromStream(Stream: TStream); overload; override; 110 procedure LoadFromStream(Stream: TStream; AMaxImageCount: integer); overload; 111 procedure LoadFromResource(AFilename: string); 112 procedure SaveToStream(Stream: TStream); overload; override; 96 113 procedure LoadFromFile(const AFilenameUTF8: string); override; 97 114 procedure SaveToFile(const AFilenameUTF8: string); override; … … 100 117 procedure SetSize(AWidth,AHeight: integer); virtual; 101 118 procedure SaveToStream(Stream: TStream; AQuantizer: TBGRAColorQuantizerAny; 102 ADitheringAlgorithm: TDitheringAlgorithm); virtual; overload;119 ADitheringAlgorithm: TDitheringAlgorithm); overload; virtual; 103 120 procedure Clear; override; 104 121 destructor Destroy; override; … … 126 143 property AspectRatio: single read FAspectRatio write SetAspectRatio; 127 144 property TotalAnimationTimeMs: Int64 read FTotalAnimationTime; 145 property AverageDelayMs: integer read GetAverageDelayMs; 128 146 end; 129 147 … … 184 202 data.BackgroundColor := BackgroundColor; 185 203 data.Images := FImages; 204 data.LoopCount := LoopCount; 186 205 GIFSaveToStream(data, Stream, AQuantizer, ADitheringAlgorithm); 187 206 end; … … 233 252 Inc(nextImage); 234 253 if nextImage >= Count then 235 nextImage := 0; 254 begin 255 if (LoopCount > 0) and (LoopDone >= LoopCount-1) then 256 begin 257 LoopDone := LoopCount; 258 dec(nextImage); 259 break; 260 end else 261 begin 262 nextImage := 0; 263 inc(LoopDone); 264 end; 265 end; 236 266 237 267 if nextImage = previousImage then 238 268 begin 239 Inc(nextImage); 240 if nextImage >= Count then 241 nextImage := 0; 269 if not ((LoopCount > 0) and (LoopDone >= LoopCount-1)) then 270 begin 271 Inc(nextImage); 272 if nextImage >= Count then 273 nextImage := 0; 274 end; 242 275 break; 243 276 end; … … 370 403 end; 371 404 405 function TBGRAAnimatedGif.GetAverageDelayMs: integer; 406 var sum: int64; 407 i: Integer; 408 begin 409 if Count > 0 then 410 begin 411 sum := 0; 412 for i := 0 to Count-1 do 413 inc(sum, FrameDelayMs[i]); 414 result := sum div Count; 415 end else 416 result := 100; //default 417 end; 418 372 419 function TBGRAAnimatedGif.GetCount: integer; 373 420 begin … … 437 484 end; 438 485 486 constructor TBGRAAnimatedGif.Create(stream: TStream; AMaxImageCount: integer); 487 begin 488 inherited Create; 489 Init; 490 LoadFromStream(stream, AMaxImageCount); 491 end; 492 439 493 constructor TBGRAAnimatedGif.Create; 440 494 begin … … 478 532 end; 479 533 480 procedure TBGRAAnimatedGif.InsertFrame(AIndex: integer; AImage: T BGRABitmap; X,534 procedure TBGRAAnimatedGif.InsertFrame(AIndex: integer; AImage: TFPCustomImage; X, 481 535 Y: integer; ADelayMs: integer; ADisposeMode: TDisposeMode; 482 536 AHasLocalPalette: boolean); … … 491 545 with FImages[AIndex] do 492 546 begin 493 Image := AImage.Duplicate as TBGRABitmap;547 Image := TBGRABitmap.Create(AImage); 494 548 Position := Point(x,y); 495 549 DelayMs := ADelayMs; … … 500 554 end; 501 555 556 function TBGRAAnimatedGif.AddFullFrame(AImage: TFPCustomImage; 557 ADelayMs: integer; AHasLocalPalette: boolean): integer; 558 begin 559 if (AImage.Width <> Width) or (AImage.Height <> Height) then 560 raise exception.Create('Size mismatch'); 561 if Count > 0 then 562 FrameDisposeMode[Count-1] := dmErase; 563 result := AddFrame(AImage, 0,0, ADelayMs, dmErase, AHasLocalPalette); 564 end; 565 566 procedure TBGRAAnimatedGif.InsertFullFrame(AIndex: integer; 567 AImage: TFPCustomImage; ADelayMs: integer; AHasLocalPalette: boolean); 568 var nextImage: TBGRABitmap; 569 begin 570 if (AIndex < 0) or (AIndex > Count) then 571 raise ERangeError.Create('Index out of bounds'); 572 573 if AIndex = Count then 574 AddFullFrame(AImage, ADelayMs, AHasLocalPalette) 575 else 576 begin 577 //if previous image did not clear up, ensure that 578 //next image will stay the same 579 if (AIndex > 0) and (FrameDisposeMode[AIndex-1] <> dmErase) then 580 begin 581 CurrentImage := AIndex; 582 nextImage := MemBitmap.Duplicate as TBGRABitmap; 583 FrameImagePos[AIndex] := Point(0,0); 584 FrameImage[AIndex] := nextImage; 585 FrameHasLocalPalette[AIndex] := true; 586 FreeAndNil(nextImage); 587 588 FrameDisposeMode[AIndex-1] := dmErase; 589 end; 590 591 InsertFrame(AIndex, AImage, 0,0, ADelayMs, dmErase, AHasLocalPalette); 592 end; 593 end; 594 595 procedure TBGRAAnimatedGif.ReplaceFullFrame(AIndex: integer; 596 AImage: TFPCustomImage; ADelayMs: integer; AHasLocalPalette: boolean); 597 begin 598 DeleteFrame(AIndex, True); 599 if AIndex > 0 then FrameDisposeMode[AIndex-1] := dmErase; 600 InsertFrame(AIndex, AImage, 0,0, ADelayMs, dmErase, AHasLocalPalette); 601 end; 602 603 procedure TBGRAAnimatedGif.DeleteFrame(AIndex: integer; 604 AEnsureNextFrameDoesNotChange: boolean); 605 var 606 nextImage: TBGRABitmap; 607 i: Integer; 608 begin 609 CheckFrameIndex(AIndex); 610 611 //if this frame did not clear up, ensure that 612 //next image will stay the same 613 if AEnsureNextFrameDoesNotChange and 614 ((AIndex < Count-1) and (FrameDisposeMode[AIndex] <> dmErase)) then 615 begin 616 CurrentImage := AIndex+1; 617 nextImage := MemBitmap.Duplicate as TBGRABitmap; 618 FrameImagePos[AIndex+1] := Point(0,0); 619 FrameImage[AIndex+1] := nextImage; 620 FrameHasLocalPalette[AIndex+1] := true; 621 FreeAndNil(nextImage); 622 end; 623 624 dec(FTotalAnimationTime, FImages[AIndex].DelayMs); 625 626 FImages[AIndex].Image.FreeReference; 627 for i := AIndex to Count-2 do 628 FImages[i] := FImages[i+1]; 629 SetLength(FImages, Count-1); 630 631 if (CurrentImage >= Count) then 632 CurrentImage := 0; 633 end; 634 502 635 procedure TBGRAAnimatedGif.LoadFromStream(Stream: TStream); 636 begin 637 LoadFromStream(Stream, maxLongint); 638 end; 639 640 procedure TBGRAAnimatedGif.LoadFromStream(Stream: TStream; 641 AMaxImageCount: integer); 503 642 var data: TGIFData; 504 643 i: integer; 505 644 begin 506 data := GIFLoadFromStream(Stream );645 data := GIFLoadFromStream(Stream, AMaxImageCount); 507 646 508 647 ClearViewer; … … 512 651 FBackgroundColor := data.BackgroundColor; 513 652 FAspectRatio:= data.AspectRatio; 653 LoopDone := 0; 654 LoopCount := data.LoopCount; 514 655 515 656 SetLength(FImages, length(data.Images)); … … 519 660 FImages[i] := data.Images[i]; 520 661 FTotalAnimationTime += FImages[i].DelayMs; 662 end; 663 end; 664 665 procedure TBGRAAnimatedGif.LoadFromResource(AFilename: string); 666 var 667 stream: TStream; 668 begin 669 stream := BGRAResource.GetResourceStream(AFilename); 670 try 671 LoadFromStream(stream); 672 finally 673 stream.Free; 521 674 end; 522 675 end; … … 658 811 FImages[i].Image.FreeReference; 659 812 FImages := nil; 813 LoopDone := 0; 814 LoopCount := 0; 660 815 end; 661 816 … … 959 1114 begin 960 1115 BackgroundMode := gbmSaveBackgroundOnce; 1116 LoopCount := 0; 1117 LoopDone := 0; 961 1118 end; 962 1119 … … 981 1138 Mem: TBGRABitmap; 982 1139 begin 983 gif := TBGRAAnimatedGif.Create(Str );1140 gif := TBGRAAnimatedGif.Create(Str, 1); 984 1141 Mem := gif.MemBitmap; 985 1142 if Img is TBGRABitmap then
Note:
See TracChangeset
for help on using the changeset viewer.