Changeset 472 for GraphicTest/Packages/bgrabitmap/bgrabitmaptypes.pas
- Timestamp:
- Apr 9, 2015, 9:58:36 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
GraphicTest/Packages/bgrabitmap/bgrabitmaptypes.pas
r452 r472 36 36 PBGRAPixel = ^TBGRAPixel; 37 37 38 //pixel structure 38 Int32or64 = {$IFDEF CPU64}Int64{$ELSE}LongInt{$ENDIF}; 39 UInt32or64 = {$IFDEF CPU64}UInt64{$ELSE}LongWord{$ENDIF}; 40 41 //Each pixel is a sequence of 4 bytes containing blue, green, red and alpha channel. 39 42 TBGRAPixel = packed record 40 43 blue, green, red, alpha: byte; 41 44 end; 45 46 ArrayOfTBGRAPixel = array of TBGRAPixel; 42 47 43 48 //gamma expanded values … … 50 55 hue, saturation, lightness, alpha: word; 51 56 end; 57 TGSBAPixel = THSLAPixel; 52 58 53 59 //general purpose color variable with floating point values … … 70 76 71 77 TResampleMode = (rmSimpleStretch, //low quality resample 72 rmFineResample); //use resample filters 73 TResampleFilter = (rfLinear, //linear interpolation 78 rmFineResample); //use resample filters and pixel-centered coordinates 79 TResampleFilter = (rfBox, //equivalent of stretch with high quality 80 rfLinear, //linear interpolation 74 81 rfHalfCosine, //mix of rfLinear and rfCosine 75 82 rfCosine, //cosine-like interpolation … … 77 84 rfMitchell, //downsizing interpolation 78 85 rfSpline, //upsizing interpolation 86 rfLanczos2, //Lanczos with radius 2 87 rfLanczos3, //Lanczos with radius 3 88 rfLanczos4, //Lanczos with radius 4 79 89 rfBestQuality); //mix of rfMitchell and rfSpline 80 90 91 TDitheringAlgorithm = (daNearestNeighbor, daFloydSteinberg); 92 TAlphaChannelPaletteOption = (acIgnore, acTransparentEntry, acFullChannelInPalette); 93 94 const 95 ResampleFilterStr : array[TResampleFilter] of string = 96 ('Box','Linear','HalfCosine','Cosine','Bicubic','Mitchell','Spline', 97 'Lanczos2','Lanczos3','Lanczos4','BestQuality'); 98 99 function StrToResampleFilter(str: string): TResampleFilter; 100 101 type 102 TBGRAImageFormat = (ifUnknown, ifJpeg, ifPng, ifGif, ifBmp, ifIco, ifPcx, ifPaintDotNet, ifLazPaint, ifOpenRaster, 103 ifPsd, ifTarga, ifTiff, ifXwd, ifXPixMap, ifBmpMioMap); 104 105 var 106 DefaultBGRAImageReader: array[TBGRAImageFormat] of TFPCustomImageReaderClass; 107 DefaultBGRAImageWriter: array[TBGRAImageFormat] of TFPCustomImageWriterClass; 108 109 type 81 110 TBGRAFontQuality = (fqSystem, fqSystemClearType, fqFineAntialiasing, fqFineClearTypeRGB, fqFineClearTypeBGR); 111 // fqSystem: use system rendering. It is fast however it may be not be smoothed. 112 // fqSystemClearType: use system rendering with ClearType. This quality is of course better than fqSystem however it may not be much smoother. 113 // fqFineAntialiasing: garanties a high quality antialiasing. This is slower. 114 // fqFineClearTypeRGB: garanties a high quality antialiasing with ClearType. The order of the color in the LCD screen is supposed to be un red/green/blue order. 115 // fqFineClearTypeBGR: same as above, except the color of the LCD screen is supposed to be in blue/green/red order. 82 116 83 117 TMedianOption = (moNone, moLowSmooth, moMediumSmooth, moHighSmooth); 84 TRadialBlurType = (rbNormal, rbDisk, rbCorona, rbPrecise, rbFast); 85 TSplineStyle = (ssInside, ssInsideWithEnds, ssCrossing, ssCrossingWithEnds, ssOutside, ssRoundOutside, ssVertexToSide); 118 TRadialBlurType = (rbNormal, rbDisk, rbCorona, rbPrecise, rbFast, rbBox); 119 TSplineStyle = (ssInside, ssInsideWithEnds, ssCrossing, ssCrossingWithEnds, 120 ssOutside, ssRoundOutside, ssVertexToSide); 86 121 87 //Advanced blending modes88 //see : http://www.brighthub.com/multimedia/photography/articles/18301.aspx89 //and : http://www.pegtop.net/delphi/articles/blendmodes/122 { Advanced blending modes 123 see : http://www.brighthub.com/multimedia/photography/articles/18301.aspx 124 and : http://www.pegtop.net/delphi/articles/blendmodes/ } 90 125 TBlendOperation = (boLinearBlend, boTransparent, //blending 91 126 boLighten, boScreen, boAdditive, boLinearAdd, boColorDodge, boDivide, boNiceGlow, boSoftLight, boHardLight, //lighting … … 146 181 end; 147 182 183 TArcDef = record 184 center: TPointF; 185 radius: TPointF; 186 xAngleRadCW, startAngleRadCW, endAngleRadCW: single; //see convention in BGRAPath 187 anticlockwise: boolean 188 end; 189 PArcDef = ^TArcDef; 190 148 191 TPoint3D = record 149 192 x,y,z: single; 150 193 end; 194 195 TBGRAArrowStyle = (asNone, asNormal, asCut, asTriangle, asHollowTriangle, asFlipped, asFlippedCut, asTail, asTailRepeat); 151 196 152 197 TBGRATypeWriterAlignment = (twaTopLeft, twaTop, twaTopRight, … … 169 214 function BezierCurve(origin, control1, control2, destination: TPointF) : TCubicBezierCurve; overload; 170 215 function BezierCurve(origin, control, destination: TPointF) : TQuadraticBezierCurve; overload; 216 function BezierCurve(origin, destination: TPointF) : TQuadraticBezierCurve; overload; 217 function ArcDef(cx, cy, rx,ry, xAngleRadCW, startAngleRadCW, endAngleRadCW: single; anticlockwise: boolean) : TArcDef; 171 218 172 219 { Useful constants } … … 184 231 clBlackOpaque = TColor($010000); 185 232 233 {$DEFINE INCLUDE_COLOR_CONST} 186 234 {$i csscolorconst.inc} 187 235 … … 204 252 public 205 253 constructor Create; 206 procedure Add(Name: string; Color: TBGRAPixel);254 procedure Add(Name: string; const Color: TBGRAPixel); 207 255 procedure Finished; 208 256 function IndexOf(Name: string): integer; 257 function IndexOfColor(const AColor: TBGRAPixel; AMaxDiff: Word = 0): integer; 209 258 210 259 property ByName[Name: string]: TBGRAPixel read GetByName; … … 215 264 216 265 var 217 CSSColors: TBGRAColorList;266 VGAColors, CSSColors: TBGRAColorList; 218 267 219 268 function isEmptyPointF(pt: TPointF): boolean; … … 236 285 end; 237 286 287 { A path is the ability to define a contour with moveTo, lineTo... 288 It must not implement reference counting. } 289 IBGRAPath = interface 290 procedure closePath; 291 procedure moveTo(const pt: TPointF); 292 procedure lineTo(const pt: TPointF); 293 procedure polylineTo(const pts: array of TPointF); 294 procedure quadraticCurveTo(const cp,pt: TPointF); 295 procedure bezierCurveTo(const cp1,cp2,pt: TPointF); 296 procedure arc(const arcDef: TArcDef); 297 procedure copyTo(dest: IBGRAPath); 298 end; 299 238 300 TScanAtFunction = function (X,Y: Single): TBGRAPixel of object; 239 301 TScanAtIntegerFunction = function (X,Y: Integer): TBGRAPixel of object; 240 302 TScanNextPixelFunction = function: TBGRAPixel of object; 241 303 TBGRACustomGradient = class; 304 305 TBGRACustomFillInfo = class; 306 TBGRACustomFontRenderer = class; 242 307 243 308 { TBGRACustomBitmap } … … 249 314 protected 250 315 { accessors to properies } 316 function GetArrowEndRepeat: integer; virtual; abstract; 317 function GetArrowStartRepeat: integer; virtual; abstract; 318 procedure SetArrowEndRepeat(AValue: integer); virtual; abstract; 319 procedure SetArrowStartRepeat(AValue: integer); virtual; abstract; 320 function GetArrowEndOffset: single; virtual; abstract; 321 function GetArrowStartOffset: single; virtual; abstract; 322 procedure SetArrowEndOffset(AValue: single); virtual; abstract; 323 procedure SetArrowStartOffset(AValue: single); virtual; abstract; 324 function GetArrowEndSize: TPointF; virtual; abstract; 325 function GetArrowStartSize: TPointF; virtual; abstract; 326 procedure SetArrowEndSize(AValue: TPointF); virtual; abstract; 327 procedure SetArrowStartSize(AValue: TPointF); virtual; abstract; 328 function GetLineCap: TPenEndCap; virtual; abstract; 329 procedure SetLineCap(AValue: TPenEndCap); virtual; abstract; 330 function GetFontRenderer: TBGRACustomFontRenderer; virtual; abstract; 331 procedure SetFontRenderer(AValue: TBGRACustomFontRenderer); virtual; abstract; 251 332 function GetHeight: integer; virtual; abstract; 252 333 function GetWidth: integer; virtual; abstract; … … 280 361 procedure SetClipRect(const AValue: TRect); virtual; abstract; 281 362 function GetFontPixelMetric: TFontPixelMetric; virtual; abstract; 282 function LoadAsBmp32(Str: TStream): boolean; virtual; abstract; 363 procedure ClearTransparentPixels; virtual; abstract; 364 procedure SetArrowStart(AStyle: TBGRAArrowStyle; ATipStyle: TPenJoinStyle = pjsMiter; ARelativePenWidth: single = 1; ATriangleBackOffset: single = 0); virtual; abstract; 365 procedure SetArrowEnd(AStyle: TBGRAArrowStyle; ATipStyle: TPenJoinStyle = pjsMiter; ARelativePenWidth: single = 1; ATriangleBackOffset: single = 0); virtual; abstract; 283 366 284 367 public 285 368 Caption: string; //user defined caption 286 369 287 //font style 288 FontName: string; 289 FontStyle: TFontStyles; 290 FontQuality : TBGRAFontQuality; 291 FontOrientation: integer; 370 {-------------------font style------------------------} 371 FontName: string; //Specifies the font to use. Unless the font renderer accept otherwise, 372 //the name is in human readable form, like 'Arial', 'Times New Roman', ... 373 374 FontStyle: TFontStyles; //Specifies the set of styles to be applied to the font. 375 //These can be fsBold, fsItalic, fsStrikeOut, fsUnderline. 376 //So the value [fsBold,fsItalic] means that the font must be bold and italic. 377 378 FontQuality : TBGRAFontQuality;//Specifies the quality of rendering. Default value is fqSystem. 379 380 FontOrientation: integer; //Specifies the rotation of the text, for functions that support text rotation. 381 //It is expressed in tenth of degrees, positive values going counter-clockwise. 292 382 293 383 //line style 294 LineCap: TPenEndCap;295 384 JoinStyle: TPenJoinStyle; 296 385 JoinMiterLimit: single; 297 386 298 387 FillMode: TFillMode; //winding or alternate 388 LinearAntialiasing: boolean; 299 389 300 390 { The resample filter is used when resizing the bitmap, and … … 310 400 constructor Create(AWidth, AHeight: integer; Color: TBGRAPixel); virtual; abstract; overload; 311 401 constructor Create(AFilename: string); virtual; abstract; overload; 402 constructor Create(AFilename: string; AIsUtf8Filename: boolean); virtual; abstract; overload; 312 403 constructor Create(AStream: TStream); virtual; abstract; overload; 313 404 … … 315 406 function NewBitmap(AWidth, AHeight: integer; Color: TBGRAPixel): TBGRACustomBitmap; virtual; abstract; overload; 316 407 function NewBitmap(Filename: string): TBGRACustomBitmap; virtual; abstract; overload; 317 408 function NewBitmap(Filename: string; AIsUtf8: boolean): TBGRACustomBitmap; virtual; abstract; overload; 409 410 //there are UTF8 functions that are different from standard function as those 411 //depend on TFPCustomImage that does not clearly handle UTF8 318 412 procedure LoadFromFile(const filename: string); virtual; 319 procedure LoadFromStream(Str: TStream); virtual; 320 procedure LoadFromStream(Str: TStream; Handler: TFPCustomImageReader); virtual; 321 procedure SaveToFile(const filename: string); virtual; 322 procedure SaveToFile(const filename: string; Handler:TFPCustomImageWriter); virtual; 413 procedure LoadFromFileUTF8(const filenameUTF8: string); virtual; 414 procedure LoadFromFileUTF8(const filenameUTF8: string; AHandler: TFPCustomImageReader); virtual; 415 procedure LoadFromStream(Str: TStream); virtual; overload; 416 procedure LoadFromStream(Str: TStream; Handler: TFPCustomImageReader); virtual; overload; 417 procedure SaveToFile(const filename: string); virtual; overload; 418 procedure SaveToFile(const filename: string; Handler:TFPCustomImageWriter); virtual; overload; 419 procedure SaveToFileUTF8(const filenameUTF8: string); virtual; overload; 420 procedure SaveToFileUTF8(const filenameUTF8: string; Handler:TFPCustomImageWriter); virtual; overload; 323 421 procedure SaveToStreamAsPng(Str: TStream); virtual; abstract; 324 procedure Assign(ABitmap: TBitmap); virtual; abstract; overload; 422 procedure SaveToStreamAs(Str: TStream; AFormat: TBGRAImageFormat); virtual; 423 procedure Assign(ARaster: TRasterImage); virtual; abstract; overload; 325 424 procedure Assign(MemBitmap: TBGRACustomBitmap); virtual; abstract; overload; 326 425 procedure Serialize(AStream: TStream); virtual; abstract; … … 328 427 329 428 {Pixel functions} 330 procedure SetPixel(x, y: integer; c: TColor); virtual; abstract; overload; 331 procedure XorPixel(x, y: integer; c: TBGRAPixel); virtual; abstract; overload; 332 procedure SetPixel(x, y: integer; c: TBGRAPixel); virtual; abstract; overload; 333 procedure DrawPixel(x, y: integer; c: TBGRAPixel); virtual; abstract; overload; 334 procedure DrawPixel(x, y: integer; ec: TExpandedPixel); virtual; abstract; overload; 335 procedure FastBlendPixel(x, y: integer; c: TBGRAPixel); virtual; abstract; 336 procedure ErasePixel(x, y: integer; alpha: byte); virtual; abstract; 337 procedure AlphaPixel(x, y: integer; alpha: byte); virtual; abstract; 338 function GetPixel(x, y: integer): TBGRAPixel; virtual; abstract; 339 function GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; virtual; abstract; overload; 340 function GetPixelCycle(x, y: integer): TBGRAPixel; virtual; 429 procedure SetPixel(x, y: int32or64; c: TColor); virtual; abstract; overload; 430 procedure XorPixel(x, y: int32or64; c: TBGRAPixel); virtual; abstract; overload; 431 procedure SetPixel(x, y: int32or64; c: TBGRAPixel); virtual; abstract; overload; 432 procedure DrawPixel(x, y: int32or64; c: TBGRAPixel); virtual; abstract; overload; 433 procedure DrawPixel(x, y: int32or64; c: TBGRAPixel; ADrawMode: TDrawMode); overload; 434 procedure DrawPixel(x, y: int32or64; ec: TExpandedPixel); virtual; abstract; overload; 435 procedure FastBlendPixel(x, y: int32or64; c: TBGRAPixel); virtual; abstract; 436 procedure ErasePixel(x, y: int32or64; alpha: byte); virtual; abstract; 437 procedure AlphaPixel(x, y: int32or64; alpha: byte); virtual; abstract; 438 function GetPixel(x, y: int32or64): TBGRAPixel; virtual; abstract; overload; 439 function GetPixel256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; virtual; abstract; 440 function GetPixel(x, y: single; AResampleFilter: TResampleFilter = rfLinear; smoothBorder: boolean = true): TBGRAPixel; virtual; abstract; overload; 441 function GetPixelCycle(x, y: int32or64): TBGRAPixel; virtual; overload; 341 442 function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; virtual; abstract; overload; 342 443 function GetPixelCycle(x, y: single; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; virtual; abstract; overload; 444 function GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter = rfLinear): TBGRAPixel; virtual; abstract; overload; 445 function GetPixelCycle256(x, y, fracX256,fracY256: int32or64; AResampleFilter: TResampleFilter; repeatX: boolean; repeatY: boolean): TBGRAPixel; virtual; abstract; overload; 343 446 344 447 {Line primitives} 345 procedure SetHorizLine(x, y, x2: integer; c: TBGRAPixel); virtual; abstract; 346 procedure XorHorizLine(x, y, x2: integer; c: TBGRAPixel); virtual; abstract; 347 procedure DrawHorizLine(x, y, x2: integer; c: TBGRAPixel); virtual; abstract; overload; 348 procedure DrawHorizLine(x, y, x2: integer; ec: TExpandedPixel); virtual; abstract; overload; 349 procedure DrawHorizLine(x, y, x2: integer; texture: IBGRAScanner); virtual; abstract; overload; 350 procedure FastBlendHorizLine(x, y, x2: integer; c: TBGRAPixel); virtual; abstract; 351 procedure AlphaHorizLine(x, y, x2: integer; alpha: byte); virtual; abstract; 352 procedure SetVertLine(x, y, y2: integer; c: TBGRAPixel); virtual; abstract; 353 procedure XorVertLine(x, y, y2: integer; c: TBGRAPixel); virtual; abstract; 354 procedure DrawVertLine(x, y, y2: integer; c: TBGRAPixel); virtual; abstract; 355 procedure AlphaVertLine(x, y, y2: integer; alpha: byte); virtual; abstract; 356 procedure FastBlendVertLine(x, y, y2: integer; c: TBGRAPixel); virtual; abstract; 357 procedure DrawHorizLineDiff(x, y, x2: integer; c, compare: TBGRAPixel; 358 maxDiff: byte); virtual; abstract; 448 procedure SetHorizLine(x, y, x2: int32or64; c: TBGRAPixel); virtual; abstract; 449 procedure XorHorizLine(x, y, x2: int32or64; c: TBGRAPixel); virtual; abstract; 450 procedure DrawHorizLine(x, y, x2: int32or64; c: TBGRAPixel); virtual; abstract; overload; 451 procedure DrawHorizLine(x, y, x2: int32or64; ec: TExpandedPixel); virtual; abstract; overload; 452 procedure DrawHorizLine(x, y, x2: int32or64; texture: IBGRAScanner); overload; 453 procedure FastBlendHorizLine(x, y, x2: int32or64; c: TBGRAPixel); virtual; abstract; 454 procedure AlphaHorizLine(x, y, x2: int32or64; alpha: byte); virtual; abstract; 455 procedure SetVertLine(x, y, y2: int32or64; c: TBGRAPixel); virtual; abstract; 456 procedure XorVertLine(x, y, y2: int32or64; c: TBGRAPixel); virtual; abstract; 457 procedure DrawVertLine(x, y, y2: int32or64; c: TBGRAPixel); virtual; abstract; 458 procedure AlphaVertLine(x, y, y2: int32or64; alpha: byte); virtual; abstract; 459 procedure FastBlendVertLine(x, y, y2: int32or64; c: TBGRAPixel); virtual; abstract; 460 procedure DrawHorizLineDiff(x, y, x2: int32or64; c, compare: TBGRAPixel; maxDiff: byte); virtual; abstract; 461 procedure HorizLine(x,y,x2: Int32or64; c: TBGRAPixel; ADrawMode: TDrawMode); overload; 462 procedure VertLine(x,y,y2: Int32or64; c: TBGRAPixel; ADrawMode: TDrawMode); 463 procedure HorizLine(x,y,x2: Int32or64; texture: IBGRAScanner; ADrawMode: TDrawMode); virtual; abstract; overload; 359 464 360 465 {Shapes} 361 procedure DrawLine(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean); virtual; abstract; 466 procedure DrawPath(APath: IBGRAPath; c: TBGRAPixel; w: single); virtual; abstract; 467 procedure DrawPath(APath: IBGRAPath; texture: IBGRAScanner; w: single); virtual; abstract; 468 469 procedure ArrowStartAsNone; 470 procedure ArrowStartAsClassic(AFlipped: boolean = false; ACut: boolean = false; ARelativePenWidth: single = 1); 471 procedure ArrowStartAsTriangle(ABackOffset: single = 0; ARounded: boolean = false; AHollow: boolean = false; AHollowPenWidth: single = 0.5); 472 procedure ArrowStartAsTail; 473 474 procedure ArrowEndAsNone; 475 procedure ArrowEndAsClassic(AFlipped: boolean = false; ACut: boolean = false; ARelativePenWidth: single = 1); 476 procedure ArrowEndAsTriangle(ABackOffset: single = 0; ARounded: boolean = false; AHollow: boolean = false; AHollowPenWidth: single = 0.5); 477 procedure ArrowEndAsTail; 478 479 procedure DrawLine(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean; ADrawMode: TDrawMode= dmDrawWithTransparency); virtual; abstract; 362 480 procedure DrawLineAntialias(x1, y1, x2, y2: integer; c: TBGRAPixel; DrawLastPixel: boolean); virtual; abstract; overload; 363 481 procedure DrawLineAntialias(x1, y1, x2, y2: integer; c1, c2: TBGRAPixel; dashLen: integer; DrawLastPixel: boolean); virtual; abstract; overload; … … 368 486 procedure DrawLineAntialias(x1, y1, x2, y2: single; texture: IBGRAScanner; w: single; Closed: boolean); virtual; abstract; overload; 369 487 488 procedure DrawPolyLine(const points: array of TPoint; c: TBGRAPixel; DrawLastPixel: boolean; ADrawMode: TDrawMode=dmDrawWithTransparency); 370 489 procedure DrawPolyLineAntialias(const points: array of TPoint; c: TBGRAPixel; DrawLastPixel: boolean); virtual; overload; 371 490 procedure DrawPolyLineAntialias(const points: array of TPoint; c1, c2: TBGRAPixel; dashLen: integer; DrawLastPixel: boolean); virtual; overload; … … 373 492 procedure DrawPolyLineAntialias(const points: array of TPointF; texture: IBGRAScanner; w: single); virtual; abstract; overload; 374 493 procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; Closed: boolean); virtual; abstract; overload; 494 procedure DrawPolyLineAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; fillcolor: TBGRAPixel); virtual; abstract; overload; 495 procedure DrawPolygon(const points: array of TPoint; c: TBGRAPixel; ADrawMode: TDrawMode=dmDrawWithTransparency); 496 procedure DrawPolygonAntialias(const points: array of TPoint; c: TBGRAPixel); overload; 375 497 procedure DrawPolygonAntialias(const points: array of TPointF; c: TBGRAPixel; w: single); virtual; abstract; overload; 376 498 procedure DrawPolygonAntialias(const points: array of TPointF; texture: IBGRAScanner; w: single); virtual; abstract; overload; 499 procedure DrawPolygonAntialias(const points: array of TPointF; c: TBGRAPixel; w: single; fillcolor: TBGRAPixel); virtual; abstract; overload; 377 500 378 501 procedure EraseLine(x1, y1, x2, y2: integer; alpha: byte; DrawLastPixel: boolean); virtual; abstract; … … 380 503 procedure EraseLineAntialias(x1, y1, x2, y2: single; alpha: byte; w: single); virtual; abstract; overload; 381 504 procedure EraseLineAntialias(x1, y1, x2, y2: single; alpha: byte; w: single; Closed: boolean); virtual; abstract; overload; 505 procedure ErasePolyLine(const points: array of TPoint; alpha: byte; DrawLastPixel: boolean); 506 procedure ErasePolyLineAntialias(const points: array of TPoint; alpha: byte; DrawLastPixel: boolean); overload; 382 507 procedure ErasePolyLineAntialias(const points: array of TPointF; alpha: byte; w: single); virtual; abstract; overload; 508 procedure ErasePolygonOutline(const points: array of TPoint; alpha: byte); 509 procedure ErasePolygonOutlineAntialias(const points: array of TPoint; alpha: byte); 510 511 procedure FillPath(APath: IBGRAPath; c: TBGRAPixel); virtual; abstract; 512 procedure FillPath(APath: IBGRAPath; texture: IBGRAScanner); virtual; abstract; 383 513 384 514 procedure FillTriangleLinearColor(pt1,pt2,pt3: TPointF; c1,c2,c3: TBGRAPixel); virtual; abstract; overload; … … 394 524 procedure FillQuadLinearMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); virtual; abstract; overload; 395 525 procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); virtual; abstract; overload; 526 procedure FillQuadPerspectiveMapping(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect); virtual; abstract; overload; 396 527 procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF); virtual; abstract; overload; 528 procedure FillQuadPerspectiveMappingAntialias(pt1,pt2,pt3,pt4: TPointF; texture: IBGRAScanner; tex1, tex2, tex3, tex4: TPointF; ACleanBorders: TRect); virtual; abstract; overload; 397 529 398 530 procedure FillPolyLinearColor(const points: array of TPointF; AColors: array of TBGRAPixel); virtual; abstract; overload; … … 408 540 procedure ErasePoly(const points: array of TPointF; alpha: byte); virtual; abstract; 409 541 procedure ErasePolyAntialias(const points: array of TPointF; alpha: byte); virtual; abstract; 542 543 procedure FillShape(shape: TBGRACustomFillInfo; c: TBGRAPixel; drawmode: TDrawMode); virtual; abstract; 544 procedure FillShape(shape: TBGRACustomFillInfo; texture: IBGRAScanner; drawmode: TDrawMode); virtual; abstract; 545 procedure FillShapeAntialias(shape: TBGRACustomFillInfo; c: TBGRAPixel); virtual; abstract; 546 procedure FillShapeAntialias(shape: TBGRACustomFillInfo; texture: IBGRAScanner); virtual; abstract; 547 procedure EraseShape(shape: TBGRACustomFillInfo; alpha: byte); virtual; abstract; 548 procedure EraseShapeAntialias(shape: TBGRACustomFillInfo; alpha: byte); virtual; abstract; 410 549 411 550 procedure EllipseAntialias(x, y, rx, ry: single; c: TBGRAPixel; w: single); virtual; abstract; … … 427 566 procedure RectangleAntialias(x, y, x2, y2: single; texture: IBGRAScanner; w: single); virtual; abstract; overload; 428 567 429 procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer; BorderColor, FillColor: TBGRAPixel); virtual; abstract; 568 procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer; BorderColor, FillColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); virtual; abstract; overload; 569 procedure RoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer; BorderColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); virtual; abstract; overload; 430 570 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; c: TBGRAPixel; w: single; options: TRoundRectangleOptions = []); virtual; abstract; 431 571 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; pencolor: TBGRAPixel; w: single; fillcolor: TBGRAPixel; options: TRoundRectangleOptions = []); virtual; abstract; 432 572 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; penTexture: IBGRAScanner; w: single; fillTexture: IBGRAScanner; options: TRoundRectangleOptions = []); virtual; abstract; 433 573 procedure RoundRectAntialias(x,y,x2,y2,rx,ry: single; texture: IBGRAScanner; w: single; options: TRoundRectangleOptions = []); virtual; abstract; 574 procedure FillRoundRect(X1, Y1, X2, Y2: integer; DX, DY: integer; FillColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); virtual; 434 575 procedure FillRoundRectAntialias(x,y,x2,y2,rx,ry: single; c: TBGRAPixel; options: TRoundRectangleOptions = []); virtual; abstract; 435 576 procedure FillRoundRectAntialias(x,y,x2,y2,rx,ry: single; texture: IBGRAScanner; options: TRoundRectangleOptions = []); virtual; abstract; 436 577 procedure EraseRoundRectAntialias(x,y,x2,y2,rx,ry: single; alpha: byte; options: TRoundRectangleOptions = []); virtual; abstract; 437 578 579 procedure EllipseInRect(r: TRect; BorderColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); virtual; overload; 580 procedure EllipseInRect(r: TRect; BorderColor,FillColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); virtual; overload; 581 procedure FillEllipseInRect(r: TRect; FillColor: TBGRAPixel; ADrawMode: TDrawMode = dmDrawWithTransparency); virtual; 582 438 583 procedure FillRect(r: TRect; c: TColor); virtual; overload; 439 584 procedure FillRect(r: TRect; c: TBGRAPixel; mode: TDrawMode); virtual; overload; 585 procedure FillRect(r: TRect; texture: IBGRAScanner; mode: TDrawMode); virtual; overload; 440 586 procedure FillRect(x, y, x2, y2: integer; c: TColor); virtual; overload; 441 587 procedure FillRect(x, y, x2, y2: integer; c: TBGRAPixel; mode: TDrawMode); virtual; abstract; overload; 442 procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode); virtual; abstract; 588 procedure FillRect(x, y, x2, y2: integer; texture: IBGRAScanner; mode: TDrawMode); virtual; abstract; overload; 443 589 procedure FillRectAntialias(x, y, x2, y2: single; c: TBGRAPixel); virtual; abstract; 444 590 procedure FillRectAntialias(x, y, x2, y2: single; texture: IBGRAScanner); virtual; abstract; … … 446 592 procedure AlphaFillRect(x, y, x2, y2: integer; alpha: byte); virtual; abstract; 447 593 448 procedure TextOut(x, y: single; s: string; c: TBGRAPixel; align: TAlignment); virtual; abstract; overload; 449 procedure TextOut(x, y: single; s: string; texture: IBGRAScanner; align: TAlignment); virtual; abstract; overload; 450 procedure TextOutAngle(x, y: single; orientation: integer; s: string; c: TBGRAPixel; align: TAlignment); virtual; abstract; 451 procedure TextOutAngle(x, y: single; orientation: integer; s: string; texture: IBGRAScanner; align: TAlignment); virtual; abstract; 452 procedure TextOut(x, y: single; s: string; c: TBGRAPixel); virtual; overload; 453 procedure TextOut(x, y: single; s: string; c: TColor); virtual; overload; 454 procedure TextOut(x, y: single; s: string; texture: IBGRAScanner); virtual; overload; 455 procedure TextRect(ARect: TRect; x, y: integer; s: string; style: TTextStyle; c: TBGRAPixel); virtual; abstract; overload; 456 procedure TextRect(ARect: TRect; x, y: integer; s: string; style: TTextStyle; texture: IBGRAScanner); virtual; abstract; overload; 457 procedure TextRect(ARect: TRect; s: string; halign: TAlignment; valign: TTextLayout; c: TBGRAPixel); virtual; overload; 458 procedure TextRect(ARect: TRect; s: string; halign: TAlignment; valign: TTextLayout; texture: IBGRAScanner); virtual; overload; 459 function TextSize(s: string): TSize; virtual; abstract; 594 procedure TextOut(x, y: single; sUTF8: string; c: TBGRAPixel; align: TAlignment); virtual; abstract; overload; 595 procedure TextOut(x, y: single; sUTF8: string; texture: IBGRAScanner; align: TAlignment); virtual; abstract; overload; 596 procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; sUTF8: string; c: TBGRAPixel; align: TAlignment); virtual; abstract; 597 procedure TextOutAngle(x, y: single; orientationTenthDegCCW: integer; sUTF8: string; texture: IBGRAScanner; align: TAlignment); virtual; abstract; 598 procedure TextRect(ARect: TRect; x, y: integer; sUTF8: string; style: TTextStyle; c: TBGRAPixel); virtual; abstract; overload; 599 procedure TextRect(ARect: TRect; x, y: integer; sUTF8: string; style: TTextStyle; texture: IBGRAScanner); virtual; abstract; overload; 600 function TextSize(sUTF8: string): TSize; virtual; abstract; 601 602 { Draw the UTF8 encoded string, (x,y) being the top-left corner. The color c or texture is used to fill the text. 603 The value of FontOrientation is taken into account, so that the text may be rotated. } 604 procedure TextOut(x, y: single; sUTF8: string; c: TBGRAPixel); virtual; overload; 605 procedure TextOut(x, y: single; sUTF8: string; c: TColor); virtual; overload; 606 procedure TextOut(x, y: single; sUTF8: string; texture: IBGRAScanner); virtual; overload; 607 608 { Draw the UTF8 encoded string in the rectangle ARect. Text is wrapped if necessary. 609 The position depends on the specified horizontal alignment halign and vertical alignement valign. 610 The color c or texture is used to fill the text. No rotation is applied. } 611 procedure TextRect(ARect: TRect; sUTF8: string; halign: TAlignment; valign: TTextLayout; c: TBGRAPixel); virtual; overload; 612 procedure TextRect(ARect: TRect; sUTF8: string; halign: TAlignment; valign: TTextLayout; texture: IBGRAScanner); virtual; overload; 460 613 461 614 {Spline} … … 494 647 procedure AlphaFill(alpha: byte); virtual; overload; 495 648 procedure AlphaFill(alpha: byte; start, Count: integer); virtual; abstract; overload; 496 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel); virtual; abstract; overload; 497 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner); virtual; abstract; overload; 649 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel); virtual; overload; 650 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner); virtual; overload; 651 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel; ADrawMode: TDrawMode); virtual; abstract; overload; 652 procedure FillMask(x,y: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ADrawMode: TDrawMode); virtual; abstract; overload; 498 653 procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; color: TBGRAPixel; ARGBOrder: boolean = true); virtual; abstract; overload; 499 654 procedure FillClearTypeMask(x,y: integer; xThird: integer; AMask: TBGRACustomBitmap; texture: IBGRAScanner; ARGBOrder: boolean = true); virtual; abstract; overload; … … 529 684 530 685 {BGRA bitmap functions} 686 procedure CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadePosition: byte; mode: TDrawMode = dmDrawWithTransparency); virtual; abstract; 687 procedure CrossFade(ARect: TRect; Source1, Source2: IBGRAScanner; AFadeMask: IBGRAScanner; mode: TDrawMode = dmDrawWithTransparency); virtual; abstract; 531 688 procedure PutImage(x, y: integer; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); virtual; abstract; 689 procedure StretchPutImage(ARect: TRect; Source: TBGRACustomBitmap; mode: TDrawMode; AOpacity: byte = 255); virtual; abstract; 532 690 procedure PutImageSubpixel(x, y: single; Source: TBGRACustomBitmap); 533 691 procedure PutImagePart(x,y: integer; Source: TBGRACustomBitmap; SourceRect: TRect; mode: TDrawMode; AOpacity: byte = 255); 534 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOpacity: Byte=255); virtual; abstract; 535 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false); virtual; abstract; 692 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOpacity: Byte=255; ACorrectBlur: Boolean = false); overload; 693 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AOpacity: Byte=255); overload; 694 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOutputBounds: TRect; AResampleFilter: TResampleFilter; AMode: TDrawMode; AOpacity: Byte=255); virtual; abstract; overload; 695 procedure PutImageAffine(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap; AOutputBounds: TRect; AOpacity: Byte=255; ACorrectBlur: Boolean = false); overload; 696 function GetImageAffineBounds(Origin,HAxis,VAxis: TPointF; Source: TBGRACustomBitmap): TRect; 697 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false; ACorrectBlur: Boolean = false); overload; 698 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false; ACorrectBlur: Boolean = false); overload; 699 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; AResampleFilter: TResampleFilter; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false); overload; 700 procedure PutImageAngle(x,y: single; Source: TBGRACustomBitmap; angle: single; AResampleFilter: TResampleFilter; imageCenterX: single = 0; imageCenterY: single = 0; AOpacity: Byte=255; ARestoreOffsetAfterRotation: boolean = false); overload; 701 procedure ComputeImageAngleAxes(x,y,w,h,angle: single; imageCenterX,imageCenterY: single; ARestoreOffsetAfterRotation: boolean; 702 out Origin,HAxis,VAxis: TPointF); 703 function GetImageAngleBounds(x,y: single; Source: TBGRACustomBitmap; angle: single; imageCenterX: single = 0; imageCenterY: single = 0; ARestoreOffsetAfterRotation: boolean = false): TRect; 536 704 procedure BlendImage(x, y: integer; Source: TBGRACustomBitmap; operation: TBlendOperation); virtual; abstract; 537 705 procedure BlendImageOver(x, y: integer; Source: TBGRACustomBitmap; operation: TBlendOperation; AOpacity: byte = 255; … … 542 710 function Resample(newWidth, newHeight: integer; 543 711 mode: TResampleMode = rmFineResample): TBGRACustomBitmap; virtual; abstract; 544 procedure VerticalFlip; virtual; abstract; 545 procedure HorizontalFlip; virtual; abstract; 712 procedure VerticalFlip; virtual; overload; 713 procedure VerticalFlip(ARect: TRect); virtual; abstract; overload; 714 procedure HorizontalFlip; virtual; overload; 715 procedure HorizontalFlip(ARect: TRect); virtual; abstract; overload; 546 716 function RotateCW: TBGRACustomBitmap; virtual; abstract; 547 717 function RotateCCW: TBGRACustomBitmap; virtual; abstract; 548 718 procedure Negative; virtual; abstract; 719 procedure NegativeRect(ABounds: TRect); virtual; abstract; 549 720 procedure LinearNegative; virtual; abstract; 721 procedure LinearNegativeRect(ABounds: TRect); virtual; abstract; 722 procedure InplaceGrayscale; virtual; abstract; 723 procedure InplaceGrayscale(ABounds: TRect); virtual; abstract; 550 724 procedure ConvertToLinearRGB; virtual; abstract; 551 725 procedure ConvertFromLinearRGB; virtual; abstract; … … 553 727 procedure GrayscaleToAlpha; virtual; abstract; 554 728 procedure AlphaToGrayscale; virtual; abstract; 555 procedure ApplyMask(mask: TBGRACustomBitmap); virtual; abstract; 729 procedure ApplyMask(mask: TBGRACustomBitmap); overload; 730 procedure ApplyMask(mask: TBGRACustomBitmap; ARect: TRect); overload; 731 procedure ApplyMask(mask: TBGRACustomBitmap; ARect: TRect; AMaskRectTopLeft: TPoint); virtual; abstract; overload; 556 732 function GetImageBounds(Channel: TChannel = cAlpha; ANothingValue: Byte = 0): TRect; virtual; abstract; 557 function GetImageBounds(Channels: TChannels ): TRect; virtual; abstract;733 function GetImageBounds(Channels: TChannels; ANothingValue: Byte = 0): TRect; virtual; abstract; 558 734 function GetDifferenceBounds(ABitmap: TBGRACustomBitmap): TRect; virtual; abstract; 559 735 function MakeBitmapCopy(BackgroundColor: TColor): TBitmap; virtual; abstract; … … 563 739 function FilterMedian(Option: TMedianOption): TBGRACustomBitmap; virtual; abstract; 564 740 function FilterSmooth: TBGRACustomBitmap; virtual; abstract; 565 function FilterSharpen: TBGRACustomBitmap; virtual; abstract; 741 function FilterSharpen(Amount: single = 1): TBGRACustomBitmap; virtual; abstract; 742 function FilterSharpen(ABounds: TRect; Amount: single = 1): TBGRACustomBitmap; virtual; abstract; 566 743 function FilterContour: TBGRACustomBitmap; virtual; abstract; 744 function FilterPixelate(pixelSize: integer; useResample: boolean; filter: TResampleFilter = rfLinear): TBGRACustomBitmap; virtual; abstract; 567 745 function FilterBlurRadial(radius: integer; 568 746 blurType: TRadialBlurType): TBGRACustomBitmap; virtual; abstract; 569 function FilterPixelate(pixelSize: integer; useResample: boolean; filter: TResampleFilter = rfLinear): TBGRACustomBitmap; virtual; abstract; 747 function FilterBlurRadial(ABounds: TRect; radius: integer; 748 blurType: TRadialBlurType): TBGRACustomBitmap; virtual; abstract; 570 749 function FilterBlurMotion(distance: integer; angle: single; 571 750 oriented: boolean): TBGRACustomBitmap; virtual; abstract; 751 function FilterBlurMotion(ABounds: TRect; distance: integer; angle: single; 752 oriented: boolean): TBGRACustomBitmap; virtual; abstract; 572 753 function FilterCustomBlur(mask: TBGRACustomBitmap): TBGRACustomBitmap; virtual; abstract; 754 function FilterCustomBlur(ABounds: TRect; mask: TBGRACustomBitmap): TBGRACustomBitmap; virtual; abstract; 573 755 function FilterEmboss(angle: single): TBGRACustomBitmap; virtual; abstract; 756 function FilterEmboss(angle: single; ABounds: TRect): TBGRACustomBitmap; virtual; abstract; 574 757 function FilterEmbossHighlight(FillSelection: boolean): TBGRACustomBitmap; virtual; abstract; 575 758 function FilterEmbossHighlight(FillSelection: boolean; BorderColor: TBGRAPixel): TBGRACustomBitmap; virtual; abstract; 576 759 function FilterEmbossHighlight(FillSelection: boolean; BorderColor: TBGRAPixel; var Offset: TPoint): TBGRACustomBitmap; virtual; abstract; 577 760 function FilterGrayscale: TBGRACustomBitmap; virtual; abstract; 761 function FilterGrayscale(ABounds: TRect): TBGRACustomBitmap; virtual; abstract; 578 762 function FilterNormalize(eachChannel: boolean = True): TBGRACustomBitmap; virtual; abstract; 579 function FilterRotate(origin: TPointF; angle: single): TBGRACustomBitmap; virtual; abstract; 763 function FilterNormalize(ABounds: TRect; eachChannel: boolean = True): TBGRACustomBitmap; virtual; abstract; 764 function FilterRotate(origin: TPointF; angle: single; correctBlur: boolean = false): TBGRACustomBitmap; virtual; abstract; 580 765 function FilterSphere: TBGRACustomBitmap; virtual; abstract; 581 766 function FilterTwirl(ACenter: TPoint; ARadius: Single; ATurn: Single=1; AExponent: Single=3): TBGRACustomBitmap; virtual; abstract; 767 function FilterTwirl(ABounds: TRect; ACenter: TPoint; ARadius: Single; ATurn: Single=1; AExponent: Single=3): TBGRACustomBitmap; virtual; abstract; 582 768 function FilterCylinder: TBGRACustomBitmap; virtual; abstract; 583 769 function FilterPlane: TBGRACustomBitmap; virtual; abstract; 584 770 585 property Data: PBGRAPixel Read GetDataPtr; 586 property Width: integer Read GetWidth; 587 property Height: integer Read GetHeight; 588 property NbPixels: integer Read GetNbPixels; 589 property Empty: boolean Read CheckEmpty; 590 591 property ScanLine[y: integer]: PBGRAPixel Read GetScanLine; 771 property Width: integer Read GetWidth; //width of the image in pixels 772 property Height: integer Read GetHeight; //height of the image in pixels 773 property NbPixels: integer Read GetNbPixels; //total number of pixels. It is always true that NbPixels = Width * Height 774 775 property ScanLine[y: integer]: PBGRAPixel Read GetScanLine; //Returns the address of the left-most pixel of any line. 776 //The parameter y ranges from 0 to Height-1. 777 778 property LineOrder: TRawImageLineOrder Read GetLineOrder; //Indicates the order in which lines are stored in memory. 779 //If it is equal to riloTopToBottom, the first line is the top line. 780 //If it is equal to riloBottomToTop, the first line is the bottom line. 781 782 property Data: PBGRAPixel Read GetDataPtr; //Provides a pointer to the first pixel in memory. 783 //Depending on the LineOrder property, this can be the top-left pixel or the bottom-left pixel. 784 //There is no padding between scanlines, so the start of the next line is at the address Data + Width. 785 786 property Empty: boolean Read CheckEmpty; //Returns True if the bitmap only contains transparent pixels or has a size of zero. 787 788 property HasTransparentPixels: boolean Read GetHasTransparentPixels; //Returns True if there are transparent or semitransparent pixels, 789 //and so if the image would be stored with an alpha channel. 790 592 791 property RefCount: integer Read GetRefCount; 593 792 property Bitmap: TBitmap Read GetBitmap; //don't forget to call InvalidateBitmap before if you changed something with Scanline 594 property HasTransparentPixels: boolean Read GetHasTransparentPixels;595 793 property AverageColor: TColor Read GetAverageColor; 596 794 property AveragePixel: TBGRAPixel Read GetAveragePixel; 597 property LineOrder: TRawImageLineOrder Read GetLineOrder;598 795 property CanvasFP: TFPImageCanvas read GetCanvasFP; 599 796 property CanvasDrawModeFP: TDrawMode read GetCanvasDrawModeFP write SetCanvasDrawModeFP; … … 603 800 Read GetCanvasAlphaCorrection Write SetCanvasAlphaCorrection; 604 801 605 property FontHeight: integer Read GetFontHeight Write SetFontHeight;606 802 property PenStyle: TPenStyle read GetPenStyle Write SetPenStyle; 607 803 property CustomPenStyle: TBGRAPenStyle read GetCustomPenStyle write SetCustomPenStyle; 608 804 property ClipRect: TRect read GetClipRect write SetClipRect; 609 property FontAntialias: Boolean read GetFontAntialias write SetFontAntialias; //antialiasing (it's different from TFont antialiasing mode) 805 806 { Specifies the height of the font without taking into account additional line spacing. 807 A negative value means that it is the full height instead (see below). } 808 property FontHeight: integer Read GetFontHeight Write SetFontHeight; 809 810 { Specifies the height of the font, taking into account the additional line spacing defined for the font. } 610 811 property FontFullHeight: integer read GetFontFullHeight write SetFontFullHeight; 611 property FontPixelMetric: TFontPixelMetric read GetFontPixelMetric; 612 613 //interface 614 function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 615 function _AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 616 function _Release: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 812 813 property FontAntialias: Boolean read GetFontAntialias write SetFontAntialias; //Simplified property to specify the quality. 814 property FontPixelMetric: TFontPixelMetric read GetFontPixelMetric; //Returns measurement for the current font in pixels. 815 816 { Specifies the font renderer. By default it is an instance of TLCLFontRenderer of unit BGRAText. 817 Other renderers are provided in BGRATextFX unit and BGRAVectorize unit. 818 Once you assign a renderer, it will automatically be freed. 819 The renderers may provide additional styling for the font. } 820 property FontRenderer: TBGRACustomFontRenderer read GetFontRenderer write SetFontRenderer; 821 822 property LineCap: TPenEndCap read GetLineCap write SetLineCap; 823 property ArrowStartSize: TPointF read GetArrowStartSize write SetArrowStartSize; 824 property ArrowEndSize: TPointF read GetArrowEndSize write SetArrowEndSize; 825 property ArrowStartOffset: single read GetArrowStartOffset write SetArrowStartOffset; 826 property ArrowEndOffset: single read GetArrowEndOffset write SetArrowEndOffset; 827 property ArrowStartRepeat: integer read GetArrowStartRepeat write SetArrowStartRepeat; 828 property ArrowEndRepeat: integer read GetArrowEndRepeat write SetArrowEndRepeat; 617 829 618 830 //IBGRAScanner … … 623 835 procedure ScanPutPixels(pdest: PBGRAPixel; count: integer; mode: TDrawMode); virtual; 624 836 function IsScanPutPixelsDefined: boolean; virtual; 837 838 protected 839 //interface 840 function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 841 function _AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 842 function _Release: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 843 625 844 end; 626 845 … … 637 856 procedure ScanPutPixels(pdest: PBGRAPixel; count: integer; mode: TDrawMode); virtual; 638 857 function IsScanPutPixelsDefined: boolean; virtual; 858 protected 639 859 function QueryInterface({$IFDEF FPC_HAS_CONSTREF}constref{$ELSE}const{$ENDIF} IID: TGUID; out Obj): HResult; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; 640 860 function _AddRef: Integer; {$IF (not defined(WINDOWS)) AND (FPC_FULLVERSION>=20501)}cdecl{$ELSE}stdcall{$IFEND}; … … 653 873 end; 654 874 875 { TIntersectionInfo } 876 877 TIntersectionInfo = class 878 interX: single; 879 winding: integer; 880 numSegment: integer; 881 procedure SetValues(AInterX: Single; AWinding, ANumSegment: integer); 882 end; 883 ArrayOfTIntersectionInfo = array of TIntersectionInfo; 884 885 TBGRACustomFillInfo = class 886 public 887 //returns true if the same segment number can be curved 888 function SegmentsCurved: boolean; virtual; abstract; 889 890 //returns integer bounds 891 function GetBounds: TRect; virtual; abstract; 892 893 //compute min-max to be drawn on destination bitmap according to cliprect. Returns false if 894 //there is nothing to draw 895 function ComputeMinMax(out minx,miny,maxx,maxy: integer; bmpDest: TBGRACustomBitmap): boolean; virtual; abstract; 896 897 //check if the point is inside the filling zone 898 function IsPointInside(x,y: single; windingMode: boolean): boolean; virtual; abstract; 899 900 //create an array that will contain computed intersections. 901 //you may augment, in this case, use CreateIntersectionInfo for new items 902 function CreateIntersectionArray: ArrayOfTIntersectionInfo; virtual; abstract; 903 function CreateIntersectionInfo: TIntersectionInfo; virtual; abstract; //creates a single info 904 procedure FreeIntersectionArray(var inter: ArrayOfTIntersectionInfo); virtual; abstract; 905 906 //fill a previously created array of intersections with actual intersections at the current y coordinate. 907 //nbInter gets the number of computed intersections 908 procedure ComputeAndSort(cury: single; var inter: ArrayOfTIntersectionInfo; out nbInter: integer; windingMode: boolean); virtual; abstract; 909 end; 910 911 { TBGRACustomFontRenderer } 912 913 TBGRACustomFontRenderer = class 914 FontName: string; //Specifies the font to use. Unless the font renderer accept otherwise, 915 //the name is in human readable form, like 'Arial', 'Times New Roman', ... 916 917 FontStyle: TFontStyles; //Specifies the set of styles to be applied to the font. 918 //These can be fsBold, fsItalic, fsStrikeOut, fsUnderline. 919 //So the value [fsBold,fsItalic] means that the font must be bold and italic. 920 921 FontQuality : TBGRAFontQuality;//Specifies the quality of rendering. Default value is fqSystem. 922 923 FontOrientation: integer; //Specifies the rotation of the text, for functions that support text rotation. 924 //It is expressed in tenth of degrees, positive values going counter-clockwise. 925 926 FontEmHeight: integer; // Specifies the height of the font without taking into account additional line spacing. 927 // A negative value means that it is the full height instead. 928 929 { Returns measurement for the current font in pixels. } 930 function GetFontPixelMetric: TFontPixelMetric; virtual; abstract; 931 932 { Returns the total size of the string provided using the current font. 933 Orientation is not taken into account, so that the width is along the text. } 934 function TextSize(sUTF8: string): TSize; virtual; abstract; 935 936 { Draws the UTF8 encoded string, with color c. 937 If align is taLeftJustify, (x,y) is the top-left corner. 938 If align is taCenter, (x,y) is at the top and middle of the text. 939 If align is taRightJustify, (x,y) is the top-right corner. 940 The value of FontOrientation is taken into account, so that the text may be rotated. } 941 procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; sUTF8: string; c: TBGRAPixel; align: TAlignment); virtual; abstract; 942 943 { Same as above functions, except that the text is filled using texture. 944 The value of FontOrientation is taken into account, so that the text may be rotated. } 945 procedure TextOut(ADest: TBGRACustomBitmap; x, y: single; sUTF8: string; texture: IBGRAScanner; align: TAlignment); virtual; abstract; 946 947 { Same as above, except that the orientation is specified, overriding the value of the property FontOrientation. } 948 procedure TextOutAngle(ADest: TBGRACustomBitmap; x, y: single; orientationTenthDegCCW: integer; sUTF8: string; c: TBGRAPixel; align: TAlignment); virtual; abstract; 949 procedure TextOutAngle(ADest: TBGRACustomBitmap; x, y: single; orientationTenthDegCCW: integer; sUTF8: string; texture: IBGRAScanner; align: TAlignment); virtual; abstract; 950 951 { Draw the UTF8 encoded string at the coordinate (x,y), clipped inside the rectangle ARect. 952 Additional style information is provided by the style parameter. 953 The color c or texture is used to fill the text. No rotation is applied. } 954 procedure TextRect(ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; sUTF8: string; style: TTextStyle; c: TBGRAPixel); virtual; abstract; 955 procedure TextRect(ADest: TBGRACustomBitmap; ARect: TRect; x, y: integer; sUTF8: string; style: TTextStyle; texture: IBGRAScanner); virtual; abstract; 956 957 { Copy the path for the UTF8 encoded string into ADest. 958 If align is taLeftJustify, (x,y) is the top-left corner. 959 If align is taCenter, (x,y) is at the top and middle of the text. 960 If align is taRightJustify, (x,y) is the top-right corner. } 961 procedure CopyTextPathTo({%H-}ADest: IBGRAPath; {%H-}x, {%H-}y: single; {%H-}s: string; {%H-}align: TAlignment); virtual; //optional 962 end; 963 655 964 type 656 965 TBGRABitmapAny = class of TBGRACustomBitmap; //used to create instances of the same type (see NewBitmap) 966 TBGRATextOutImproveReadabilityMode = (irMask, irNormal, irClearTypeRGB, irClearTypeBGR); 657 967 658 968 var 659 969 BGRABitmapFactory : TBGRABitmapAny; 970 BGRATextOutImproveReadabilityProc : procedure (bmp: TBGRACustomBitmap; AFont: TFont; xf,yf: single; text: string; color: TBGRAPixel; tex: IBGRAScanner; align: TAlignment; mode : TBGRATextOutImproveReadabilityMode); 971 972 function CheckPutImageBounds(x, y, tx, ty: integer; out minxb, minyb, maxxb, maxyb, ignoreleft: integer; const cliprect: TRect): boolean; inline; 660 973 661 974 { Color functions } 662 function GetIntensity(c: TExpandedPixel): word; inline; 663 function SetIntensity(c: TExpandedPixel; intensity: word): TExpandedPixel; 664 function GetLightness(c: TExpandedPixel): word; inline; 665 function SetLightness(c: TExpandedPixel; lightness: word): TExpandedPixel; 975 function GetIntensity(const c: TExpandedPixel): word; inline; 976 function GetIntensity(c: TBGRAPixel): word; inline; 977 function SetIntensity(const c: TExpandedPixel; intensity: word): TExpandedPixel; 978 function SetIntensity(c: TBGRAPixel; intensity: word): TBGRAPixel; 979 function GetLightness(c: TBGRAPixel): word; 980 function GetLightness(const c: TExpandedPixel): word; inline; 981 function SetLightness(const c: TExpandedPixel; lightness: word): TExpandedPixel; 982 function SetLightness(c: TBGRAPixel; lightness: word): TBGRAPixel; 983 function SetLightness(const c: TExpandedPixel; lightness: word; curLightness: word): TExpandedPixel; //if you already know the current lightness of the color 666 984 function ApplyLightnessFast(color: TBGRAPixel; lightness: word): TBGRAPixel; inline; 667 985 function ApplyIntensityFast(color: TBGRAPixel; lightness: longword): TBGRAPixel; 668 function CombineLightness(lightness1,lightness2: integer): integer;986 function CombineLightness(lightness1,lightness2: Int32or64): Int32or64; 669 987 function BGRAToHSLA(c: TBGRAPixel): THSLAPixel; 670 function ExpandedToHSLA(ec: TExpandedPixel): THSLAPixel; inline; 671 function BGRAToGSBA(c: TBGRAPixel): THSLAPixel; 672 function HSLAToExpanded(c: THSLAPixel): TExpandedPixel; 673 function HSLAToBGRA(c: THSLAPixel): TBGRAPixel; 988 function ExpandedToHSLA(const ec: TExpandedPixel): THSLAPixel; 989 function ExpandedToGSBA(ec: TExpandedPixel): TGSBAPixel; 990 function BGRAToGSBA(c: TBGRAPixel): TGSBAPixel; 991 function HSLAToExpanded(const c: THSLAPixel): TExpandedPixel; 992 function HSLAToBGRA(const c: THSLAPixel): TBGRAPixel; 674 993 function GtoH(ghue: word): word; 675 994 function HtoG(hue: word): word; … … 677 996 function GetHue(ec: TExpandedPixel): word; 678 997 function ColorImportance(ec: TExpandedPixel): word; 679 function GSBAToBGRA(c: THSLAPixel): TBGRAPixel; 680 function GSBAToHSLA(c: THSLAPixel): THSLAPixel; 998 function GSBAToBGRA(c: TGSBAPixel): TBGRAPixel; 999 function GSBAToExpanded(c: TGSBAPixel): TExpandedPixel; 1000 function GSBAToHSLA(c: TGSBAPixel): THSLAPixel; 681 1001 function GammaExpansion(c: TBGRAPixel): TExpandedPixel; inline; 682 function GammaCompression( ec: TExpandedPixel): TBGRAPixel; inline;1002 function GammaCompression(const ec: TExpandedPixel): TBGRAPixel; inline; 683 1003 function GammaCompression(red,green,blue,alpha: word): TBGRAPixel; inline; 684 1004 function BGRAToGrayscale(c: TBGRAPixel): TBGRAPixel; … … 707 1027 operator * (const c1: TColorF; factor: single): TColorF; inline; 708 1028 function ColorF(red,green,blue,alpha: single): TColorF; 709 function BGRAToStr(c: TBGRAPixel): string; 710 function StrToBGRA(str: string): TBGRAPixel; 711 function StrToBGRA(str: string; DefaultColor: TBGRAPixel): TBGRAPixel; 1029 function BGRAToStr(c: TBGRAPixel; AColorList: TBGRAColorList = nil; AMaxDiff: Word= 0): string; 1030 function StrToBGRA(str: string): TBGRAPixel; //full parse 1031 function StrToBGRA(str: string; const DefaultColor: TBGRAPixel): TBGRAPixel; //full parse with default when error or missing values 1032 function PartialStrToBGRA(str: string; const fallbackValues: TBGRAPixel; out error: boolean): TBGRAPixel; //partial parse allowed 1033 procedure TryStrToBGRA(str: string; var parsedValue: TBGRAPixel; out missingValues: boolean; out error: boolean); 712 1034 713 1035 { Get height [0..1] stored in a TBGRAPixel } … … 736 1058 operator * (const pt1: TPointF; factor: single): TPointF; inline; 737 1059 operator * (factor: single; const pt1: TPointF): TPointF; inline; 738 function PtInRect(pt: TPoint; r: TRect): boolean; 1060 function PtInRect(const pt: TPoint; r: TRect): boolean; overload; 1061 function RectWithSize(left,top,width,height: integer): TRect; 739 1062 function VectLen(dx,dy: single): single; overload; 740 1063 function VectLen(v: TPointF): single; overload; … … 753 1076 754 1077 { Cyclic functions } 755 function PositiveMod(value, cycle: integer): integer; inline;1078 function PositiveMod(value, cycle: Int32or64): Int32or64; inline; overload; 756 1079 757 1080 { Sin65536 and Cos65536 are fast routines to compute sine and cosine as integer values. … … 761 1084 without applying a modulo. } 762 1085 procedure PrecalcSin65536; // compute all values now 763 function Sin65536(value: word): integer; inline;764 function Cos65536(value: word): integer; inline;1086 function Sin65536(value: word): Int32or64; inline; 1087 function Cos65536(value: word): Int32or64; inline; 765 1088 function ByteSqrt(value: byte): byte; inline; 766 1089 1090 function DetectFileFormat(AFilenameUTF8: string): TBGRAImageFormat; 1091 function DetectFileFormat(AStream: TStream; ASuggestedExtensionUTF8: string = ''): TBGRAImageFormat; 1092 function SuggestImageFormat(AFilenameOrExtensionUTF8: string): TBGRAImageFormat; 1093 function CreateBGRAImageReader(AFormat: TBGRAImageFormat): TFPCustomImageReader; 1094 function CreateBGRAImageWriter(AFormat: TBGRAImageFormat; AHasTransparentPixels: boolean): TFPCustomImageWriter; 1095 767 1096 implementation 768 1097 769 uses Math, SysUtils; 1098 uses Math, SysUtils, FileUtil, lazutf8classes, LCLProc, 1099 FPReadTiff, FPReadXwd, FPReadXPM, 1100 FPWriteTiff, FPWriteJPEG, FPWritePNG, FPWriteBMP, FPWritePCX, 1101 FPWriteTGA, FPWriteXPM; 1102 1103 function StrToResampleFilter(str: string): TResampleFilter; 1104 var f: TResampleFilter; 1105 begin 1106 result := rfLinear; 1107 str := LowerCase(str); 1108 for f := low(TResampleFilter) to high(TResampleFilter) do 1109 if CompareText(str,ResampleFilterStr[f])=0 then 1110 begin 1111 result := f; 1112 exit; 1113 end; 1114 end; 770 1115 771 1116 function StrToBlendOperation(str: string): TBlendOperation; … … 937 1282 end; 938 1283 1284 //straight line 1285 function BezierCurve(origin, destination: TPointF): TQuadraticBezierCurve; 1286 begin 1287 result.p1 := origin; 1288 result.c := (origin+destination)*0.5; 1289 result.p2 := destination; 1290 end; 1291 1292 function ArcDef(cx, cy, rx, ry, xAngleRadCW, startAngleRadCW, endAngleRadCW: single; 1293 anticlockwise: boolean): TArcDef; 1294 begin 1295 result.center := PointF(cx,cy); 1296 result.radius := PointF(rx,ry); 1297 result.xAngleRadCW:= xAngleRadCW; 1298 result.startAngleRadCW := startAngleRadCW; 1299 result.endAngleRadCW:= endAngleRadCW; 1300 result.anticlockwise:= anticlockwise; 1301 end; 1302 939 1303 { Check if a PointF structure is empty or should be treated as a list separator } 940 1304 function isEmptyPointF(pt: TPointF): boolean; 941 1305 begin 942 1306 Result := (pt.x = EmptySingle) and (pt.y = EmptySingle); 1307 end; 1308 1309 { TBGRACustomFontRenderer } 1310 1311 procedure TBGRACustomFontRenderer.CopyTextPathTo(ADest: IBGRAPath; x, y: single; s: string; align: TAlignment); 1312 begin 1313 end; 1314 1315 { TIntersectionInfo } 1316 1317 procedure TIntersectionInfo.SetValues(AInterX: Single; AWinding, 1318 ANumSegment: integer); 1319 begin 1320 interX := AInterX; 1321 winding := AWinding; 1322 numSegment := ANumSegment; 943 1323 end; 944 1324 … … 991 1371 end; 992 1372 993 procedure TBGRAColorList.Add(Name: string; Color: TBGRAPixel);1373 procedure TBGRAColorList.Add(Name: string; const Color: TBGRAPixel); 994 1374 begin 995 1375 if FFinished then … … 1021 1401 end; 1022 1402 1403 function TBGRAColorList.IndexOfColor(const AColor: TBGRAPixel; AMaxDiff: Word = 0): integer; 1404 var i: integer; 1405 MinDiff,CurDiff: Word; 1406 begin 1407 if AMaxDiff = 0 then 1408 begin 1409 for i := 0 to FNbColors-1 do 1410 if AColor = FColors[i].Color then 1411 begin 1412 result := i; 1413 exit; 1414 end; 1415 result := -1; 1416 end else 1417 begin 1418 MinDiff := AMaxDiff; 1419 result := -1; 1420 for i := 0 to FNbColors-1 do 1421 begin 1422 CurDiff := BGRAWordDiff(AColor,FColors[i].Color); 1423 if CurDiff <= MinDiff then 1424 begin 1425 result := i; 1426 MinDiff := CurDiff; 1427 if MinDiff = 0 then exit; 1428 end; 1429 end; 1430 end; 1431 end; 1432 1023 1433 { TBGRACustomBitmap } 1024 1434 … … 1039 1449 procedure TBGRACustomBitmap.LoadFromFile(const filename: string); 1040 1450 begin 1041 inherited LoadFromFile(filename); 1451 LoadFromFileUTF8(SysToUtf8(filename)); 1452 end; 1453 1454 procedure TBGRACustomBitmap.LoadFromFileUTF8(const filenameUTF8: string); 1455 var 1456 Stream: TStream; 1457 format: TBGRAImageFormat; 1458 reader: TFPCustomImageReader; 1459 begin 1460 stream := TFileStreamUTF8.Create(filenameUTF8,fmOpenRead or fmShareDenyWrite); 1461 try 1462 format := DetectFileFormat(Stream, ExtractFileExt(filenameUTF8)); 1463 reader := CreateBGRAImageReader(format); 1464 try 1465 LoadFromStream(stream, reader); 1466 finally 1467 reader.Free; 1468 end; 1469 finally 1470 ClearTransparentPixels; 1471 stream.Free; 1472 end; 1473 end; 1474 1475 procedure TBGRACustomBitmap.LoadFromFileUTF8(const filenameUTF8: string; 1476 AHandler: TFPCustomImageReader); 1477 var 1478 Stream: TStream; 1479 begin 1480 stream := TFileStreamUTF8.Create(filenameUTF8,fmOpenRead or fmShareDenyWrite); 1481 try 1482 LoadFromStream(stream, AHandler); 1483 finally 1484 ClearTransparentPixels; 1485 stream.Free; 1486 end; 1042 1487 end; 1043 1488 1044 1489 procedure TBGRACustomBitmap.SaveToFile(const filename: string); 1045 1490 begin 1046 inherited SaveToFile(filename); 1491 SaveToFileUTF8(SysToUtf8(filename)); 1492 end; 1493 1494 procedure TBGRACustomBitmap.SaveToFileUTF8(const filenameUTF8: string); 1495 var 1496 writer: TFPCustomImageWriter; 1497 format: TBGRAImageFormat; 1498 begin 1499 format := SuggestImageFormat(filenameUTF8); 1500 writer := CreateBGRAImageWriter(Format, HasTransparentPixels); 1501 try 1502 SaveToFileUTF8(filenameUTF8, writer); 1503 finally 1504 writer.free; 1505 end; 1047 1506 end; 1048 1507 … … 1050 1509 Handler: TFPCustomImageWriter); 1051 1510 begin 1052 inherited SaveToFile(filename, Handler); 1511 SaveToFileUTF8(SysToUtf8(filename),Handler); 1512 end; 1513 1514 procedure TBGRACustomBitmap.SaveToFileUTF8(const filenameUTF8: string; 1515 Handler: TFPCustomImageWriter); 1516 var 1517 stream: TFileStreamUTF8; 1518 begin 1519 stream := TFileStreamUTF8.Create(filenameUTF8,fmCreate); 1520 try 1521 SaveToStream(stream, Handler); 1522 finally 1523 stream.Free; 1524 end; 1525 end; 1526 1527 procedure TBGRACustomBitmap.SaveToStreamAs(Str: TStream; 1528 AFormat: TBGRAImageFormat); 1529 var handler: TFPCustomImageWriter; 1530 begin 1531 handler := CreateBGRAImageWriter(AFormat, HasTransparentPixels); 1532 try 1533 SaveToStream(Str, handler) 1534 finally 1535 handler.Free; 1536 end; 1537 end; 1538 1539 procedure TBGRACustomBitmap.DrawPixel(x, y: int32or64; c: TBGRAPixel; 1540 ADrawMode: TDrawMode); 1541 begin 1542 case ADrawMode of 1543 dmSet: SetPixel(x,y,c); 1544 dmSetExceptTransparent: if c.alpha = 255 then SetPixel(x,y,c); 1545 dmLinearBlend: FastBlendPixel(x,y,c); 1546 dmDrawWithTransparency: DrawPixel(x,y,c); 1547 dmXor: XorPixel(x,y,c); 1548 end; 1549 end; 1550 1551 procedure TBGRACustomBitmap.LoadFromStream(Str: TStream); 1552 var 1553 format: TBGRAImageFormat; 1554 reader: TFPCustomImageReader; 1555 begin 1556 format := DetectFileFormat(Str); 1557 reader := CreateBGRAImageReader(format); 1558 try 1559 LoadFromStream(Str,reader); 1560 finally 1561 reader.Free; 1562 end; 1053 1563 end; 1054 1564 … … 1057 1567 FP drawing mode is temporarily changed to load 1058 1568 bitmaps properly } 1059 procedure TBGRACustomBitmap.LoadFromStream(Str: TStream);1060 var1061 OldDrawMode: TDrawMode;1062 begin1063 OldDrawMode := CanvasDrawModeFP;1064 CanvasDrawModeFP := dmSet;1065 try1066 if not LoadAsBmp32(Str) then1067 inherited LoadFromStream(Str);1068 finally1069 CanvasDrawModeFP := OldDrawMode;1070 end;1071 end;1072 1073 { See above }1074 1569 procedure TBGRACustomBitmap.LoadFromStream(Str: TStream; 1075 1570 Handler: TFPCustomImageReader); … … 1087 1582 1088 1583 { Look for a pixel considering the bitmap is repeated in both directions } 1089 function TBGRACustomBitmap.GetPixelCycle(x, y: int eger): TBGRAPixel;1584 function TBGRACustomBitmap.GetPixelCycle(x, y: int32or64): TBGRAPixel; 1090 1585 begin 1091 1586 if (Width = 0) or (Height = 0) then … … 1093 1588 else 1094 1589 Result := (Scanline[PositiveMod(y,Height)] + PositiveMod(x,Width))^; 1590 end; 1591 1592 procedure TBGRACustomBitmap.DrawHorizLine(x, y, x2: int32or64; 1593 texture: IBGRAScanner); 1594 begin 1595 HorizLine(x,y,x2,texture,dmDrawWithTransparency); 1596 end; 1597 1598 procedure TBGRACustomBitmap.HorizLine(x, y, x2: Int32or64; c: TBGRAPixel; 1599 ADrawMode: TDrawMode); 1600 begin 1601 case ADrawMode of 1602 dmSet: SetHorizLine(x,y,x2,c); 1603 dmSetExceptTransparent: if c.alpha = 255 then SetHorizLine(x,y,x2,c); 1604 dmXor: XorHorizLine(x,y,x2,c); 1605 dmLinearBlend: FastBlendHorizLine(x,y,x2,c); 1606 dmDrawWithTransparency: DrawHorizLine(x,y,x2,c); 1607 end; 1608 end; 1609 1610 procedure TBGRACustomBitmap.VertLine(x, y, y2: Int32or64; c: TBGRAPixel; 1611 ADrawMode: TDrawMode); 1612 begin 1613 case ADrawMode of 1614 dmSet: SetVertLine(x,y,y2,c); 1615 dmSetExceptTransparent: if c.alpha = 255 then SetVertLine(x,y,y2,c); 1616 dmXor: XorVertLine(x,y,y2,c); 1617 dmLinearBlend: FastBlendVertLine(x,y,y2,c); 1618 dmDrawWithTransparency: DrawVertLine(x,y,y2,c); 1619 end; 1620 end; 1621 1622 procedure TBGRACustomBitmap.ArrowStartAsNone; 1623 begin 1624 SetArrowStart(asNone); 1625 end; 1626 1627 procedure TBGRACustomBitmap.ArrowStartAsClassic(AFlipped: boolean; ACut: boolean; ARelativePenWidth: single); 1628 var join: TPenJoinStyle; 1629 begin 1630 if (LineCap = pecRound) and not ACut then join := pjsRound else join := pjsMiter; 1631 if ACut then 1632 begin 1633 if AFlipped then 1634 SetArrowStart(asFlippedCut,join,ARelativePenWidth) 1635 else 1636 SetArrowStart(asCut,join,ARelativePenWidth) 1637 end 1638 else 1639 begin 1640 if AFlipped then 1641 SetArrowStart(asFlipped,join,ARelativePenWidth) 1642 else 1643 SetArrowStart(asNormal,join,ARelativePenWidth) 1644 end; 1645 end; 1646 1647 procedure TBGRACustomBitmap.ArrowStartAsTriangle(ABackOffset: single; ARounded: boolean; AHollow: boolean; 1648 AHollowPenWidth: single); 1649 var join: TPenJoinStyle; 1650 begin 1651 if ARounded then join := pjsRound else join := pjsMiter; 1652 if AHollow then 1653 SetArrowStart(asHollowTriangle, join,AHollowPenWidth, ABackOffset) 1654 else 1655 SetArrowStart(asTriangle, join,1,ABackOffset); 1656 end; 1657 1658 procedure TBGRACustomBitmap.ArrowStartAsTail; 1659 begin 1660 SetArrowStart(asTail); 1661 end; 1662 1663 procedure TBGRACustomBitmap.ArrowEndAsNone; 1664 begin 1665 SetArrowEnd(asNone); 1666 end; 1667 1668 procedure TBGRACustomBitmap.ArrowEndAsClassic(AFlipped: boolean; ACut: boolean; ARelativePenWidth: single); 1669 var join: TPenJoinStyle; 1670 begin 1671 if (LineCap = pecRound) and not ACut then join := pjsRound else join := pjsMiter; 1672 if ACut then 1673 begin 1674 if AFlipped then 1675 SetArrowEnd(asFlippedCut,join,ARelativePenWidth) 1676 else 1677 SetArrowEnd(asCut,join,ARelativePenWidth) 1678 end 1679 else 1680 begin 1681 if AFlipped then 1682 SetArrowEnd(asFlipped,join,ARelativePenWidth) 1683 else 1684 SetArrowEnd(asNormal,join,ARelativePenWidth) 1685 end; 1686 end; 1687 1688 procedure TBGRACustomBitmap.ArrowEndAsTriangle(ABackOffset: single; ARounded: boolean; AHollow: boolean; 1689 AHollowPenWidth: single); 1690 var join: TPenJoinStyle; 1691 begin 1692 if ARounded then join := pjsRound else join := pjsMiter; 1693 if AHollow then 1694 SetArrowEnd(asHollowTriangle, join,AHollowPenWidth, ABackOffset) 1695 else 1696 SetArrowEnd(asTriangle, join,1, ABackOffset); 1697 end; 1698 1699 procedure TBGRACustomBitmap.ArrowEndAsTail; 1700 begin 1701 SetArrowEnd(asTail); 1702 end; 1703 1704 procedure TBGRACustomBitmap.DrawPolyLine(const points: array of TPoint; 1705 c: TBGRAPixel; DrawLastPixel: boolean; ADrawMode: TDrawMode); 1706 var i: integer; 1707 begin 1708 if length(points) = 1 then 1709 begin 1710 if DrawLastPixel then DrawPixel(points[0].x,points[0].y,c,ADrawMode); 1711 end 1712 else 1713 for i := 0 to high(points)-1 do 1714 DrawLine(points[i].x,points[i].Y,points[i+1].x,points[i+1].y,c,DrawLastPixel and (i=high(points)-1),ADrawMode); 1095 1715 end; 1096 1716 … … 1102 1722 if length(points) = 1 then 1103 1723 begin 1104 if DrawLastPixel then Draw Pixel(points[0].x,points[0].y,c);1724 if DrawLastPixel then DrawLineAntialias(points[0].x,points[0].y,points[0].x,points[0].y,c,true); 1105 1725 end 1106 1726 else … … 1124 1744 end; 1125 1745 1746 procedure TBGRACustomBitmap.DrawPolygon(const points: array of TPoint; 1747 c: TBGRAPixel; ADrawMode: TDrawMode); 1748 var i: integer; 1749 begin 1750 if length(points) = 1 then 1751 begin 1752 DrawPixel(points[0].x,points[0].y,c,ADrawMode); 1753 end 1754 else 1755 begin 1756 for i := 0 to high(points)-1 do 1757 DrawLine(points[i].x,points[i].Y,points[i+1].x,points[i+1].y,c,false,ADrawMode); 1758 DrawLine(points[high(points)].x,points[high(points)].Y,points[0].x,points[0].y,c,false,ADrawMode); 1759 end; 1760 end; 1761 1762 procedure TBGRACustomBitmap.DrawPolygonAntialias(const points: array of TPoint; 1763 c: TBGRAPixel); 1764 var i: integer; 1765 begin 1766 if length(points) = 1 then 1767 begin 1768 DrawLineAntialias(points[0].x,points[0].y,points[0].x,points[0].y,c,true); 1769 end 1770 else 1771 begin 1772 for i := 0 to high(points)-1 do 1773 DrawLineAntialias(points[i].x,points[i].Y,points[i+1].x,points[i+1].y,c,false); 1774 DrawLineAntialias(points[high(points)].x,points[high(points)].Y,points[0].x,points[0].y,c,false); 1775 end; 1776 end; 1777 1778 procedure TBGRACustomBitmap.ErasePolyLine(const points: array of TPoint; alpha: byte; 1779 DrawLastPixel: boolean); 1780 var i: integer; 1781 begin 1782 if length(points) = 1 then 1783 begin 1784 if DrawLastPixel then ErasePixel(points[0].x,points[0].y,alpha); 1785 end 1786 else 1787 for i := 0 to high(points)-1 do 1788 EraseLine(points[i].x,points[i].Y,points[i+1].x,points[i+1].y,alpha,DrawLastPixel and (i=high(points)-1)); 1789 end; 1790 1791 procedure TBGRACustomBitmap.ErasePolyLineAntialias( 1792 const points: array of TPoint; alpha: byte; DrawLastPixel: boolean); 1793 var i: integer; 1794 begin 1795 if length(points) = 1 then 1796 begin 1797 if DrawLastPixel then ErasePixel(points[0].x,points[0].y,alpha); 1798 end 1799 else 1800 for i := 0 to high(points)-1 do 1801 EraseLineAntialias(points[i].x,points[i].Y,points[i+1].x,points[i+1].y,alpha,DrawLastPixel and (i=high(points)-1)); 1802 end; 1803 1804 procedure TBGRACustomBitmap.ErasePolygonOutline(const points: array of TPoint; 1805 alpha: byte); 1806 var i: integer; 1807 begin 1808 if length(points) = 1 then 1809 begin 1810 ErasePixel(points[0].x,points[0].y,alpha); 1811 end 1812 else 1813 begin 1814 for i := 0 to high(points)-1 do 1815 EraseLine(points[i].x,points[i].Y,points[i+1].x,points[i+1].y,alpha,false); 1816 EraseLine(points[high(points)].x,points[high(points)].Y,points[0].x,points[0].y,alpha,false); 1817 end; 1818 end; 1819 1820 procedure TBGRACustomBitmap.ErasePolygonOutlineAntialias( 1821 const points: array of TPoint; alpha: byte); 1822 var i: integer; 1823 begin 1824 if length(points) = 1 then 1825 begin 1826 ErasePixel(points[0].x,points[0].y,alpha); 1827 end 1828 else 1829 begin 1830 for i := 0 to high(points)-1 do 1831 EraseLineAntialias(points[i].x,points[i].Y,points[i+1].x,points[i+1].y,alpha,false); 1832 EraseLineAntialias(points[high(points)].x,points[high(points)].Y,points[0].x,points[0].y,alpha,false); 1833 end; 1834 end; 1835 1126 1836 { Following functions are defined for convenience } 1127 1837 procedure TBGRACustomBitmap.Rectangle(x, y, x2, y2: integer; c: TColor); … … 1153 1863 end; 1154 1864 1865 procedure TBGRACustomBitmap.FillRoundRect(X1, Y1, X2, Y2: integer; DX, 1866 DY: integer; FillColor: TBGRAPixel; ADrawMode: TDrawMode); 1867 begin 1868 RoundRect(X1,Y1,X2,Y2,DX,DY,FillColor,FillColor,ADrawMode); 1869 end; 1870 1871 procedure TBGRACustomBitmap.EllipseInRect(r: TRect; BorderColor: TBGRAPixel; 1872 ADrawMode: TDrawMode); 1873 begin 1874 RoundRect(r.left,r.top,r.right,r.bottom,abs(r.right-r.left),abs(r.bottom-r.top),BorderColor,ADrawMode); 1875 end; 1876 1877 procedure TBGRACustomBitmap.EllipseInRect(r: TRect; BorderColor, 1878 FillColor: TBGRAPixel; ADrawMode: TDrawMode); 1879 begin 1880 RoundRect(r.left,r.top,r.right,r.bottom,abs(r.right-r.left),abs(r.bottom-r.top),BorderColor,FillColor,ADrawMode); 1881 end; 1882 1883 procedure TBGRACustomBitmap.FillEllipseInRect(r: TRect; FillColor: TBGRAPixel; 1884 ADrawMode: TDrawMode); 1885 begin 1886 FillRoundRect(r.left,r.top,r.right,r.bottom,abs(r.right-r.left),abs(r.bottom-r.top),FillColor,ADrawMode); 1887 end; 1888 1155 1889 procedure TBGRACustomBitmap.FillRect(r: TRect; c: TColor); 1156 1890 begin … … 1163 1897 end; 1164 1898 1899 procedure TBGRACustomBitmap.FillRect(r: TRect; texture: IBGRAScanner; 1900 mode: TDrawMode); 1901 begin 1902 FillRect(r.Left, r.top, r.right, r.bottom, texture, mode); 1903 end; 1904 1165 1905 procedure TBGRACustomBitmap.FillRect(x, y, x2, y2: integer; c: TColor); 1166 1906 begin … … 1168 1908 end; 1169 1909 1170 procedure TBGRACustomBitmap.TextOut(x, y: single; s: string; c: TBGRAPixel); 1171 begin 1172 TextOut(x, y, s, c, taLeftJustify); 1173 end; 1174 1175 procedure TBGRACustomBitmap.TextOut(x, y: single; s: string; c: TColor); 1176 begin 1177 TextOut(x, y, s, ColorToBGRA(c)); 1178 end; 1179 1180 procedure TBGRACustomBitmap.TextOut(x, y: single; s: string; 1910 { Draw the UTF8 encoded string, (x,y) being the top-left corner. The color c is used to fill the text. 1911 The value of FontOrientation is taken into account, so that the text may be rotated. } 1912 procedure TBGRACustomBitmap.TextOut(x, y: single; sUTF8: string; c: TBGRAPixel); 1913 begin 1914 TextOut(x, y, sUTF8, c, taLeftJustify); 1915 end; 1916 1917 { Draw the UTF8 encoded string, (x,y) being the top-left corner. The color c is used to fill the text. 1918 The value of FontOrientation is taken into account, so that the text may be rotated. } 1919 procedure TBGRACustomBitmap.TextOut(x, y: single; sUTF8: string; c: TColor); 1920 begin 1921 TextOut(x, y, sUTF8, ColorToBGRA(c)); 1922 end; 1923 1924 { Draw the UTF8 encoded string, (x,y) being the top-left corner. The texture is used to fill the text. 1925 The value of FontOrientation is taken into account, so that the text may be rotated. } 1926 procedure TBGRACustomBitmap.TextOut(x, y: single; sUTF8: string; 1181 1927 texture: IBGRAScanner); 1182 1928 begin 1183 TextOut(x, y, s, texture, taLeftJustify); 1184 end; 1185 1186 procedure TBGRACustomBitmap.TextRect(ARect: TRect; s: string; 1929 TextOut(x, y, sUTF8, texture, taLeftJustify); 1930 end; 1931 1932 { Draw the UTF8 encoded string in the rectangle ARect. Text is wrapped if necessary. 1933 The position depends on the specified horizontal alignment halign and vertical alignement valign. 1934 The color c is used to fill the text. No rotation is applied. } 1935 procedure TBGRACustomBitmap.TextRect(ARect: TRect; sUTF8: string; 1187 1936 halign: TAlignment; valign: TTextLayout; c: TBGRAPixel); 1188 1937 var … … 1197 1946 style.ShowPrefix := false; 1198 1947 style.Clipping := false; 1199 TextRect(ARect,ARect.Left,ARect.Top,s,style,c); 1200 end; 1201 1202 procedure TBGRACustomBitmap.TextRect(ARect: TRect; s: string; 1948 TextRect(ARect,ARect.Left,ARect.Top,sUTF8,style,c); 1949 end; 1950 1951 { Draw the UTF8 encoded string in the rectangle ARect. Text is wrapped if necessary. 1952 The position depends on the specified horizontal alignment halign and vertical alignement valign. 1953 The texture is used to fill the text. No rotation is applied. } 1954 procedure TBGRACustomBitmap.TextRect(ARect: TRect; sUTF8: string; 1203 1955 halign: TAlignment; valign: TTextLayout; texture: IBGRAScanner); 1204 1956 var … … 1213 1965 style.ShowPrefix := false; 1214 1966 style.Clipping := false; 1215 TextRect(ARect,ARect.Left,ARect.Top,s ,style,texture);1967 TextRect(ARect,ARect.Left,ARect.Top,sUTF8,style,texture); 1216 1968 end; 1217 1969 … … 1245 1997 begin 1246 1998 AlphaFill(alpha, 0, NbPixels); 1999 end; 2000 2001 procedure TBGRACustomBitmap.FillMask(x, y: integer; AMask: TBGRACustomBitmap; 2002 color: TBGRAPixel); 2003 begin 2004 FillMask(x,y, AMask, color, dmDrawWithTransparency); 2005 end; 2006 2007 procedure TBGRACustomBitmap.FillMask(x, y: integer; AMask: TBGRACustomBitmap; 2008 texture: IBGRAScanner); 2009 begin 2010 FillMask(x,y, AMask, texture, dmDrawWithTransparency); 1247 2011 end; 1248 2012 … … 1276 2040 oldClip,newClip: TRect; 1277 2041 begin 1278 if Source = nilthen exit;2042 if (Source = nil) or (AOpacity = 0) then exit; 1279 2043 w := SourceRect.Right-SourceRect.Left; 1280 2044 h := SourceRect.Bottom-SourceRect.Top; … … 1304 2068 1305 2069 ClipRect := oldClip; 2070 end; 2071 2072 procedure TBGRACustomBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF; 2073 Source: TBGRACustomBitmap; AOpacity: Byte; ACorrectBlur: Boolean); 2074 begin 2075 if ACorrectBlur then 2076 PutImageAffine(Origin,HAxis,VAxis,Source,rfCosine,AOpacity) 2077 else 2078 PutImageAffine(Origin,HAxis,VAxis,Source,rfLinear,AOpacity); 2079 end; 2080 2081 procedure TBGRACustomBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF; 2082 Source: TBGRACustomBitmap; AResampleFilter: TResampleFilter; AOpacity: Byte); 2083 var outputBounds: TRect; 2084 begin 2085 if (Source = nil) or (AOpacity = 0) then exit; 2086 if (abs(Origin.x-round(Origin.x))<1e-6) and (abs(Origin.y-round(Origin.Y))<1e-6) and 2087 (abs(HAxis.x-(Origin.x+Source.Width))<1e-6) and (abs(HAxis.y-origin.y)<1e-6) and 2088 (abs(VAxis.x-Origin.x)<1e-6) and (abs(VAxis.y-(Origin.y+Source.Height))<1e-6) then 2089 begin 2090 PutImage(round(origin.x),round(origin.y),Source,dmDrawWithTransparency,AOpacity); 2091 exit; 2092 end; 2093 outputBounds := GetImageAffineBounds(Origin,HAxis,VAxis,Source); 2094 PutImageAffine(Origin,HAxis,VAxis,Source,outputBounds,AResampleFilter,dmDrawWithTransparency,AOpacity); 2095 end; 2096 2097 procedure TBGRACustomBitmap.PutImageAffine(Origin, HAxis, VAxis: TPointF; 2098 Source: TBGRACustomBitmap; AOutputBounds: TRect; AOpacity: Byte; 2099 ACorrectBlur: Boolean); 2100 begin 2101 if ACorrectBlur then 2102 PutImageAffine(Origin,HAxis,VAxis,Source,AOutputBounds,rfCosine,dmDrawWithTransparency, AOpacity) 2103 else 2104 PutImageAffine(Origin,HAxis,VAxis,Source,AOutputBounds,rfLinear,dmDrawWithTransparency,AOpacity); 2105 end; 2106 2107 { Returns the area that contains the affine transformed image } 2108 function TBGRACustomBitmap.GetImageAffineBounds(Origin, HAxis, VAxis: TPointF; 2109 Source: TBGRACustomBitmap): TRect; 2110 var minx,miny,maxx,maxy: integer; 2111 vx,vy,pt1: TPointF; 2112 sourceBounds: TRect; 2113 2114 //include specified point in the bounds 2115 procedure Include(pt: TPointF); 2116 begin 2117 if floor(pt.X) < minx then minx := floor(pt.X); 2118 if floor(pt.Y) < miny then miny := floor(pt.Y); 2119 if ceil(pt.X) > maxx then maxx := ceil(pt.X); 2120 if ceil(pt.Y) > maxy then maxy := ceil(pt.Y); 2121 end; 2122 2123 begin 2124 result := EmptyRect; 2125 if (Source = nil) then exit; 2126 sourceBounds := source.GetImageBounds; 2127 if IsRectEmpty(sourceBounds) then exit; 2128 2129 if (abs(Origin.x-round(Origin.x))<1e-6) and (abs(Origin.y-round(Origin.Y))<1e-6) and 2130 (abs(HAxis.x-(Origin.x+Source.Width))<1e-6) and (abs(HAxis.y-origin.y)<1e-6) and 2131 (abs(VAxis.x-Origin.x)<1e-6) and (abs(VAxis.y-(Origin.y+Source.Height))<1e-6) then 2132 begin 2133 result := sourceBounds; 2134 OffsetRect(result,round(origin.x),round(origin.y)); 2135 IntersectRect(result,result,ClipRect); 2136 exit; 2137 end; 2138 2139 { Compute bounds } 2140 vx := (HAxis-Origin)*(1/source.Width); 2141 vy := (VAxis-Origin)*(1/source.Height); 2142 pt1 := Origin+vx*sourceBounds.Left+vy*sourceBounds.Top; 2143 minx := floor(pt1.X); 2144 miny := floor(pt1.Y); 2145 maxx := ceil(pt1.X); 2146 maxy := ceil(pt1.Y); 2147 Include(Origin+vx*sourceBounds.Right+vy*sourceBounds.Top); 2148 Include(Origin+vx*sourceBounds.Right+vy*sourceBounds.Bottom); 2149 Include(Origin+vx*sourceBounds.Left+vy*sourceBounds.Bottom); 2150 2151 result := rect(minx,miny,maxx+1,maxy+1); 2152 IntersectRect(result,result,ClipRect); 2153 end; 2154 2155 procedure TBGRACustomBitmap.PutImageAngle(x, y: single; 2156 Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; 2157 imageCenterX: single; imageCenterY: single; AOpacity: Byte; 2158 ARestoreOffsetAfterRotation: boolean; ACorrectBlur: Boolean); 2159 begin 2160 if ACorrectBlur then 2161 PutImageAngle(x,y,Source,angle,AOutputBounds,rfCosine,imageCenterX,imageCenterY,AOpacity,ARestoreOffsetAfterRotation) 2162 else 2163 PutImageAngle(x,y,Source,angle,AOutputBounds,rfLinear,imageCenterX,imageCenterY,AOpacity,ARestoreOffsetAfterRotation); 2164 end; 2165 2166 procedure TBGRACustomBitmap.PutImageAngle(x, y: single; 2167 Source: TBGRACustomBitmap; angle: single; imageCenterX: single; 2168 imageCenterY: single; AOpacity: Byte; ARestoreOffsetAfterRotation: boolean; ACorrectBlur: Boolean); 2169 begin 2170 if ACorrectBlur then 2171 PutImageAngle(x,y,Source,angle,rfCosine,imageCenterX,imageCenterY,AOpacity,ARestoreOffsetAfterRotation) 2172 else 2173 PutImageAngle(x,y,Source,angle,rfLinear,imageCenterX,imageCenterY,AOpacity,ARestoreOffsetAfterRotation); 2174 end; 2175 2176 procedure TBGRACustomBitmap.PutImageAngle(x, y: single; 2177 Source: TBGRACustomBitmap; angle: single; AOutputBounds: TRect; 2178 AResampleFilter: TResampleFilter; imageCenterX: single; imageCenterY: single; AOpacity: Byte; 2179 ARestoreOffsetAfterRotation: boolean); 2180 var 2181 Origin,HAxis,VAxis: TPointF; 2182 begin 2183 if (source = nil) or (AOpacity=0) then exit; 2184 ComputeImageAngleAxes(x,y,source.Width,source.Height,angle,imageCenterX,imageCenterY,ARestoreOffsetAfterRotation, 2185 Origin,HAxis,VAxis); 2186 PutImageAffine(Origin,HAxis,VAxis,source,AOutputBounds,AResampleFilter,dmDrawWithTransparency,AOpacity); 2187 end; 2188 2189 procedure TBGRACustomBitmap.PutImageAngle(x, y: single; 2190 Source: TBGRACustomBitmap; angle: single; AResampleFilter: TResampleFilter; 2191 imageCenterX: single; imageCenterY: single; AOpacity: Byte; 2192 ARestoreOffsetAfterRotation: boolean); 2193 var 2194 Origin,HAxis,VAxis: TPointF; 2195 begin 2196 if (source = nil) or (AOpacity=0) then exit; 2197 ComputeImageAngleAxes(x,y,source.Width,source.Height,angle,imageCenterX,imageCenterY,ARestoreOffsetAfterRotation, 2198 Origin,HAxis,VAxis); 2199 PutImageAffine(Origin,HAxis,VAxis,source,AResampleFilter,AOpacity); 2200 end; 2201 2202 procedure TBGRACustomBitmap.ComputeImageAngleAxes(x, y, w, h, 2203 angle: single; imageCenterX, imageCenterY: single; 2204 ARestoreOffsetAfterRotation: boolean; out Origin, HAxis, VAxis: TPointF); 2205 var 2206 cosa,sina: single; 2207 2208 { Compute rotated coordinates } 2209 function Coord(relX,relY: single): TPointF; 2210 begin 2211 relX -= imageCenterX; 2212 relY -= imageCenterY; 2213 result.x := relX*cosa-relY*sina+x; 2214 result.y := relY*cosa+relX*sina+y; 2215 if ARestoreOffsetAfterRotation then 2216 begin 2217 result.x += imageCenterX; 2218 result.y += imageCenterY; 2219 end; 2220 end; 2221 2222 begin 2223 cosa := cos(-angle*Pi/180); 2224 sina := -sin(-angle*Pi/180); 2225 Origin := Coord(0,0); 2226 HAxis := Coord(w,0); 2227 VAxis := Coord(0,h); 2228 end; 2229 2230 function TBGRACustomBitmap.GetImageAngleBounds(x, y: single; 2231 Source: TBGRACustomBitmap; angle: single; imageCenterX: single; 2232 imageCenterY: single; ARestoreOffsetAfterRotation: boolean): TRect; 2233 var 2234 cosa,sina: single; 2235 2236 { Compute rotated coordinates } 2237 function Coord(relX,relY: single): TPointF; 2238 begin 2239 relX -= imageCenterX; 2240 relY -= imageCenterY; 2241 result.x := relX*cosa-relY*sina+x; 2242 result.y := relY*cosa+relX*sina+y; 2243 if ARestoreOffsetAfterRotation then 2244 begin 2245 result.x += imageCenterX; 2246 result.y += imageCenterY; 2247 end; 2248 end; 2249 2250 begin 2251 if (source = nil) then 2252 begin 2253 result := EmptyRect; 2254 exit; 2255 end; 2256 cosa := cos(-angle*Pi/180); 2257 sina := -sin(-angle*Pi/180); 2258 result := GetImageAffineBounds(Coord(0,0),Coord(source.Width,0),Coord(0,source.Height),source); 2259 end; 2260 2261 procedure TBGRACustomBitmap.VerticalFlip; 2262 begin 2263 VerticalFlip(rect(0,0,Width,Height)); 2264 end; 2265 2266 procedure TBGRACustomBitmap.HorizontalFlip; 2267 begin 2268 HorizontalFlip(rect(0,0,Width,Height)); 2269 end; 2270 2271 procedure TBGRACustomBitmap.ApplyMask(mask: TBGRACustomBitmap); 2272 begin 2273 ApplyMask(mask, Rect(0,0,Width,Height), Point(0,0)); 2274 end; 2275 2276 procedure TBGRACustomBitmap.ApplyMask(mask: TBGRACustomBitmap; ARect: TRect); 2277 begin 2278 ApplyMask(mask, ARect, ARect.TopLeft); 1306 2279 end; 1307 2280 … … 1448 2421 {************************** Color functions **************************} 1449 2422 2423 function CheckPutImageBounds(x, y, tx, ty: integer; out minxb, minyb, maxxb, 2424 maxyb, ignoreleft: integer; const cliprect: TRect): boolean; 2425 var x2,y2: integer; 2426 begin 2427 if (x >= cliprect.Right) or (y >= cliprect.Bottom) or (x <= cliprect.Left-tx) or 2428 (y <= cliprect.Top-ty) or (ty <= 0) or (tx <= 0) then 2429 begin 2430 result := false; 2431 exit; 2432 end; 2433 2434 x2 := x + tx - 1; 2435 y2 := y + ty - 1; 2436 2437 if y < cliprect.Top then 2438 minyb := cliprect.Top 2439 else 2440 minyb := y; 2441 if y2 >= cliprect.Bottom then 2442 maxyb := cliprect.Bottom - 1 2443 else 2444 maxyb := y2; 2445 2446 if x < cliprect.Left then 2447 begin 2448 ignoreleft := cliprect.Left-x; 2449 minxb := cliprect.Left; 2450 end 2451 else 2452 begin 2453 ignoreleft := 0; 2454 minxb := x; 2455 end; 2456 if x2 >= cliprect.Right then 2457 maxxb := cliprect.Right - 1 2458 else 2459 maxxb := x2; 2460 2461 result := true; 2462 end; 2463 1450 2464 { The intensity is defined here as the maximum value of any color component } 1451 function GetIntensity(c : TExpandedPixel): word; inline;2465 function GetIntensity(const c: TExpandedPixel): word; inline; 1452 2466 begin 1453 2467 Result := c.red; … … 1458 2472 end; 1459 2473 1460 function SetIntensity(c: TExpandedPixel; intensity: word): TExpandedPixel; 2474 function GetIntensity(c: TBGRAPixel): word; 2475 begin 2476 Result := c.red; 2477 if c.green > Result then 2478 Result := c.green; 2479 if c.blue > Result then 2480 Result := c.blue; 2481 result := GammaExpansionTab[Result]; 2482 end; 2483 2484 function SetIntensity(const c: TExpandedPixel; intensity: word): TExpandedPixel; 1461 2485 var 1462 2486 curIntensity: word; … … 1464 2488 curIntensity := GetIntensity(c); 1465 2489 if curIntensity = 0 then //suppose it's gray if there is no color information 1466 Result := c 2490 begin 2491 Result.red := intensity; 2492 Result.green := intensity; 2493 Result.blue := intensity; 2494 result.alpha := c.alpha; 2495 end 1467 2496 else 1468 2497 begin … … 1475 2504 end; 1476 2505 2506 function SetIntensity(c: TBGRAPixel; intensity: word): TBGRAPixel; 2507 begin 2508 result := GammaCompression(SetIntensity(GammaExpansion(c),intensity)); 2509 end; 2510 2511 function GetLightness(c: TBGRAPixel): word; 2512 begin 2513 result := GetLightness(GammaExpansion(c)); 2514 end; 2515 1477 2516 { The lightness here is defined as the subjective sensation of luminosity, where 1478 2517 blue is the darkest component and green the lightest } 1479 function GetLightness(c : TExpandedPixel): word; inline;2518 function GetLightness(const c: TExpandedPixel): word; inline; 1480 2519 begin 1481 2520 Result := (c.red * redWeightShl10 + c.green * greenWeightShl10 + … … 1483 2522 end; 1484 2523 1485 function SetLightness(c : TExpandedPixel; lightness: word): TExpandedPixel;2524 function SetLightness(const c: TExpandedPixel; lightness: word): TExpandedPixel; 1486 2525 var 1487 2526 curLightness: word; 1488 AddedWhiteness, maxBeforeWhite: word;1489 clip: boolean;1490 2527 begin 1491 2528 curLightness := GetLightness(c); … … 1495 2532 exit; 1496 2533 end; 2534 result := SetLightness(c, lightness, curLightness); 2535 end; 2536 2537 function SetLightness(c: TBGRAPixel; lightness: word): TBGRAPixel; 2538 begin 2539 result := GammaCompression(SetLightness(GammaExpansion(c),lightness)); 2540 end; 2541 2542 function SetLightness(const c: TExpandedPixel; lightness: word; curLightness: word): TExpandedPixel; 2543 var 2544 AddedWhiteness, maxBeforeWhite: word; 2545 clip: boolean; 2546 begin 2547 if lightness = curLightness then 2548 begin //no change 2549 Result := c; 2550 exit; 2551 end; 1497 2552 if lightness = 65535 then //set to white 1498 2553 begin … … 1521 2576 if lightness < curLightness then //darker is easy 1522 2577 begin 1523 Result := SetIntensity(c, (GetIntensity(c) * lightness + (curLightness shr 1)) div 1524 curLightness); 2578 result.alpha:= c.alpha; 2579 result.red := (c.red * lightness + (curLightness shr 1)) div curLightness; 2580 result.green := (c.green * lightness + (curLightness shr 1)) div curLightness; 2581 result.blue := (c.blue * lightness + (curLightness shr 1)) div curLightness; 1525 2582 exit; 1526 2583 end; … … 1597 2654 end; 1598 2655 1599 function CombineLightness(lightness1,lightness2: integer): integer;2656 function CombineLightness(lightness1,lightness2: Int32or64): Int32or64; 1600 2657 {$ifdef CPUI386} {$asmmode intel} assembler; 1601 2658 asm … … 1663 2720 end; 1664 2721 1665 function ExpandedToHSLA(ec: TExpandedPixel): THSLAPixel;2722 procedure ExpandedToHSLAInline(r,g,b: Int32Or64; var dest: THSLAPixel); inline; 1666 2723 const 1667 deg60 = 8192; 1668 deg120 = deg60 * 2; 1669 deg240 = deg60 * 4; 1670 deg360 = deg60 * 6; 2724 deg60 = 10922; 2725 deg120 = 21845; 2726 deg240 = 43690; 1671 2727 var 1672 min, max, minMax: integer; 1673 twiceLightness: integer; 1674 r,g,b: integer; 1675 begin 1676 r := ec.red; 1677 g := ec.green; 1678 b := ec.blue; 1679 min := r; 1680 max := r; 1681 if g > max then 1682 max := g 1683 else 1684 if g < min then 2728 min, max, minMax: Int32or64; 2729 UMinMax,UTwiceLightness: UInt32or64; 2730 begin 2731 if g > r then 2732 begin 2733 max := g; 2734 min := r; 2735 end 2736 else 2737 begin 2738 max := r; 1685 2739 min := g; 2740 end; 1686 2741 if b > max then 1687 2742 max := b … … 1692 2747 1693 2748 if minMax = 0 then 1694 Result.hue := 02749 dest.hue := 0 1695 2750 else 1696 2751 if max = r then 1697 Result.hue := (((g - b) * deg60) div 1698 minMax + deg360) mod deg360 2752 {$PUSH}{$RANGECHECKS OFF} 2753 dest.hue := ((g - b) * deg60) div minMax 2754 {$POP} 1699 2755 else 1700 2756 if max = g then 1701 Result.hue := ((b - r) * deg60) div minMax + deg120 1702 else 1703 {max = b} Result.hue := 1704 ((r - g) * deg60) div minMax + deg240; 1705 twiceLightness := max + min; 2757 dest.hue := ((b - r) * deg60) div minMax + deg120 2758 else 2759 {max = b} dest.hue := ((r - g) * deg60) div minMax + deg240; 2760 UTwiceLightness := max + min; 1706 2761 if min = max then 1707 Result.saturation := 0 1708 else 1709 {$hints off} 1710 if twiceLightness < 65536 then 1711 Result.saturation := (int64(minMax) shl 16) div (twiceLightness + 1) 1712 else 1713 Result.saturation := (int64(minMax) shl 16) div (131072 - twiceLightness); 1714 {$hints on} 1715 Result.lightness := twiceLightness shr 1; 1716 Result.alpha := ec.alpha; 1717 Result.hue := (Result.hue shl 16) div deg360; 2762 dest.saturation := 0 2763 else 2764 begin 2765 UMinMax:= minMax; 2766 if UTwiceLightness < 65536 then 2767 dest.saturation := (UMinMax shl 16) div (UTwiceLightness + 1) 2768 else 2769 dest.saturation := (UMinMax shl 16) div (131072 - UTwiceLightness); 2770 end; 2771 dest.lightness := UTwiceLightness shr 1; 2772 end; 2773 2774 function ExpandedToHSLA(const ec: TExpandedPixel): THSLAPixel; 2775 begin 2776 result.alpha := ec.alpha; 2777 ExpandedToHSLAInline(ec.red,ec.green,ec.blue,result); 1718 2778 end; 1719 2779 1720 2780 function HtoG(hue: word): word; 1721 2781 const 1722 segmentDest: array[0..5] of word=2782 segmentDest: array[0..5] of NativeUInt = 1723 2783 (13653, 10923, 8192, 13653, 10923, 8192); 1724 segmentSrc: array[0..5] of word=2784 segmentSrc: array[0..5] of NativeUInt = 1725 2785 (10923, 10922, 10923, 10923, 10922, 10923); 1726 begin 1727 if hue < segmentSrc[0] then 1728 result := hue * segmentDest[0] div segmentSrc[0] 1729 else 1730 begin 1731 result := segmentDest[0]; 1732 hue -= segmentSrc[0]; 1733 if hue < segmentSrc[1] then 1734 result += hue * segmentDest[1] div segmentSrc[1] 2786 var 2787 h,g: NativeUInt; 2788 begin 2789 h := hue; 2790 if h < segmentSrc[0] then 2791 g := h * segmentDest[0] div segmentSrc[0] 2792 else 2793 begin 2794 g := segmentDest[0]; 2795 h -= segmentSrc[0]; 2796 if h < segmentSrc[1] then 2797 g += h * segmentDest[1] div segmentSrc[1] 1735 2798 else 1736 2799 begin 1737 result+= segmentDest[1];1738 h ue-= segmentSrc[1];1739 if h ue< segmentSrc[2] then1740 result += hue* segmentDest[2] div segmentSrc[2]2800 g += segmentDest[1]; 2801 h -= segmentSrc[1]; 2802 if h < segmentSrc[2] then 2803 g += h * segmentDest[2] div segmentSrc[2] 1741 2804 else 1742 2805 begin 1743 result+= segmentDest[2];1744 h ue-= segmentSrc[2];1745 if h ue< segmentSrc[3] then1746 result += hue* segmentDest[3] div segmentSrc[3]2806 g += segmentDest[2]; 2807 h -= segmentSrc[2]; 2808 if h < segmentSrc[3] then 2809 g += h * segmentDest[3] div segmentSrc[3] 1747 2810 else 1748 2811 begin 1749 result+= segmentDest[3];1750 h ue-= segmentSrc[3];1751 if h ue< segmentSrc[4] then1752 result += hue* segmentDest[4] div segmentSrc[4]2812 g += segmentDest[3]; 2813 h -= segmentSrc[3]; 2814 if h < segmentSrc[4] then 2815 g += h * segmentDest[4] div segmentSrc[4] 1753 2816 else 1754 2817 begin 1755 result+= segmentDest[4];1756 h ue-= segmentSrc[4];1757 result += hue* segmentDest[5] div segmentSrc[5];2818 g += segmentDest[4]; 2819 h -= segmentSrc[4]; 2820 g += h * segmentDest[5] div segmentSrc[5]; 1758 2821 end; 1759 2822 end; … … 1761 2824 end; 1762 2825 end; 2826 result := g; 1763 2827 end; 1764 2828 1765 2829 function GtoH(ghue: word): word; 1766 2830 const 1767 segment: array[0..5] of word=2831 segment: array[0..5] of NativeUInt = 1768 2832 (13653, 10923, 8192, 13653, 10923, 8192); 1769 begin 1770 if ghue < segment[0] then 1771 result := ghue * 10923 div segment[0] 1772 else 1773 begin 1774 ghue -= segment[0]; 1775 if ghue < segment[1] then 1776 result := ghue * (21845-10923) div segment[1] + 10923 2833 var g: NativeUint; 2834 begin 2835 g := ghue; 2836 if g < segment[0] then 2837 result := g * 10923 div segment[0] 2838 else 2839 begin 2840 g -= segment[0]; 2841 if g < segment[1] then 2842 result := g * (21845-10923) div segment[1] + 10923 1777 2843 else 1778 2844 begin 1779 g hue-= segment[1];1780 if g hue< segment[2] then1781 result := g hue* (32768-21845) div segment[2] + 218452845 g -= segment[1]; 2846 if g < segment[2] then 2847 result := g * (32768-21845) div segment[2] + 21845 1782 2848 else 1783 2849 begin 1784 g hue-= segment[2];1785 if g hue< segment[3] then1786 result := g hue* (43691-32768) div segment[3] + 327682850 g -= segment[2]; 2851 if g < segment[3] then 2852 result := g * (43691-32768) div segment[3] + 32768 1787 2853 else 1788 2854 begin 1789 g hue-= segment[3];1790 if g hue< segment[4] then1791 result := g hue* (54613-43691) div segment[4] + 436912855 g -= segment[3]; 2856 if g < segment[4] then 2857 result := g * (54613-43691) div segment[4] + 43691 1792 2858 else 1793 2859 begin 1794 g hue-= segment[4];1795 result := g hue* (65536-54613) div segment[5] + 54613;2860 g -= segment[4]; 2861 result := g * (65536-54613) div segment[5] + 54613; 1796 2862 end; 1797 2863 end; … … 1801 2867 end; 1802 2868 1803 function BGRAToGSBA(c: TBGRAPixel): THSLAPixel; 1804 var ec: TExpandedPixel; 1805 lightness: word; 1806 begin 1807 ec := GammaExpansion(c); 1808 lightness := GetLightness(ec); 1809 1810 result := ExpandedToHSLA(ec); 2869 function BGRAToGSBA(c: TBGRAPixel): TGSBAPixel; 2870 var lightness: UInt32Or64; 2871 red,green,blue: Int32or64; 2872 begin 2873 red := GammaExpansionTab[c.red]; 2874 green := GammaExpansionTab[c.green]; 2875 blue := GammaExpansionTab[c.blue]; 2876 result.alpha := c.alpha shl 8 + c.alpha; 2877 2878 lightness := (red * redWeightShl10 + green * greenWeightShl10 + 2879 blue * blueWeightShl10 + 512) shr 10; 2880 2881 ExpandedToHSLAInline(red,green,blue,result); 1811 2882 if result.lightness > 32768 then 1812 result.saturation := result.saturation* word(65535-result.lightness) div 32767;2883 result.saturation := result.saturation* UInt32or64(not result.lightness) div 32767; 1813 2884 result.lightness := lightness; 1814 2885 result.hue := HtoG(result.hue); 1815 2886 end; 1816 2887 1817 function HSLAToExpanded(c: THSLAPixel): TExpandedPixel; 2888 function ExpandedToGSBA(ec: TExpandedPixel): TGSBAPixel; 2889 var lightness: UInt32Or64; 2890 red,green,blue: Int32or64; 2891 begin 2892 red := ec.red; 2893 green := ec.green; 2894 blue := ec.blue; 2895 result.alpha := ec.alpha; 2896 2897 lightness := (red * redWeightShl10 + green * greenWeightShl10 + 2898 blue * blueWeightShl10 + 512) shr 10; 2899 2900 ExpandedToHSLAInline(red,green,blue,result); 2901 if result.lightness > 32768 then 2902 result.saturation := result.saturation* UInt32or64(not result.lightness) div 32767; 2903 result.lightness := lightness; 2904 result.hue := HtoG(result.hue); 2905 end; 2906 2907 function HSLAToExpanded(const c: THSLAPixel): TExpandedPixel; 1818 2908 const 1819 2909 deg30 = 4096; … … 1824 2914 deg360 = deg60 * 6; 1825 2915 1826 function ComputeColor(p, q: integer; h: integer): word; inline; 1827 begin 1828 if h > deg360 then 1829 Dec(h, deg360); 1830 if h < deg60 then 1831 Result := p + ((q - p) * h + deg30) div deg60 1832 else 2916 function ComputeColor(p, q: Int32or64; h: Int32or64): Int32or64; inline; 2917 begin 1833 2918 if h < deg180 then 1834 Result := q 1835 else 1836 if h < deg240 then 1837 Result := p + ((q - p) * (deg240 - h) + deg30) div deg60 1838 else 1839 Result := p; 2919 begin 2920 if h < deg60 then 2921 Result := p + ((q - p) * h + deg30) div deg60 2922 else 2923 Result := q 2924 end else 2925 begin 2926 if h < deg240 then 2927 Result := p + ((q - p) * (deg240 - h) + deg30) div deg60 2928 else 2929 Result := p; 2930 end; 1840 2931 end; 1841 2932 1842 2933 var 1843 q, p: integer; 1844 begin 1845 c.hue := c.hue * deg360 shr 16; 1846 if c.saturation = 0 then //gray 1847 begin 1848 result.red := c.lightness; 1849 result.green := c.lightness; 1850 result.blue := c.lightness; 2934 q, p, L, S, H: Int32or64; 2935 begin 2936 L := c.lightness; 2937 S := c.saturation; 2938 if S = 0 then //gray 2939 begin 2940 result.red := L; 2941 result.green := L; 2942 result.blue := L; 1851 2943 result.alpha := c.alpha; 1852 2944 exit; 1853 2945 end; 1854 2946 {$hints off} 1855 if c.lightness< 32768 then1856 q := ( c.lightness shr 1) * ((65535 + c.saturation) shr 1) shr 141857 else 1858 q := c.lightness + c.saturation - ((c.lightnessshr 1) *1859 ( c.saturationshr 1) shr 14);2947 if L < 32768 then 2948 q := (L shr 1) * ((65535 + S) shr 1) shr 14 2949 else 2950 q := L + S - ((L shr 1) * 2951 (S shr 1) shr 14); 1860 2952 {$hints on} 1861 if q > 65535 then 1862 q := 65535; 1863 p := c.lightness * 2 - q; 1864 if p > 65535 then 1865 p := 65535; 1866 result.red := ComputeColor(p, q, c.hue + deg120); 1867 result.green := ComputeColor(p, q, c.hue); 1868 result.blue := ComputeColor(p, q, c.hue + deg240); 2953 if q > 65535 then q := 65535; 2954 p := (L shl 1) - q; 2955 if p > 65535 then p := 65535; 2956 H := c.hue * deg360 shr 16; 2957 result.green := ComputeColor(p, q, H); 2958 inc(H, deg120); 2959 if H > deg360 then Dec(H, deg360); 2960 result.red := ComputeColor(p, q, H); 2961 inc(H, deg120); 2962 if H > deg360 then Dec(H, deg360); 2963 result.blue := ComputeColor(p, q, H); 1869 2964 result.alpha := c.alpha; 1870 2965 end; 1871 2966 1872 2967 { Conversion from HSL colorspace to RGB. See : http://en.wikipedia.org/wiki/HSL_color_space } 1873 function HSLAToBGRA(c : THSLAPixel): TBGRAPixel;2968 function HSLAToBGRA(const c: THSLAPixel): TBGRAPixel; 1874 2969 var ec: TExpandedPixel; 1875 2970 begin … … 1945 3040 end; 1946 3041 1947 function GSBAToBGRA(c: T HSLAPixel): TBGRAPixel;3042 function GSBAToBGRA(c: TGSBAPixel): TBGRAPixel; 1948 3043 var ec: TExpandedPixel; 1949 3044 lightness: word; … … 1956 3051 end; 1957 3052 1958 function GSBAToHSLA(c: THSLAPixel): THSLAPixel; 3053 function GSBAToExpanded(c: TGSBAPixel): TExpandedPixel; 3054 var lightness: word; 3055 begin 3056 c.hue := GtoH(c.hue); 3057 lightness := c.lightness; 3058 c.lightness := 32768; 3059 result := SetLightness(HSLAToExpanded(c),lightness); 3060 end; 3061 3062 function GSBAToHSLA(c: TGSBAPixel): THSLAPixel; 1959 3063 begin 1960 3064 result := BGRAToHSLA(GSBAToBGRA(c)); … … 1970 3074 end; 1971 3075 1972 function GammaCompression( ec: TExpandedPixel): TBGRAPixel;3076 function GammaCompression(const ec: TExpandedPixel): TBGRAPixel; 1973 3077 begin 1974 3078 Result.red := GammaCompressionTab[ec.red]; … … 1994 3098 cgray: byte; 1995 3099 begin 3100 if c.alpha = 0 then 3101 begin 3102 result := BGRAPixelTransparent; 3103 exit; 3104 end; 1996 3105 //gamma expansion 1997 3106 ec := GammaExpansion(c); … … 2017 3126 function MergeBGRA(const colors: array of TBGRAPixel): TBGRAPixel; 2018 3127 var 2019 sumR,sumG,sumB,sumA: longword;3128 sumR,sumG,sumB,sumA: NativeUInt; 2020 3129 i: integer; 2021 3130 begin … … 2107 3216 weight2: byte): TBGRAPixel; 2108 3217 var 2109 f1,f2: word; 2110 f12: longword; 2111 begin 2112 if (weight1 = 0) then 2113 begin 2114 if (weight2 = 0) then 3218 w1,w2,f1,f2,f12,a: UInt32or64; 3219 begin 3220 w1 := weight1; 3221 w2 := weight2; 3222 if (w1 = 0) then 3223 begin 3224 if (w2 = 0) then 2115 3225 result := BGRAPixelTransparent 2116 3226 else … … 2118 3228 end 2119 3229 else 2120 if (w eight2 = 0) then3230 if (w2 = 0) then 2121 3231 Result := c1 2122 3232 else 2123 3233 begin 2124 f1 := c1.alpha*weight1 shr 1; 2125 f2 := c2.alpha*weight2 shr 1; 3234 f1 := c1.alpha*w1; 3235 f2 := c2.alpha*w2; 3236 a := (f1+f2 + ((w1+w2) shr 1)) div (w1+w2); 3237 if a = 0 then 3238 begin 3239 result := BGRAPixelTransparent; 3240 exit; 3241 end else 3242 Result.alpha := a; 3243 {$IFNDEF CPU64} 3244 if (f1 >= 32768) or (f2 >= 32768) then 3245 begin 3246 f1 := f1 shr 1; 3247 f2 := f2 shr 1; 3248 end; 3249 {$ENDIF} 2126 3250 f12 := f1+f2; 2127 if f12 = 0 then 2128 result := BGRAPixelTransparent 2129 else 2130 begin 2131 Result.red := GammaCompressionTab[(GammaExpansionTab[c1.red] * f1 + GammaExpansionTab[c2.red] * f2) div f12]; 2132 Result.green := GammaCompressionTab[(GammaExpansionTab[c1.green] * f1 + GammaExpansionTab[c2.green] * f2) div f12]; 2133 Result.blue := GammaCompressionTab[(GammaExpansionTab[c1.blue] * f1 + GammaExpansionTab[c2.blue] * f2) div f12]; 2134 Result.alpha := (c1.alpha*weight1+c2.alpha*weight2 + ((weight1+weight2) shr 1)) div (weight1+weight2); 2135 end; 3251 Result.red := GammaCompressionTab[(GammaExpansionTab[c1.red] * f1 + GammaExpansionTab[c2.red] * f2) div f12]; 3252 Result.green := GammaCompressionTab[(GammaExpansionTab[c1.green] * f1 + GammaExpansionTab[c2.green] * f2) div f12]; 3253 Result.blue := GammaCompressionTab[(GammaExpansionTab[c1.blue] * f1 + GammaExpansionTab[c2.blue] * f2) div f12]; 2136 3254 end; 2137 3255 end; … … 2329 3447 end; 2330 3448 2331 { Write a color in hexadecimal format RRGGBBAA } 2332 function BGRAToStr(c: TBGRAPixel): string; 2333 begin 3449 { Write a color in hexadecimal format RRGGBBAA or using the name in a color list } 3450 function BGRAToStr(c: TBGRAPixel; AColorList: TBGRAColorList = nil; AMaxDiff: Word= 0): string; 3451 var idx: integer; 3452 begin 3453 if Assigned(AColorList) then 3454 begin 3455 idx := AColorList.IndexOfColor(c, AMaxDiff); 3456 if idx<> -1 then 3457 begin 3458 result := AColorList.Name[idx]; 3459 exit; 3460 end; 3461 end; 2334 3462 result := IntToHex(c.red,2)+IntToHex(c.green,2)+IntToHex(c.Blue,2)+IntToHex(c.Alpha,2); 2335 3463 end; … … 2338 3466 arrayOfString = array of string; 2339 3467 2340 function SimpleParseFuncParam(str: string ): arrayOfString;3468 function SimpleParseFuncParam(str: string; var flagError: boolean): arrayOfString; 2341 3469 var idxOpen,start,cur: integer; 2342 3470 begin 2343 3471 result := nil; 2344 3472 idxOpen := pos('(',str); 2345 if idxOpen = 0 then exit; 2346 start := idxOpen+1; 3473 if idxOpen = 0 then 3474 begin 3475 start := 1; 3476 //find first space 3477 while (start <= length(str)) and (str[start]<>' ') do inc(start); 3478 end else 3479 start := idxOpen+1; 2347 3480 cur := start; 2348 3481 while cur <= length(str) do … … 2351 3484 begin 2352 3485 setlength(result,length(result)+1); 2353 result[high(result)] := copy(str,start,cur-start);3486 result[high(result)] := trim(copy(str,start,cur-start)); 2354 3487 start := cur+1; 3488 if str[cur] = ')' then exit; 2355 3489 end; 2356 3490 inc(cur); 2357 3491 end; 3492 if idxOpen <> 0 then flagError := true; //should exit on ')' 2358 3493 if start <= length(str) then 2359 3494 begin … … 2363 3498 end; 2364 3499 2365 function ParseColorValue(str: string ): byte;3500 function ParseColorValue(str: string; var flagError: boolean): byte; 2366 3501 var pourcent,unclipped,{%H-}errPos: integer; 2367 3502 begin … … 2371 3506 begin 2372 3507 val(copy(str,1,length(str)-1),pourcent,errPos); 3508 if errPos <> 0 then flagError := true; 2373 3509 if pourcent < 0 then result := 0 else 2374 3510 if pourcent > 100 then result := 255 else … … 2377 3513 begin 2378 3514 val(str,unclipped,errPos); 3515 if errPos <> 0 then flagError := true; 2379 3516 if unclipped < 0 then result := 0 else 2380 3517 if unclipped > 255 then result := 255 else … … 2384 3521 end; 2385 3522 3523 //this function returns the parsed value only if it contains no error nor missing values, otherwise 3524 //it returns BGRAPixelTransparent 2386 3525 function StrToBGRA(str: string): TBGRAPixel; 2387 begin 2388 result := StrToBGRA(str, BGRAPixelTransparent); 2389 end; 2390 2391 { Read a color in hexadecimal format RRGGBB(AA) or RGB(A) } 2392 function StrToBGRA(str: string; DefaultColor: TBGRAPixel): TBGRAPixel; 3526 var missingValues, error: boolean; 3527 begin 3528 result := BGRABlack; 3529 TryStrToBGRA(str, result, missingValues, error); 3530 if missingValues or error then result := BGRAPixelTransparent; 3531 end; 3532 3533 //this function changes the content of parsedValue depending on available and parsable information. 3534 //set parsedValue to the fallback values before calling this function. 3535 //missing values are expressed by empty string or by '?', for example 'rgb(255,?,?,?)' will change only the red value. 3536 //note that if alpha is not expressed by the string format, it will be opaque. So 'rgb(255,?,?)' will change the red value and the alpha value. 3537 //the last parameter of rgba() is a floating point number where 1 is opaque and 0 is transparent. 3538 procedure TryStrToBGRA(str: string; var parsedValue: TBGRAPixel; out missingValues: boolean; out error: boolean); 2393 3539 var errPos: integer; 2394 3540 values: array of string; … … 2396 3542 idx: integer; 2397 3543 begin 2398 if str = '' then 2399 begin 2400 result := DefaultColor; 3544 str := Trim(str); 3545 error := false; 3546 if (str = '') or (str = '?') then 3547 begin 3548 missingValues := true; 2401 3549 exit; 2402 end; 2403 str := lowerCase(str); 3550 end else 3551 missingValues := false; 3552 str := StringReplace(lowerCase(str),'grey','gray',[]); 2404 3553 2405 3554 //VGA color names 2406 if str='black' then result := BGRA(0,0,0) else 2407 if str='silver' then result := BGRA(192,192,192) else 2408 if str='gray' then result := BGRA(128,128,128) else 2409 if str='grey' then result := BGRA(128,128,128) else 2410 if str='white' then result := BGRA(255,255,255) else 2411 if str='maroon' then result := BGRA(128,0,0) else 2412 if str='red' then result := BGRA(255,0,0) else 2413 if str='purple' then result := BGRA(128,0,128) else 2414 if str='fuchsia' then result := BGRA(255,0,255) else 2415 if str='green' then result := BGRA(0,128,0) else 2416 if str='lime' then result := BGRA(0,255,0) else 2417 if str='olive' then result := BGRA(128,128,0) else 2418 if str='yellow' then result := BGRA(255,255,0) else 2419 if str='navy' then result := BGRA(0,0,128) else 2420 if str='blue' then result := BGRA(0,0,255) else 2421 if str='teal' then result := BGRA(0,128,128) else 2422 if str='aqua' then result := BGRA(0,255,255) else 2423 if str='transparent' then result := DefaultColor else 3555 idx := VGAColors.IndexOf(str); 3556 if idx <> -1 then 3557 begin 3558 parsedValue := VGAColors[idx]; 3559 exit; 3560 end; 3561 if str='transparent' then parsedValue := BGRAPixelTransparent else 2424 3562 begin 2425 3563 //check CSS color … … 2427 3565 if idx <> -1 then 2428 3566 begin 2429 result:= CSSColors[idx];3567 parsedValue := CSSColors[idx]; 2430 3568 exit; 2431 3569 end; 2432 3570 2433 3571 //CSS RGB notation 2434 if (copy(str,1,4)='rgb(') or (copy(str,1,5)='rgba(') then 3572 if (copy(str,1,4)='rgb(') or (copy(str,1,5)='rgba(') or 3573 (copy(str,1,4)='rgb ') or (copy(str,1,5)='rgba ') then 2435 3574 begin 2436 values := SimpleParseFuncParam(str );3575 values := SimpleParseFuncParam(str,error); 2437 3576 if (length(values)=3) or (length(values)=4) then 2438 3577 begin 2439 result.red := ParseColorValue(values[0]); 2440 result.green := ParseColorValue(values[1]); 2441 result.blue := ParseColorValue(values[2]); 3578 if (values[0] <> '') and (values[0] <> '?') then 3579 parsedValue.red := ParseColorValue(values[0], error) 3580 else 3581 missingValues := true; 3582 if (values[1] <> '') and (values[1] <> '?') then 3583 parsedValue.green := ParseColorValue(values[1], error) 3584 else 3585 missingValues := true; 3586 if (values[2] <> '') and (values[2] <> '?') then 3587 parsedValue.blue := ParseColorValue(values[2], error) 3588 else 3589 missingValues := true; 2442 3590 if length(values)=4 then 2443 3591 begin 2444 val(values[3],alphaF,errPos); 2445 if alphaF < 0 then 2446 result.alpha := 0 else 2447 if alphaF > 1 then 2448 result.alpha := 255 2449 else 2450 result.alpha := round(alphaF*255); 3592 if (values[3] <> '') and (values[3] <> '?') then 3593 begin 3594 val(values[3],alphaF,errPos); 3595 if errPos <> 0 then 3596 begin 3597 parsedValue.alpha := 255; 3598 error := true; 3599 end 3600 else 3601 begin 3602 if alphaF < 0 then 3603 parsedValue.alpha := 0 else 3604 if alphaF > 1 then 3605 parsedValue.alpha := 255 3606 else 3607 parsedValue.alpha := round(alphaF*255); 3608 end; 3609 end else 3610 missingValues := true; 2451 3611 end else 2452 result.alpha := 255;3612 parsedValue.alpha := 255; 2453 3613 end else 2454 result := DefaultColor;3614 error := true; 2455 3615 exit; 2456 3616 end; … … 2459 3619 if str[1]='#' then delete(str,1,1); 2460 3620 2461 //add alpha if missing 3621 //add alpha if missing (if you want an undefined alpha use '??' or '?') 2462 3622 if length(str)=6 then str += 'FF'; 2463 3623 if length(str)=3 then str += 'F'; … … 2466 3626 if length(str)=8 then 2467 3627 begin 2468 val('$'+copy(str,1,2),result.red,errPos); 2469 if errPos <> 0 then 3628 if copy(str,1,2) <> '??' then 2470 3629 begin 2471 result := DefaultColor; 2472 exit; 2473 end; 2474 val('$'+copy(str,3,2),result.green,errPos); 2475 if errPos <> 0 then 3630 val('$'+copy(str,1,2),parsedValue.red,errPos); 3631 if errPos <> 0 then error := true; 3632 end else missingValues := true; 3633 if copy(str,3,2) <> '??' then 2476 3634 begin 2477 result := DefaultColor; 2478 exit; 2479 end; 2480 val('$'+copy(str,5,2),result.blue,errPos); 2481 if errPos <> 0 then 3635 val('$'+copy(str,3,2),parsedValue.green,errPos); 3636 if errPos <> 0 then error := true; 3637 end else missingValues := true; 3638 if copy(str,5,2) <> '??' then 2482 3639 begin 2483 result := DefaultColor; 2484 exit; 2485 end; 2486 val('$'+copy(str,7,2),result.alpha,errPos); 2487 if errPos <> 0 then 3640 val('$'+copy(str,5,2),parsedValue.blue,errPos); 3641 if errPos <> 0 then error := true; 3642 end else missingValues := true; 3643 if copy(str,7,2) <> '??' then 2488 3644 begin 2489 result := DefaultColor; 2490 exit; 2491 end; 3645 val('$'+copy(str,7,2),parsedValue.alpha,errPos); 3646 if errPos <> 0 then 3647 begin 3648 error := true; 3649 parsedValue.alpha := 255; 3650 end; 3651 end else missingValues := true; 2492 3652 end else 2493 3653 if length(str)=4 then 2494 3654 begin 2495 val('$'+copy(str,1,1),result.red,errPos); 2496 if errPos <> 0 then 3655 if str[1] <> '?' then 2497 3656 begin 2498 result := DefaultColor;2499 exit;2500 end;2501 val('$'+copy(str,2,1),result.green,errPos);2502 if errPos <> 0then3657 val('$'+str[1],parsedValue.red,errPos); 3658 if errPos <> 0 then error := true; 3659 parsedValue.red *= $11; 3660 end else missingValues := true; 3661 if str[2] <> '?' then 2503 3662 begin 2504 result := DefaultColor;2505 exit;2506 end;2507 val('$'+copy(str,3,1),result.blue,errPos);2508 if errPos <> 0then3663 val('$'+str[2],parsedValue.green,errPos); 3664 if errPos <> 0 then error := true; 3665 parsedValue.green *= $11; 3666 end else missingValues := true; 3667 if str[3] <> '?' then 2509 3668 begin 2510 result := DefaultColor;2511 exit;2512 end;2513 val('$'+copy(str,4,1),result.alpha,errPos);2514 if errPos <> 0then3669 val('$'+str[3],parsedValue.blue,errPos); 3670 if errPos <> 0 then error := true; 3671 parsedValue.blue *= $11; 3672 end else missingValues := true; 3673 if str[4] <> '?' then 2515 3674 begin 2516 result := DefaultColor; 2517 exit; 2518 end; 2519 result.red *= $11; 2520 result.green *= $11; 2521 result.blue *= $11; 2522 result.alpha *= $11; 3675 val('$'+str[4],parsedValue.alpha,errPos); 3676 if errPos <> 0 then 3677 begin 3678 error := true; 3679 parsedValue.alpha := 255; 3680 end else 3681 parsedValue.alpha *= $11; 3682 end else missingValues := true; 2523 3683 end else 2524 result := DefaultColor; 2525 end; 2526 3684 error := true; //string format not recognised 3685 end; 3686 3687 end; 3688 3689 //this function returns the values that can be read from the string, otherwise 3690 //it fills the gaps with the fallback values. The error boolean is True only 3691 //if there was invalid values, it is not set to True if there was missing values. 3692 function PartialStrToBGRA(str: string; const fallbackValues: TBGRAPixel; out 3693 error: boolean): TBGRAPixel; 3694 var missingValues: boolean; 3695 begin 3696 result := fallbackValues; 3697 TryStrToBGRA(str, result, missingValues, error); 3698 end; 3699 3700 { Read a color, for example in hexadecimal format RRGGBB(AA) or RGB(A). Partial colors are not accepted by this function. } 3701 function StrToBGRA(str: string; const DefaultColor: TBGRAPixel): TBGRAPixel; 3702 var missingValues, error: boolean; 3703 begin 3704 result := BGRABlack; 3705 TryStrToBGRA(str, result, missingValues, error); 3706 if missingValues or error then result := DefaultColor; 2527 3707 end; 2528 3708 … … 2531 3711 begin 2532 3712 intval := color.Green shl 16 + color.red shl 8 + color.blue; 2533 result := intval /16777215;3713 result := intval*5.960464832810452e-8; 2534 3714 end; 2535 3715 … … 2601 3781 end; 2602 3782 2603 function PtInRect( pt: TPoint; r: TRect): boolean;3783 function PtInRect(const pt: TPoint; r: TRect): boolean; 2604 3784 var 2605 3785 temp: integer; … … 2621 3801 end; 2622 3802 3803 function RectWithSize(left, top, width, height: integer): TRect; 3804 begin 3805 result.left := left; 3806 result.top := top; 3807 result.right := left+width; 3808 result.bottom := top+height; 3809 end; 3810 2623 3811 function VectLen(dx, dy: single): single; 2624 3812 begin … … 2630 3818 result := sqrt(v.x*v.x+v.y*v.y); 2631 3819 end; 2632 3820 {$OPTIMIZATION OFF} // Modif J.P 5/2013 2633 3821 function IntersectLine(line1, line2: TLineDef): TPointF; 2634 3822 var parallel: boolean; … … 2636 3824 result := IntersectLine(line1,line2,parallel); 2637 3825 end; 3826 {$OPTIMIZATION ON} 2638 3827 2639 3828 function IntersectLine(line1, line2: TLineDef; out parallel: boolean): TPointF; … … 2787 3976 2788 3977 // Get the cyclic value in the range [0..cycle-1] 2789 function PositiveMod(value, cycle: integer): integer; inline;3978 function PositiveMod(value, cycle: Int32or64): Int32or64; inline; 2790 3979 begin 2791 3980 result := value mod cycle; … … 2801 3990 byteSqrtTab: packed array of word; 2802 3991 2803 function Sin65536(value: word): integer;3992 function Sin65536(value: word): Int32or64; 2804 3993 var b: integer; 2805 3994 begin … … 2825 4014 end; 2826 4015 2827 function Cos65536(value: word): integer; 2828 begin 4016 function Cos65536(value: word): Int32or64; 4017 begin 4018 {$PUSH}{$R-} 2829 4019 result := Sin65536(value+16384); //cosine is translated 4020 {$POP} 2830 4021 end; 2831 4022 … … 2854 4045 end; 2855 4046 4047 function DetectFileFormat(AFilenameUTF8: string): TBGRAImageFormat; 4048 var stream: TFileStreamUTF8; 4049 begin 4050 try 4051 stream := TFileStreamUTF8.Create(AFilenameUTF8,fmOpenRead or fmShareDenyWrite); 4052 except 4053 result := ifUnknown; 4054 exit; 4055 end; 4056 try 4057 result := DetectFileFormat(stream, ExtractFileExt(AFilenameUTF8)); 4058 finally 4059 stream.Free; 4060 end; 4061 end; 4062 4063 function DetectFileFormat(AStream: TStream; ASuggestedExtensionUTF8: string 4064 ): TBGRAImageFormat; 4065 var 4066 scores: array[TBGRAImageFormat] of integer; 4067 imageFormat,bestImageFormat: TBGRAImageFormat; 4068 bestScore: integer; 4069 4070 procedure DetectFromStream; 4071 var 4072 {%H-}magic: packed array[0..7] of byte; 4073 {%H-}dwords: packed array[0..9] of DWORD; 4074 magicAsText: string; 4075 4076 streamStartPos, maxFileSize: Int64; 4077 expectedFileSize: DWord; 4078 4079 procedure DetectTarga; 4080 var 4081 paletteCount: integer; 4082 {%H-}targaPixelFormat: packed record pixelDepth: byte; imgDescriptor: byte; end; 4083 begin 4084 if (magic[1] in[$00,$01]) and (magic[2] in[0,1,2,3,9,10,11]) and (maxFileSize >= 18) then 4085 begin 4086 paletteCount:= magic[5] + magic[6] shl 8; 4087 if ((paletteCount = 0) and (magic[7] = 0)) or 4088 (magic[7] in [16,24,32]) then //check palette bit count 4089 begin 4090 AStream.Position:= streamStartPos+16; 4091 if AStream.Read({%H-}targaPixelFormat,2) = 2 then 4092 begin 4093 if (targaPixelFormat.pixelDepth in [8,16,24,32]) and 4094 (targaPixelFormat.imgDescriptor and 15 < targaPixelFormat.pixelDepth) then 4095 inc(scores[ifTarga],2); 4096 end; 4097 end; 4098 end; 4099 end; 4100 4101 procedure DetectLazPaint; 4102 var 4103 w,h: dword; 4104 i: integer; 4105 begin 4106 if (copy(magicAsText,1,8) = 'LazPaint') then //with header 4107 begin 4108 AStream.Position:= streamStartPos+8; 4109 if AStream.Read(dwords,10*4) = 10*4 then 4110 begin 4111 for i := 0 to 6 do dwords[i] := LEtoN(dwords[i]); 4112 if (dwords[0] = 0) and (dwords[1] <= expectedFileSize) and (dwords[5] <= expectedFileSize) and 4113 (dwords[9] <= expectedFileSize) and 4114 (dwords[6] = 0) then inc(scores[ifLazPaint],2); 4115 end; 4116 end else //without header 4117 if ((magic[0] <> 0) or (magic[1] <> 0)) and (magic[2] = 0) and (magic[3] = 0) and 4118 ((magic[4] <> 0) or (magic[5] <> 0)) and (magic[6] = 0) and (magic[7] = 0) then 4119 begin 4120 w := magic[0] + (magic[1] shl 8); 4121 h := magic[4] + (magic[5] shl 8); 4122 AStream.Position:= streamStartPos+8; 4123 if AStream.Read(dwords,4) = 4 then 4124 begin 4125 dwords[0] := LEtoN(dwords[0]); 4126 if (dwords[0] > 0) and (dwords[0] < 65536) then 4127 begin 4128 if 12+dwords[0] < expectedFileSize then 4129 begin 4130 AStream.Position:= streamStartPos+12+dwords[0]; 4131 if AStream.Read(dwords,6*4) = 6*4 then 4132 begin 4133 for i := 0 to 5 do dwords[i] := LEtoN(dwords[i]); 4134 if (dwords[0] <= w) and (dwords[1] <= h) and 4135 (dwords[2] <= w) and (dwords[3] <= h) and 4136 (dwords[2] >= dwords[0]) and (dwords[3] >= dwords[1]) and 4137 ((dwords[4] = 0) or (dwords[4] = 1)) and 4138 (dwords[5] > 0) then inc(scores[ifLazPaint],1); 4139 end; 4140 end; 4141 end; 4142 end; 4143 end; 4144 end; 4145 4146 begin 4147 fillchar({%H-}magic, sizeof(magic), 0); 4148 fillchar({%H-}dwords, sizeof(dwords), 0); 4149 4150 streamStartPos:= AStream.Position; 4151 maxFileSize:= AStream.Size - streamStartPos; 4152 if maxFileSize < 8 then exit; 4153 if AStream.Read(magic,sizeof(magic)) <> sizeof(magic) then 4154 begin 4155 fillchar(scores,sizeof(scores),0); 4156 exit; 4157 end; 4158 setlength(magicAsText,sizeof(magic)); 4159 move(magic[0],magicAsText[1],sizeof(magic)); 4160 4161 if (magic[0] = $ff) and (magic[1] = $d8) then 4162 begin 4163 inc(scores[ifJpeg]); 4164 if (magic[2] = $ff) and (magic[3] >= $c0) then inc(scores[ifJpeg]); 4165 end; 4166 4167 if (magic[0] = $89) and (magic[1] = $50) and (magic[2] = $4e) and 4168 (magic[3] = $47) and (magic[4] = $0d) and (magic[5] = $0a) and 4169 (magic[6] = $1a) and (magic[7] = $0a) then inc(scores[ifPng],2); 4170 4171 if (copy(magicAsText,1,6)='GIF87a') or (copy(magicAsText,1,6)='GIF89a') then inc(scores[ifGif],2); 4172 4173 if (magic[0] = $0a) and (magic[1] in [0,2,3,4,5]) and (magic[2] in[0,1]) and (magic[3] in[1,2,4,8]) then 4174 inc(scores[ifPcx],2); 4175 4176 if (copy(magicAsText,1,2)='BM') then 4177 begin 4178 inc(scores[ifBmp]); 4179 expectedFileSize:= magic[2] + (magic[3] shl 8) + (magic[4] shl 16) + (magic[5] shl 24); 4180 if expectedFileSize = maxFileSize then inc(scores[ifBmp]); 4181 end else 4182 if (copy(magicAsText,1,2)='RL') then 4183 begin 4184 inc(scores[ifBmpMioMap]); 4185 if (magic[2] in[0,1]) and (magic[3] = 0) then inc(scores[ifBmpMioMap]); 4186 end; 4187 4188 if (magic[0] = $00) and (magic[1] = $00) and (magic[2] in[$01,$02]) and (magic[3] = $00) and 4189 (magic[4] + (magic[5] shl 8) > 0) then inc(scores[ifIco]); 4190 4191 if (copy(magicAsText,1,4) = 'PDN3') then 4192 begin 4193 expectedFileSize:= 6 + (magic[4] + (magic[5] shl 8) + (magic[6] shl 16)) + 2; 4194 if expectedFileSize <= maxFileSize then 4195 begin 4196 inc(scores[ifPaintDotNet]); 4197 if magic[7] = $3c then inc(scores[ifPaintDotNet]); 4198 end; 4199 end; 4200 4201 DetectLazPaint; 4202 4203 if (magic[0] = $50) and (magic[1] = $4b) and (magic[2] = $03) and (magic[3] = $04) then 4204 begin 4205 if DefaultBGRAImageReader[ifOpenRaster] = nil then inc(scores[ifOpenRaster]) else 4206 with CreateBGRAImageReader(ifOpenRaster) do 4207 try 4208 if CheckContents(AStream) then inc(scores[ifOpenRaster],2); 4209 finally 4210 Free; 4211 end; 4212 end; 4213 4214 if (copy(magicAsText,1,4) = '8BPS') and (magic[4] = $00) and (magic[5] = $01) then inc(scores[ifPsd],2); 4215 4216 DetectTarga; 4217 4218 if (copy(magicAsText,1,2)='II') and (magic[2] = 42) and (magic[3]=0) then inc(scores[ifTiff]) else 4219 if (copy(magicAsText,1,2)='MM') and (magic[2] = 0) and (magic[3]=42) then inc(scores[ifTiff]); 4220 4221 if (copy(magicAsText,1,8) = '/* XPM *') or (copy(magicAsText,1,6) = '! XPM2') then inc(scores[ifXPixMap]); 4222 4223 AStream.Position := streamStartPos; 4224 end; 4225 4226 var 4227 extFormat: TBGRAImageFormat; 4228 4229 begin 4230 result := ifUnknown; 4231 for imageFormat:= low(TBGRAImageFormat) to high(TBGRAImageFormat) do 4232 scores[imageFormat] := 0; 4233 4234 ASuggestedExtensionUTF8:= UTF8LowerCase(ASuggestedExtensionUTF8); 4235 if (ASuggestedExtensionUTF8 <> '') and (UTF8Copy(ASuggestedExtensionUTF8,1,1) <> '.') then 4236 ASuggestedExtensionUTF8 := '.'+ASuggestedExtensionUTF8; 4237 4238 extFormat:= SuggestImageFormat(ASuggestedExtensionUTF8); 4239 if extFormat <> ifUnknown then inc(scores[extFormat]); 4240 4241 If AStream <> nil then DetectFromStream; 4242 4243 bestScore := 0; 4244 bestImageFormat:= ifUnknown; 4245 for imageFormat:=low(TBGRAImageFormat) to high(TBGRAImageFormat) do 4246 if scores[imageFormat] > bestScore then 4247 begin 4248 bestScore:= scores[imageFormat]; 4249 bestImageFormat:= imageFormat; 4250 end; 4251 result := bestImageFormat; 4252 end; 4253 4254 function SuggestImageFormat(AFilenameOrExtensionUTF8: string): TBGRAImageFormat; 4255 var ext: string; 4256 begin 4257 result := ifUnknown; 4258 4259 ext := ExtractFileName(AFilenameOrExtensionUTF8); 4260 if pos('.', ext) <> 0 then ext := ExtractFileExt(ext) else ext := '.'+ext; 4261 ext := UTF8LowerCase(ext); 4262 4263 if (ext = '.jpg') or (ext = '.jpeg') then result := ifJpeg else 4264 if (ext = '.png') then result := ifPng else 4265 if (ext = '.gif') then result := ifGif else 4266 if (ext = '.pcx') then result := ifPcx else 4267 if (ext = '.bmp') then result := ifBmp else 4268 if (ext = '.ico') or (ext = '.cur') then result := ifIco else 4269 if (ext = '.pdn') then result := ifPaintDotNet else 4270 if (ext = '.lzp') then result := ifLazPaint else 4271 if (ext = '.ora') then result := ifOpenRaster else 4272 if (ext = '.psd') then result := ifPsd else 4273 if (ext = '.tga') then result := ifTarga else 4274 if (ext = '.tif') or (ext = '.tiff') then result := ifTiff else 4275 if (ext = '.xwd') then result := ifXwd else 4276 if (ext = '.xpm') then result := ifXPixMap; 4277 end; 4278 4279 function CreateBGRAImageReader(AFormat: TBGRAImageFormat): TFPCustomImageReader; 4280 begin 4281 if DefaultBGRAImageReader[AFormat] = nil then 4282 begin 4283 case AFormat of 4284 ifUnknown: raise exception.Create('The image format is unknown.'); 4285 ifOpenRaster: raise exception.Create('You need to call BGRAOpenRaster.RegisterOpenRasterFormat to read this image.'); 4286 ifPaintDotNet: raise exception.Create('You need to call BGRAPaintNet.RegisterPaintNetFormat to read this image.'); 4287 else 4288 raise exception.Create('The image reader is not registered for this image format.'); 4289 end; 4290 end; 4291 result := DefaultBGRAImageReader[AFormat].Create; 4292 end; 4293 4294 function CreateBGRAImageWriter(AFormat: TBGRAImageFormat; AHasTransparentPixels: boolean): TFPCustomImageWriter; 4295 begin 4296 if DefaultBGRAImageWriter[AFormat] = nil then 4297 begin 4298 case AFormat of 4299 ifUnknown: raise exception.Create('The image format is unknown'); 4300 ifOpenRaster: raise exception.Create('You need to call BGRAOpenRaster.RegisterOpenRasterFormat to write with this image format.'); 4301 else 4302 raise exception.Create('The image writer is not registered for this image format.'); 4303 end; 4304 end; 4305 4306 if AFormat = ifPng then 4307 begin 4308 result := TFPWriterPNG.Create; 4309 TFPWriterPNG(result).Indexed := false; 4310 TFPWriterPNG(result).WordSized := false; 4311 TFPWriterPNG(result).UseAlpha := AHasTransparentPixels; 4312 end else 4313 if AFormat = ifBmp then 4314 begin 4315 result := TFPWriterBMP.Create; 4316 if AHasTransparentPixels then 4317 TFPWriterBMP(result).BitsPerPixel := 32 else 4318 TFPWriterBMP(result).BitsPerPixel := 24; 4319 end else 4320 if AFormat = ifXPixMap then 4321 begin 4322 result := TFPWriterXPM.Create; 4323 TFPWriterXPM(result).ColorCharSize := 2; 4324 end else 4325 result := DefaultBGRAImageWriter[AFormat].Create; 4326 end; 4327 2856 4328 initialization 2857 4329 2858 4330 InitGamma; 2859 CSSColors := TBGRAColorList.Create; 2860 CSSColors.Add('AliceBlue',CSSAliceBlue); 2861 CSSColors.Add('AntiqueWhite',CSSAntiqueWhite); 2862 CSSColors.Add('Aqua',CSSAqua); 2863 CSSColors.Add('Aquamarine',CSSAquamarine); 2864 CSSColors.Add('Azure',CSSAzure); 2865 CSSColors.Add('Beige',CSSBeige); 2866 CSSColors.Add('Bisque',CSSBisque); 2867 CSSColors.Add('Black',CSSBlack); 2868 CSSColors.Add('BlanchedAlmond',CSSBlanchedAlmond); 2869 CSSColors.Add('Blue',CSSBlue); 2870 CSSColors.Add('BlueViolet',CSSBlueViolet); 2871 CSSColors.Add('Brown',CSSBrown); 2872 CSSColors.Add('BurlyWood',CSSBurlyWood); 2873 CSSColors.Add('CadetBlue',CSSCadetBlue); 2874 CSSColors.Add('Chartreuse',CSSChartreuse); 2875 CSSColors.Add('Chocolate',CSSChocolate); 2876 CSSColors.Add('Coral',CSSCoral); 2877 CSSColors.Add('CornflowerBlue',CSSCornflowerBlue); 2878 CSSColors.Add('Cornsilk',CSSCornsilk); 2879 CSSColors.Add('Crimson',CSSCrimson); 2880 CSSColors.Add('Cyan',CSSCyan); 2881 CSSColors.Add('DarkBlue',CSSDarkBlue); 2882 CSSColors.Add('DarkCyan',CSSDarkCyan); 2883 CSSColors.Add('DarkGoldenrod',CSSDarkGoldenrod); 2884 CSSColors.Add('DarkGray',CSSDarkGray); 2885 CSSColors.Add('DarkGreen',CSSDarkGreen); 2886 CSSColors.Add('DarkKhaki',CSSDarkKhaki); 2887 CSSColors.Add('DarkMagenta',CSSDarkMagenta); 2888 CSSColors.Add('DarkOliveGreen',CSSDarkOliveGreen); 2889 CSSColors.Add('DarkOrange',CSSDarkOrange); 2890 CSSColors.Add('DarkOrchid',CSSDarkOrchid); 2891 CSSColors.Add('DarkRed',CSSDarkRed); 2892 CSSColors.Add('DarkSalmon',CSSDarkSalmon); 2893 CSSColors.Add('DarkSeaGreen',CSSDarkSeaGreen); 2894 CSSColors.Add('DarkSlateBlue',CSSDarkSlateBlue); 2895 CSSColors.Add('DarkSlateGray',CSSDarkSlateGray); 2896 CSSColors.Add('DarkTurquoise',CSSDarkTurquoise); 2897 CSSColors.Add('DarkViolet',CSSDarkViolet); 2898 CSSColors.Add('DeepPink',CSSDeepPink); 2899 CSSColors.Add('DeepSkyBlue',CSSDeepSkyBlue); 2900 CSSColors.Add('DimGray',CSSDimGray); 2901 CSSColors.Add('DodgerBlue',CSSDodgerBlue); 2902 CSSColors.Add('FireBrick',CSSFireBrick); 2903 CSSColors.Add('FloralWhite',CSSFloralWhite); 2904 CSSColors.Add('ForestGreen',CSSForestGreen); 2905 CSSColors.Add('Fuchsia',CSSFuchsia); 2906 CSSColors.Add('Gainsboro',CSSGainsboro); 2907 CSSColors.Add('GhostWhite',CSSGhostWhite); 2908 CSSColors.Add('Gold',CSSGold); 2909 CSSColors.Add('Goldenrod',CSSGoldenrod); 2910 CSSColors.Add('Gray',CSSGray); 2911 CSSColors.Add('Green',CSSGreen); 2912 CSSColors.Add('GreenYellow',CSSGreenYellow); 2913 CSSColors.Add('Honeydew',CSSHoneydew); 2914 CSSColors.Add('HotPink',CSSHotPink); 2915 CSSColors.Add('IndianRed',CSSIndianRed); 2916 CSSColors.Add('Indigo',CSSIndigo); 2917 CSSColors.Add('Ivory',CSSIvory); 2918 CSSColors.Add('Khaki',CSSKhaki); 2919 CSSColors.Add('Lavender',CSSLavender); 2920 CSSColors.Add('LavenderBlush',CSSLavenderBlush); 2921 CSSColors.Add('LawnGreen',CSSLawnGreen); 2922 CSSColors.Add('LemonChiffon',CSSLemonChiffon); 2923 CSSColors.Add('LightBlue',CSSLightBlue); 2924 CSSColors.Add('LightCoral',CSSLightCoral); 2925 CSSColors.Add('LightCyan',CSSLightCyan); 2926 CSSColors.Add('LightGoldenrodYellow',CSSLightGoldenrodYellow); 2927 CSSColors.Add('LightGray',CSSLightGray); 2928 CSSColors.Add('LightGreen',CSSLightGreen); 2929 CSSColors.Add('LightPink',CSSLightPink); 2930 CSSColors.Add('LightSalmon',CSSLightSalmon); 2931 CSSColors.Add('LightSeaGreen',CSSLightSeaGreen); 2932 CSSColors.Add('LightSkyBlue',CSSLightSkyBlue); 2933 CSSColors.Add('LightSlateGray',CSSLightSlateGray); 2934 CSSColors.Add('LightSteelBlue',CSSLightSteelBlue); 2935 CSSColors.Add('LightYellow',CSSLightYellow); 2936 CSSColors.Add('Lime',CSSLime); 2937 CSSColors.Add('LimeGreen',CSSLimeGreen); 2938 CSSColors.Add('Linen',CSSLinen); 2939 CSSColors.Add('Magenta',CSSMagenta); 2940 CSSColors.Add('Maroon',CSSMaroon); 2941 CSSColors.Add('MediumAquamarine',CSSMediumAquamarine); 2942 CSSColors.Add('MediumBlue',CSSMediumBlue); 2943 CSSColors.Add('MediumOrchid',CSSMediumOrchid); 2944 CSSColors.Add('MediumPurple',CSSMediumPurple); 2945 CSSColors.Add('MediumSeaGreen',CSSMediumSeaGreen); 2946 CSSColors.Add('MediumSlateBlue',CSSMediumSlateBlue); 2947 CSSColors.Add('MediumSpringGreen',CSSMediumSpringGreen); 2948 CSSColors.Add('MediumTurquoise',CSSMediumTurquoise); 2949 CSSColors.Add('MediumVioletRed',CSSMediumVioletRed); 2950 CSSColors.Add('MidnightBlue',CSSMidnightBlue); 2951 CSSColors.Add('MintCream',CSSMintCream); 2952 CSSColors.Add('MistyRose',CSSMistyRose); 2953 CSSColors.Add('Moccasin',CSSMoccasin); 2954 CSSColors.Add('NavajoWhite',CSSNavajoWhite); 2955 CSSColors.Add('Navy',CSSNavy); 2956 CSSColors.Add('OldLace',CSSOldLace); 2957 CSSColors.Add('Olive',CSSOlive); 2958 CSSColors.Add('OliveDrab',CSSOliveDrab); 2959 CSSColors.Add('Orange',CSSOrange); 2960 CSSColors.Add('OrangeRed',CSSOrangeRed); 2961 CSSColors.Add('Orchid',CSSOrchid); 2962 CSSColors.Add('PaleGoldenrod',CSSPaleGoldenrod); 2963 CSSColors.Add('PaleGreen',CSSPaleGreen); 2964 CSSColors.Add('PaleTurquoise',CSSPaleTurquoise); 2965 CSSColors.Add('PaleVioletRed',CSSPaleVioletRed); 2966 CSSColors.Add('PapayaWhip',CSSPapayaWhip); 2967 CSSColors.Add('PeachPuff',CSSPeachPuff); 2968 CSSColors.Add('Peru',CSSPeru); 2969 CSSColors.Add('Pink',CSSPink); 2970 CSSColors.Add('Plum',CSSPlum); 2971 CSSColors.Add('PowderBlue',CSSPowderBlue); 2972 CSSColors.Add('Purple',CSSPurple); 2973 CSSColors.Add('Red',CSSRed); 2974 CSSColors.Add('RosyBrown',CSSRosyBrown); 2975 CSSColors.Add('RoyalBlue',CSSRoyalBlue); 2976 CSSColors.Add('SaddleBrown',CSSSaddleBrown); 2977 CSSColors.Add('Salmon',CSSSalmon); 2978 CSSColors.Add('SandyBrown',CSSSandyBrown); 2979 CSSColors.Add('SeaGreen',CSSSeaGreen); 2980 CSSColors.Add('Seashell',CSSSeashell); 2981 CSSColors.Add('Sienna',CSSSienna); 2982 CSSColors.Add('Silver',CSSSilver); 2983 CSSColors.Add('SkyBlue',CSSSkyBlue); 2984 CSSColors.Add('SlateBlue',CSSSlateBlue); 2985 CSSColors.Add('SlateGray',CSSSlateGray); 2986 CSSColors.Add('Snow',CSSSnow); 2987 CSSColors.Add('SpringGreen',CSSSpringGreen); 2988 CSSColors.Add('SteelBlue',CSSSteelBlue); 2989 CSSColors.Add('Tan',CSSTan); 2990 CSSColors.Add('Teal',CSSTeal); 2991 CSSColors.Add('Thistle',CSSThistle); 2992 CSSColors.Add('Tomato',CSSTomato); 2993 CSSColors.Add('Turquoise',CSSTurquoise); 2994 CSSColors.Add('Violet',CSSViolet); 2995 CSSColors.Add('Wheat',CSSWheat); 2996 CSSColors.Add('White',CSSWhite); 2997 CSSColors.Add('WhiteSmoke',CSSWhiteSmoke); 2998 CSSColors.Add('Yellow',CSSYellow); 2999 CSSColors.Add('YellowGreen',CSSYellowGreen); 3000 CSSColors.Finished; 4331 {$DEFINE INCLUDE_COLOR_LIST} 4332 {$I csscolorconst.inc} 4333 DefaultBGRAImageWriter[ifJpeg] := TFPWriterJPEG; 4334 DefaultBGRAImageWriter[ifPng] := TFPWriterPNG; 4335 DefaultBGRAImageWriter[ifBmp] := TFPWriterBMP; 4336 DefaultBGRAImageWriter[ifPcx] := TFPWriterPCX; 4337 DefaultBGRAImageWriter[ifTarga] := TFPWriterTarga; 4338 DefaultBGRAImageWriter[ifXPixMap] := TFPWriterXPM; 4339 DefaultBGRAImageWriter[ifTiff] := TFPWriterTiff; 4340 //writing XWD not implemented 4341 4342 DefaultBGRAImageReader[ifTiff] := TFPReaderTiff; 4343 DefaultBGRAImageReader[ifXwd] := TFPReaderXWD; 4344 //the other readers are registered by their unit 3001 4345 3002 4346 finalization 3003 4347 3004 4348 CSSColors.Free; 4349 VGAColors.Free; 3005 4350 3006 4351 end.
Note:
See TracChangeset
for help on using the changeset viewer.