Changeset 521 for GraphicTest/Packages/bgrabitmap/bgrastreamlayers.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/bgrastreamlayers.pas
r494 r521 2 2 3 3 {$mode objfpc}{$H+} 4 {$MODESWITCH ADVANCEDRECORDS} 4 5 5 6 interface … … 9 10 10 11 function CheckStreamForLayers(AStream: TStream): boolean; 11 function LoadLayersFromStream(AStream: TStream; out ASelectedLayerIndex: integer; ALoadLayerUniqueIds: boolean = false) : TBGRALayeredBitmap; 12 function LoadLayersFromStream(AStream: TStream; out ASelectedLayerIndex: integer; ALoadLayerUniqueIds: boolean = false; 13 ADestination: TBGRALayeredBitmap = nil): TBGRALayeredBitmap; 12 14 procedure SaveLayersToStream(AStream: TStream; ALayers: TBGRACustomLayeredBitmap; ASelectedLayerIndex: integer; ACompression: TLzpCompression = lzpZStream); 13 15 procedure SaveLayerBitmapToStream(AStream: TStream; ABitmap: TBGRABitmap; ACaption: string; ACompression: TLzpCompression = lzpZStream); … … 18 20 19 21 uses BGRABitmapTypes, BGRACompressableBitmap, zstream, BGRAReadLzp, BGRAWriteLzp, 20 BGRAUTF8; 22 BGRAUTF8, Math; 23 24 type 25 PLayerHeader = ^TLayerHeader; 26 27 { TLayerHeader } 28 29 TLayerHeader = packed record 30 LayerOption, BlendOp, 31 LayerOfsX, LayerOfsY, 32 LayerUniqueId, LayerOpacity: Longint; 33 LayerBitmapSize: int64; 34 OriginalGuid: TGuid; 35 OriginalMatrix: TAffineMatrix; 36 procedure FixEndian; 37 end; 38 39 { TLayerHeader } 40 41 procedure TLayerHeader.FixEndian; 42 begin 43 LayerOption := NtoLE(LayerOption); 44 BlendOp := NtoLE(BlendOp); 45 LayerOfsX := NtoLE(LayerOfsX); 46 LayerOfsY := NtoLE(LayerOfsY); 47 LayerUniqueId := NtoLE(LayerUniqueId); 48 LayerOpacity := NtoLE(LayerOpacity); 49 LayerBitmapSize := NtoLE(LayerBitmapSize); 50 OriginalGuid.D1 := NtoBE(OriginalGuid.D1); 51 OriginalGuid.D2 := NtoBE(OriginalGuid.D2); 52 OriginalGuid.D3 := NtoBE(OriginalGuid.D3); 53 DWord(OriginalMatrix[1,1]) := NtoLE(DWord(OriginalMatrix[1,1])); 54 DWord(OriginalMatrix[2,1]) := NtoLE(DWord(OriginalMatrix[2,1])); 55 DWord(OriginalMatrix[1,2]) := NtoLE(DWord(OriginalMatrix[1,2])); 56 DWord(OriginalMatrix[2,2]) := NtoLE(DWord(OriginalMatrix[2,2])); 57 DWord(OriginalMatrix[1,3]) := NtoLE(DWord(OriginalMatrix[1,3])); 58 DWord(OriginalMatrix[2,3]) := NtoLE(DWord(OriginalMatrix[2,3])); 59 end; 21 60 22 61 procedure SaveLayeredBitmapToStream(AStream: TStream; ALayers: TBGRACustomLayeredBitmap); … … 25 64 end; 26 65 27 function LoadLayeredBitmapFromStream(AStream: TStream) : TBGRALayeredBitmap;66 procedure LoadLayeredBitmapFromStream(AStream: TStream; ALayers: TBGRACustomLayeredBitmap); 28 67 var selectedIndex: integer; 29 68 begin 30 69 if not CheckStreamForLayers(AStream) then 31 result := nil 70 begin 71 if Assigned(ALayers) then ALayers.Clear; 72 end 32 73 else 33 result := LoadLayersFromStream(AStream,selectedIndex);74 LoadLayersFromStream(AStream,selectedIndex,false,ALayers as TBGRALayeredBitmap); 34 75 end; 35 76 … … 60 101 end; 61 102 62 function LoadLayersFromStream(AStream: TStream; out ASelectedLayerIndex: integer; ALoadLayerUniqueIds: boolean = false): TBGRALayeredBitmap; 103 function LoadLayersFromStream(AStream: TStream; out ASelectedLayerIndex: integer; ALoadLayerUniqueIds: boolean = false; 104 ADestination: TBGRALayeredBitmap = nil): TBGRALayeredBitmap; 63 105 var 64 106 OldPosition: Int64; 65 107 HeaderFound: string; 66 NbLayers : LongInt;108 NbLayers, canvasWidth, canvasHeight: LongInt; 67 109 HeaderSize, LayerHeaderSize: LongInt; 68 LayerStackStartPosition, LayerHeaderPosition, LayerBitmapPosition, LayerEndPosition: Int64; 69 LayerOption,StackOption: LongInt; 110 LayerStackStartPosition, LayerHeaderPosition, 111 LayerBitmapPosition, LayerEndPosition, MemDirPos: Int64; 112 StackOption: LongInt; 70 113 Layer: TBGRABitmap; 71 114 i,LayerIndex: integer; 72 115 LayerName: string; 73 LayerId: LongInt;74 116 Compression: TLzpCompression; 75 LayerVisible: boolean;76 117 LayerBlendOp: TBlendOperation; 77 LayerOffset: TPoint;78 LayerOpacity: integer;79 118 LayerIdFound: boolean; 80 LayerBitmapSize: integer; 81 begin 82 result := TBGRALayeredBitmap.Create; 119 h: TLayerHeader; 120 begin 121 if Assigned(ADestination) then 122 begin 123 result := ADestination; 124 result.Clear; 125 end else 126 result := TBGRALayeredBitmap.Create; 83 127 OldPosition:= AStream.Position; 84 128 SetLength(HeaderFound, length(StreamHeader)); … … 106 150 result.LinearBlend := (StackOption and 1) = 1; 107 151 if (StackOption and 2) = 2 then Compression := lzpRLE else Compression:= lzpZStream; 152 153 if headerSize >= 20 then 154 begin 155 canvasWidth := LEReadLongint(AStream); 156 canvasHeight := LEReadLongint(AStream); 157 result.SetSize(canvasWidth,canvasHeight); 158 end; 159 160 if headerSize >= 28 then 161 begin 162 MemDirPos := LEReadInt64(AStream); 163 end else MemDirPos := 0; 108 164 //end of header 165 166 if MemDirPos <> 0 then 167 begin 168 AStream.Position:= MemDirPos+OldPosition; 169 result.MemDirectory.LoadFromStream(AStream); 170 end else 171 result.MemDirectory.Clear; 109 172 110 173 AStream.Position:= LayerStackStartPosition; … … 112 175 begin 113 176 LayerHeaderSize:= LEReadLongint(AStream); 177 114 178 LayerHeaderPosition := AStream.Position; 115 179 LayerBitmapPosition := LayerHeaderPosition + LayerHeaderSize; 116 180 LayerEndPosition := -1; 117 181 118 LayerVisible := true; 119 LayerBlendOp := result.DefaultBlendingOperation; 120 LayerOffset := Point(0,0); 121 LayerId := 0; 122 LayerIdFound := false; 123 LayerOpacity := 255; 124 125 if AStream.Position <= LayerBitmapPosition-4 then 126 begin 127 LayerOption := LEReadLongint(AStream); 128 LayerVisible := (LayerOption and 1) = 1; 129 end; 130 if AStream.Position <= LayerBitmapPosition-4 then 131 LayerBlendOp := TBlendOperation(LEReadLongint(AStream)); 132 133 if AStream.Position <= LayerBitmapPosition-8 then 134 begin 135 LayerOffset := Point(LEReadLongint(AStream),LEReadLongint(AStream)); 136 if AStream.Position <= LayerBitmapPosition-4 then 137 begin 138 LayerId := LEReadLongint(AStream); 139 LayerIdFound := true; 140 end; 141 if AStream.Position <= LayerBitmapPosition-4 then 142 LayerOpacity := LEReadLongint(AStream) shr 8; 143 end; 144 if AStream.Position <= LayerBitmapPosition-4 then 145 begin 146 LayerBitmapSize := LEReadLongint(AStream); 147 LayerEndPosition:= LayerBitmapPosition+LayerBitmapSize; 148 end; 182 fillchar({%H-}h, sizeof(h), 0); 183 h.LayerOption := 1; //visible 184 h.BlendOp:= integer(result.DefaultBlendingOperation); 185 h.LayerOpacity := 65535; //opaque 186 h.LayerUniqueId:= maxLongint; 187 h.FixEndian; 188 189 AStream.ReadBuffer(h, min(LayerHeaderSize, sizeof(h))); 190 h.FixEndian; 191 192 if h.BlendOp > ord(high(TBlendOperation)) then 193 LayerBlendOp := result.DefaultBlendingOperation 194 else 195 LayerBlendOp:= TBlendOperation(h.BlendOp); 196 197 LayerIdFound := h.LayerUniqueId <> maxLongint; 198 199 if h.LayerBitmapSize > 0 then 200 LayerEndPosition:= LayerBitmapPosition+h.LayerBitmapSize; 149 201 150 202 AStream.Position:= LayerBitmapPosition; … … 155 207 156 208 result.LayerName[LayerIndex] := LayerName; 157 result.LayerVisible[LayerIndex] := LayerVisible;209 result.LayerVisible[LayerIndex] := (h.LayerOption and 1) = 1; 158 210 result.BlendOperation[LayerIndex]:= LayerBlendOp; 159 result.LayerOffset[LayerIndex] := LayerOffset;211 result.LayerOffset[LayerIndex] := Point(h.LayerOfsX,h.LayerOfsY); 160 212 if ALoadLayerUniqueIds and LayerIdFound then 161 result.LayerUniqueId[LayerIndex] := LayerId; 162 result.LayerOpacity[LayerIndex] := LayerOpacity; 213 result.LayerUniqueId[LayerIndex] := h.LayerUniqueId; 214 result.LayerOpacity[LayerIndex] := h.LayerOpacity shr 8; 215 result.LayerOriginalGuid[LayerIndex] := h.OriginalGuid; 216 result.LayerOriginalMatrix[LayerIndex] := h.OriginalMatrix; 217 result.LayerOriginalRenderStatus[layerIndex] := orsProof; 163 218 164 219 if LayerEndPosition <> -1 then AStream.Position := LayerEndPosition; 165 220 end; 221 result.NotifyLoaded; 166 222 except 167 223 on ex: Exception do 168 224 begin 169 225 AStream.Position := OldPosition; 226 if not Assigned(ADestination) then result.Free; 170 227 raise ex; 171 228 end; … … 175 232 procedure SaveLayersToStream(AStream: TStream; ALayers: TBGRACustomLayeredBitmap; ASelectedLayerIndex: integer; ACompression: TLzpCompression); 176 233 var 177 LayerOption,StackOption: longint;234 StackOption: longint; 178 235 i: integer; 179 LayerHeaderSizePosition,LayerHeaderPosition: int64;180 Layer BitmapPosition,LayerBitmapSizePosition,BitmapSize: int64;181 Layer HeaderSize: integer;236 DirectoryOffsetPos, EndPos: int64; 237 LayerHeaderPosition: int64; 238 LayerBitmapPosition,BitmapSize, startPos: int64; 182 239 bitmap: TBGRABitmap; 240 h: TLayerHeader; 183 241 begin 184 242 if (ASelectedLayerIndex < -1) or (ASelectedLayerIndex >= ALayers.NbLayers) then 185 243 raise exception.Create('Selected layer out of bounds'); 244 245 ALayers.NotifySaving; 246 247 startPos := AStream.Position; 186 248 AStream.Write(StreamHeader[1], length(StreamHeader)); 187 LEWriteLongint(AStream, 12); //header size249 LEWriteLongint(AStream, 28); //header size 188 250 LEWriteLongint(AStream, ALayers.NbLayers); 189 251 LEWriteLongint(AStream, ASelectedLayerIndex); … … 192 254 if ACompression = lzpRLE then StackOption:= StackOption or 2; 193 255 LEWriteLongint(AStream, StackOption); 256 LEWriteLongint(AStream, ALayers.Width); 257 LEWriteLongint(AStream, ALayers.Height); 258 DirectoryOffsetPos := AStream.Position; 259 LEWriteInt64(AStream, 0); 194 260 //end of header 195 261 196 262 for i := 0 to ALayers.NbLayers-1 do 197 263 begin 198 LayerHeaderSizePosition:= AStream.Position; 199 LEWriteLongint(AStream, 0); //header size not computed yet 264 LEWriteLongint(AStream, sizeof(h)); 200 265 LayerHeaderPosition := AStream.Position; 201 266 202 LayerOption := 0; 203 if ALayers.LayerVisible[i] then LayerOption:= LayerOption or 1; 204 LEWriteLongint(AStream, LayerOption); 205 LEWriteLongint(AStream, Longint(ALayers.BlendOperation[i])); 206 LEWriteLongint(AStream, ALayers.LayerOffset[i].x); 207 LEWriteLongint(AStream, ALayers.LayerOffset[i].y); 208 LEWriteLongint(AStream, ALayers.LayerUniqueId[i]); 209 LEWriteLongint(AStream, integer(ALayers.LayerOpacity[i])*$101); 210 LayerBitmapSizePosition:=AStream.Position; 211 LEWriteLongint(AStream, 0); 267 bitmap := ALayers.GetLayerBitmapDirectly(i); //do it before to ensure update from original 268 269 h.LayerOption:= 0; 270 if ALayers.LayerVisible[i] then h.LayerOption:= h.LayerOption or 1; 271 h.BlendOp:= Longint(ALayers.BlendOperation[i]); 272 h.LayerOfsX:= ALayers.LayerOffset[i].x; 273 h.LayerOfsY:= ALayers.LayerOffset[i].y; 274 h.LayerUniqueId:= ALayers.LayerUniqueId[i]; 275 h.LayerOpacity:= integer(ALayers.LayerOpacity[i])*$101; 276 h.LayerBitmapSize := 0; 277 h.OriginalGuid := ALayers.LayerOriginalGuid[i]; 278 h.OriginalMatrix := ALayers.LayerOriginalMatrix[i]; 279 h.FixEndian; 280 AStream.WriteBuffer(h, sizeof(h)); 281 //end of layer header 282 212 283 LayerBitmapPosition:=AStream.Position; 213 LayerHeaderSize := LayerBitmapPosition - LayerHeaderPosition;214 AStream.Position:= LayerHeaderSizePosition;215 LEWriteLongint(AStream, LayerHeaderSize);216 //end of layer header217 218 AStream.Position:= LayerBitmapPosition;219 bitmap := ALayers.GetLayerBitmapDirectly(i);220 284 if bitmap <> nil then 221 285 SaveLayerBitmapToStream(AStream, bitmap, ALayers.LayerName[i], ACompression) … … 226 290 bitmap.free; 227 291 end; 292 228 293 BitmapSize := AStream.Position - LayerBitmapPosition; 229 if BitmapSize > maxLongint then 230 raise exception.Create('Image too big'); 231 AStream.Position:= LayerBitmapSizePosition; 232 LEWriteLongint(AStream, BitmapSize); 294 295 //store back the bitmap size 296 AStream.Position:= LayerHeaderPosition + (PByte(@PLayerHeader(nil)^.LayerBitmapSize)-PByte(nil)); 297 LEWriteInt64(AStream, BitmapSize); 298 233 299 AStream.Position:= LayerBitmapPosition+BitmapSize; 300 end; 301 302 EndPos:= AStream.Position; 303 if ALayers.HasMemFiles then 304 begin 305 AStream.Position := DirectoryOffsetPos; 306 LEWriteInt64(AStream,EndPos-startPos); 307 AStream.Position:= EndPos; 308 ALayers.MemDirectory.SaveToStream(AStream); 234 309 end; 235 310 end; … … 271 346 LayeredBitmapSaveToStreamProc := @SaveLayeredBitmapToStream; 272 347 LayeredBitmapLoadFromStreamProc := @LoadLayeredBitmapFromStream; 273 end; 348 LayeredBitmapCheckStreamProc := @CheckStreamForLayers; 349 end; 350 351 initialization 352 353 RegisterStreamLayers; 274 354 275 355 end.
Note:
See TracChangeset
for help on using the changeset viewer.