From: <tw...@us...> - 2020-02-02 14:59:37
|
Revision: 3045 http://sourceforge.net/p/gexperts/code/3045 Author: twm Date: 2020-02-02 14:59:35 +0000 (Sun, 02 Feb 2020) Log Message: ----------- synced with current dzlib Modified Paths: -------------- trunk/ExternalSource/dzlib/dzlib.inc trunk/ExternalSource/dzlib/u_dzConvertUtils.pas trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas Modified: trunk/ExternalSource/dzlib/dzlib.inc =================================================================== --- trunk/ExternalSource/dzlib/dzlib.inc 2020-02-02 14:52:44 UTC (rev 3044) +++ trunk/ExternalSource/dzlib/dzlib.inc 2020-02-02 14:59:35 UTC (rev 3045) @@ -5,8 +5,11 @@ {$DEFINE HAS_BITBTN_WORDWRAP} // So was the $WARN USE_BEFORE_DEF define {$DEFINE SUPPORTS_WARN_USE_BEFORE_DEF} +// Not sure about TBitmap.SetSize, was it introduced with Delphi 7 or later? +{$DEFINE SUPPPORTS_BITMAP_SETSIZE} {$ENDIF} + {$IFDEF DELPHI2005_UP} // Delphi 6 and 7 understood deprecated, but not for types {$DEFINE SUPPORTS_DEPRECATED_TYPES} Modified: trunk/ExternalSource/dzlib/u_dzConvertUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2020-02-02 14:52:44 UTC (rev 3044) +++ trunk/ExternalSource/dzlib/u_dzConvertUtils.pas 2020-02-02 14:59:35 UTC (rev 3045) @@ -140,6 +140,13 @@ function isNumberN(const _s: string; _Base: TBaseN): Integer; ///<summary> +/// Reduces an Integer to a Byte value by cutting it off at 0 and 255 </summary> +function ReduceToByte(const _Value: Integer): Byte; +{$IFDEF SUPPORTS_INLINE} + inline; +{$ENDIF} + +///<summary> /// Converts a string of the form '-hh:mm:ss', 'hh:mm:ss', /// '+hh:mm:ss', 'mm:ss' or 'ss' to a number of seconds. </summary> function TimeStrToSeconds(const _Zeit: string): Integer; @@ -577,6 +584,16 @@ Result := '0' + Result; end; +function ReduceToByte(const _Value: Integer): Byte; inline; +begin + if _Value < 0 then + Result := 0 + else if _Value > 255 then + Result := 255 + else + Result := _Value; +end; + function isHexDigit(_a: Char): Boolean; begin Result := isDigit(_a, 16); Modified: trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas =================================================================== --- trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2020-02-02 14:52:44 UTC (rev 3044) +++ trunk/ExternalSource/dzlib/u_dzGraphicsUtils.pas 2020-02-02 14:59:35 UTC (rev 3045) @@ -12,7 +12,7 @@ // If optimization is on, we turn off assertions, just in case the programmer forgot. // The reason for this is that we have some assertions below that might significantly impact // performance. -{$C-} // this is the short form for $ASSERTIONS ON +{$C-} // this is the short form for $ASSERTIONS OFF {$ENDIF} {.$DEFINE dzUseGraphics32} @@ -28,6 +28,7 @@ GR32, // libs\graphics32\src {$ENDIF} u_dzTranslator, + u_dzConvertUtils, u_dzTypesUtils; type @@ -53,6 +54,7 @@ end; type + PdzRgbTriple = ^TdzRgbTriple; TdzRgbTriple = packed record // do not change the order of the fields, do not add any fields Blue: Byte; @@ -66,7 +68,7 @@ function GetFastLuminance: Byte; overload; class function GetFastLuminance(_Red, _Green, _Blue: Byte): Byte; overload; static; inline; function GetBrightness(_Channel: TRgbBrightnessChannelEnum): Byte; - procedure SetBrightness(_Value: Byte); + procedure SetBrightness(_Value: Byte); deprecated; //use SetGray procedure GetHls(out _Hls: THlsRec); procedure SetHls(const _Hls: THlsRec); {$ENDIF} @@ -85,6 +87,11 @@ inline; {$ENDIF} +function PtrDiff(const _Ptr1, _Ptr2: Pointer): NativeInt; inline; +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} + function TdzRgbTriple_GetFastLuminance(const _Triple: TdzRgbTriple): Byte; {$IFDEF SUPPORTS_INLINE} inline; @@ -104,6 +111,7 @@ PdzRgbTripleArray = ^TdzRgbTripleArray; type + PdzRgbQuad = ^TdzRgbQuad; TdzRgbQuad = packed record // do not change the order of the fields, do not add any fields Blue: Byte; @@ -117,7 +125,7 @@ function GetLuminance: Word; function GetFastLuminance: Word; function GetBrightness(_Channel: TRgbBrightnessChannelEnum): Word; - procedure SetBrightness(_Value: Byte); + procedure SetBrightness(_Value: Byte); deprecated; //use SetGray procedure GetHls(out _Hue, _Luminance, _Saturation: Word); procedure SetHls(_Hue, _Luminance, _Saturation: Word); {$ENDIF} @@ -450,7 +458,7 @@ {$ENDIF} ///<summary> -/// calculates the average brightness of an bitmap with PixelFormat = pf8Bit +/// Calculates the average brightness of an bitmap with PixelFormat = pf8Bit /// @param bmp is the bitmap to process /// @param LowCutoff is the lower brightness limit for pixels to be include in the calculation /// @param HighCutoff is the upper brightness limit for pixels to be include in the calculation @@ -461,7 +469,7 @@ out _Average: Byte): Boolean; ///<summary> -/// calculates the average brightness of an bitmap with PixelFormat = pf24Bit +/// Calculates the average brightness of an bitmap with PixelFormat = pf24Bit /// @param bmp is the bitmap to process /// @param LowCutoff is the lower brightness limit for pixels to be include in the calculation /// @param HighCutoff is the upper brightness limit for pixels to be include in the calculation @@ -473,6 +481,18 @@ _Channel: TRgbBrightnessChannelEnum; out _Average: Byte): Boolean; +///<summary> +/// Calculates the average brightness of an bitmap with PixelFormat = pf24Bit thereby only +/// using the blue channel. +/// @param bmp is the bitmap to process +/// @param LowCutoff is the lower brightness limit for pixels to be include in the calculation +/// @param HighCutoff is the upper brightness limit for pixels to be include in the calculation +/// @param Average returns the calculated average, only valid if Result = True +/// @returns True, if at least on pixel was in the desired interval +/// False, if not </summary> +function TBitmap24_TryCalcAverageBlue(_bmp: TBitmap; _LowCutoff, _HighCutoff: Byte; + out _Average: Byte): Boolean; + type // Note: The bitmap is stored upside down, so the y coordinates are reversed! TPixel24FilterCallback = procedure(_x, _y: Integer; var _Pixel: TdzRgbTriple) of object; @@ -484,6 +504,35 @@ procedure TBitmap8_FilterPixels(_SrcBmp, _DstBmp: TBitmap; _Callback: TPixel8FilterCallback); type + TGammaCurve = array[0..255] of Byte; + +///</summary> +/// Apply the given gamma curves to the respctive colors of the bitmap </summary> +procedure TBitmap24_ApplyGamma(_SrcBmp, _DstBmp: TBitmap; const _GammaRed, _GammaGreen, _GammaBlue: TGammaCurve); overload; + +///</summary> +/// Apply the given gamma curve to all colors of the bitmap </summary> +procedure TBitmap24_ApplyGamma(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); overload; + +///</summary> +/// Apply the given gamma curve to an 8 bit gray scale bitmap </summary> +procedure TBitmap8_ApplyGamma(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); overload; + +///</summary> +/// Apply the given gamma curve to a 24 bit gray scale bitmap and convert it to 8 bit +/// in the process. +/// @param SrcBmp is the source bitmap, must have PixelFormat pf24bit and be grayscale +/// The algoritm only takes the blue channel for the conversion. +/// @param DstBmp is the destinateion bitmap, it will be set to the same size as the source +/// and to PixelFormat pf8bit and a gray scale palette. +/// @param Gamma is an array representing the gamma curve to apply. </summary> +procedure TBitmap24_ApplyGammaTo8(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); overload; + +///</summary> +/// Sequentially Apply the given gamma curves to an 8 bit gray scale bitmap </summary> +procedure TBitmap8_ApplyMultiGamma(_SrcBmp, _DstBmp: TBitmap; const _GammaArr: array of TGammaCurve); overload; + +type ///<summary> /// PixelFilter for cutting off R, G and B values at the given CutOff value /// This reduches brightness of white pixels by cutting of brightness at a given value. @@ -503,8 +552,11 @@ private FLowCutOff: Byte; FHighCutOff: Byte; - FFactor: Extended; + FDivisor: Integer; procedure StretchColor(var _Color: Byte); +{$IFDEF SUPPORTS_INLINE} + inline; +{$ENDIF} public constructor Create(_LowCutoff, _HighCutoff: Byte); procedure FilterCallback(_x, _y: Integer; var _Pixel: TdzRgbTriple); overload; @@ -516,6 +568,9 @@ private FMoveBy: Integer; procedure MoveColor(var _Color: Byte); +{$IFDEF SUPPORTS_INLINE} + inline; +{$ENDIF} public constructor Create(_MoveBy: Integer); procedure FilterCallback(_x, _y: Integer; var _Pixel: TdzRgbTriple); overload; @@ -556,9 +611,8 @@ uses Math, - GraphUtil, jpeg, // if you get a compile error here you might need to add Vcl.Imaging to the unit scope names - u_dzConvertUtils; + GraphUtil; function _(const _s: string): string; {$IFDEF SUPPORTS_INLINE} @@ -1205,9 +1259,16 @@ {$ENDIF} procedure TBitmap_SetSize(_bmp: TBitmap; _Width, _Height: Integer); +{$IFDEF SUPPORTS_INLINE} +inline; +{$ENDIF} begin +{$IFDEF SUPPPORTS_BITMAP_SETSIZE} + _bmp.SetSize(_Width, _Height); +{$ELSE} _bmp.Width := _Width; _bmp.Height := _Height; +{$ENDIF} end; {$IF Declared(TBitmap32)} @@ -1770,13 +1831,18 @@ end; procedure TBitmap24_FilterPixels(_SrcBmp, _DstBmp: TBitmap; _Callback: TPixel24FilterCallback); +const + BytesPerPixel = 3; var x: Integer; y: Integer; w: Integer; h: Integer; - SrcLine: PdzRgbTripleArray; - DstLine: PdzRgbTripleArray; + SrcLine: PByte; + DstLine: PByte; + SrcPixel: PByte; + DstPixel: PByte; + BytesPerLine: Integer; begin Assert(Assigned(_SrcBmp)); @@ -1786,28 +1852,45 @@ h := _SrcBmp.Height; TBitmap_SetSize(_DstBmp, w, h); + BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; + Assert(BytesPerLine = Graphics.BytesPerScanline(w, BytesPerPixel * 8, 32)); + + SrcLine := _SrcBmp.ScanLine[0]; + DstLine := _DstBmp.ScanLine[0]; for y := 0 to h - 1 do begin - SrcLine := _SrcBmp.ScanLine[y]; - DstLine := _DstBmp.ScanLine[y]; + Assert(SrcLine = _SrcBmp.ScanLine[y]); + Assert(DstLine = _DstBmp.ScanLine[y]); + SrcPixel := SrcLine; + DstPixel := DstLine; for x := 0 to w - 1 do begin - DstLine^[x] := SrcLine^[x]; - _Callback(x, y, DstLine^[x]); + PdzRgbTriple(DstPixel)^ := PdzRgbTriple(SrcPixel)^; + _Callback(x, y, PdzRgbTriple(DstPixel)^); + Inc(SrcPixel, BytesPerPixel); + Inc(DstPixel, BytesPerPixel); end; + Dec(SrcLine, BytesPerLine); + Dec(DstLine, BytesPerLine); end; end; procedure TBitmap8_FilterPixels(_SrcBmp, _DstBmp: TBitmap; _Callback: TPixel8FilterCallback); +const + BytesPerPixel = 1; var x: Integer; y: Integer; w: Integer; h: Integer; - SrcLine: PByteArray; - DstLine: PByteArray; + SrcLine: PByte; + DstLine: PByte; + SrcPixel: PByte; + DstPixel: PByte; + BytesPerLine: Integer; begin Assert(Assigned(_SrcBmp)); _SrcBmp.PixelFormat := pf8bit; + _DstBmp.Assign(nil); _DstBmp.PixelFormat := pf8bit; w := _SrcBmp.Width; h := _SrcBmp.Height; @@ -1814,16 +1897,264 @@ _DstBmp.Palette := MakeGrayPalette; TBitmap_SetSize(_DstBmp, w, h); + BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; + Assert(BytesPerLine = Graphics.BytesPerScanline(w, BytesPerPixel * 8, 32)); + + SrcLine := _SrcBmp.ScanLine[0]; + DstLine := _DstBmp.ScanLine[0]; for y := 0 to h - 1 do begin - SrcLine := _SrcBmp.ScanLine[y]; - DstLine := _DstBmp.ScanLine[y]; + Assert(SrcLine = _SrcBmp.ScanLine[y]); + Assert(DstLine = _DstBmp.ScanLine[y]); + SrcPixel := SrcLine; + DstPixel := DstLine; for x := 0 to w - 1 do begin - DstLine^[x] := SrcLine^[x]; - _Callback(x, y, DstLine^[x]); + DstPixel^ := SrcPixel^; + _Callback(x, y, DstPixel^); + Inc(SrcPixel, BytesPerPixel); + Inc(DstPixel, BytesPerPixel); end; + Dec(SrcLine, BytesPerLine); + Dec(DstLine, BytesPerLine); end; end; +procedure TBitmap24_ApplyGamma(_SrcBmp, _DstBmp: TBitmap; const _GammaRed, _GammaGreen, _GammaBlue: TGammaCurve); +const + BytesPerPixel = 3; +var + x: Integer; + y: Integer; + w: Integer; + h: Integer; + SrcLine: PByte; + DstLine: PByte; + SrcPixel: PByte; + DstPixel: PByte; + DstTriple: PdzRgbTriple; + SrcTriple: PdzRgbTriple; + BytesPerLine: Integer; +begin + Assert(Assigned(_SrcBmp)); + Assert(_SrcBmp.PixelFormat = pf24bit); + + _DstBmp.PixelFormat := pf24bit; + w := _SrcBmp.Width; + h := _SrcBmp.Height; + TBitmap_SetSize(_DstBmp, w, h); + + BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; + Assert(BytesPerLine = Graphics.BytesPerScanline(w, BytesPerPixel * 8, 32)); + + SrcLine := _SrcBmp.ScanLine[0]; + DstLine := _DstBmp.ScanLine[0]; + for y := 0 to h - 1 do begin + Assert(SrcLine = _SrcBmp.ScanLine[y]); + Assert(DstLine = _DstBmp.ScanLine[y]); + SrcPixel := SrcLine; + DstPixel := DstLine; + for x := 0 to w - 1 do begin + SrcTriple := PdzRgbTriple(SrcPixel); + DstTriple := PdzRgbTriple(DstPixel); + DstTriple.Red := _GammaRed[SrcTriple.Red]; + DstTriple.Green := _GammaGreen[SrcTriple.Green]; + DstTriple.Blue := _GammaBlue[SrcTriple.Blue]; + Inc(SrcPixel, BytesPerPixel); + Inc(DstPixel, BytesPerPixel); + end; + Dec(SrcLine, BytesPerLine); + Dec(DstLine, BytesPerLine); + end; +end; + +procedure TBitmap24_ApplyGamma(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); +const + BytesPerPixel = 3; +var + x: Integer; + y: Integer; + w: Integer; + h: Integer; + SrcLine: PByte; + DstLine: PByte; + SrcPixel: PByte; + DstPixel: PByte; + DstTriple: PdzRgbTriple; + SrcTriple: PdzRgbTriple; + BytesPerLine: Integer; +begin + Assert(Assigned(_SrcBmp)); + Assert(_SrcBmp.PixelFormat = pf24bit); + + _DstBmp.PixelFormat := pf24bit; + w := _SrcBmp.Width; + h := _SrcBmp.Height; + TBitmap_SetSize(_DstBmp, w, h); + + BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; + Assert(BytesPerLine = Graphics.BytesPerScanline(w, BytesPerPixel * 8, 32)); + + SrcLine := _SrcBmp.ScanLine[0]; + DstLine := _DstBmp.ScanLine[0]; + for y := 0 to h - 1 do begin + Assert(SrcLine = _SrcBmp.ScanLine[y]); + Assert(DstLine = _DstBmp.ScanLine[y]); + SrcPixel := SrcLine; + DstPixel := DstLine; + for x := 0 to w - 1 do begin + SrcTriple := PdzRgbTriple(SrcPixel); + DstTriple := PdzRgbTriple(DstPixel); + DstTriple.Red := _Gamma[SrcTriple.Red]; + DstTriple.Green := _Gamma[SrcTriple.Green]; + DstTriple.Blue := _Gamma[SrcTriple.Blue]; + Inc(SrcPixel, BytesPerPixel); + Inc(DstPixel, BytesPerPixel); + end; + Dec(SrcLine, BytesPerLine); + Dec(DstLine, BytesPerLine); + end; +end; + +procedure TBitmap24_ApplyGammaTo8(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); overload; +const + BytesPerPixelInput = 3; + BytesPerPixelOutput = 1; +var + x: Integer; + y: Integer; + w: Integer; + h: Integer; + SrcLine: PByte; + DstLine: PByte; + SrcPixel: PByte; + DstPixel: PByte; + BytesPerLineInput: Integer; + BytesPerLineOutput: Integer; +begin + Assert(Assigned(_SrcBmp)); + Assert(_SrcBmp.PixelFormat = pf24bit); + + w := _SrcBmp.Width; + h := _SrcBmp.Height; + _DstBmp.Assign(nil); + TBitmap_MakeMono8(_DstBmp); + TBitmap_SetSize(_DstBmp, w, h); + + BytesPerLineInput := ((w * 8 * BytesPerPixelInput + 31) and not 31) div 8; + Assert(BytesPerLineInput = Graphics.BytesPerScanline(w, BytesPerPixelInput * 8, 32)); + + BytesPerLineOutput := ((w * 8 * BytesPerPixelOutput + 31) and not 31) div 8; + Assert(BytesPerLineOutput = Graphics.BytesPerScanline(w, BytesPerPixelOutput * 8, 32)); + + SrcLine := _SrcBmp.ScanLine[0]; + DstLine := _DstBmp.ScanLine[0]; + for y := 0 to h - 1 do begin + Assert(SrcLine = _SrcBmp.ScanLine[y]); + Assert(DstLine = _DstBmp.ScanLine[y]); + SrcPixel := SrcLine; + DstPixel := DstLine; + for x := 0 to w - 1 do begin + DstPixel^ := _Gamma[SrcPixel^]; + Inc(SrcPixel, BytesPerPixelInput); + Inc(DstPixel, BytesPerPixelOutput); + end; + Dec(SrcLine, BytesPerLineInput); + Dec(DstLine, BytesPerLineOutput); + end; +end; + +procedure TBitmap8_ApplyGamma(_SrcBmp, _DstBmp: TBitmap; const _Gamma: TGammaCurve); +const + BytesPerPixel = 1; +var + x: Integer; + y: Integer; + w: Integer; + h: Integer; + SrcLine: PByte; + DstLine: PByte; + SrcPixel: PByte; + DstPixel: PByte; + BytesPerLine: Integer; +begin + Assert(Assigned(_SrcBmp)); + Assert(_SrcBmp.PixelFormat = pf8bit); + + _DstBmp.Assign(nil); + _DstBmp.PixelFormat := pf8bit; + w := _SrcBmp.Width; + h := _SrcBmp.Height; + _DstBmp.Palette := MakeGrayPalette; + TBitmap_SetSize(_DstBmp, w, h); + + BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; + Assert(BytesPerLine = Graphics.BytesPerScanline(w, BytesPerPixel * 8, 32)); + + SrcLine := _SrcBmp.ScanLine[0]; + DstLine := _DstBmp.ScanLine[0]; + for y := 0 to h - 1 do begin + Assert(SrcLine = _SrcBmp.ScanLine[y]); + Assert(DstLine = _DstBmp.ScanLine[y]); + SrcPixel := SrcLine; + DstPixel := DstLine; + for x := 0 to w - 1 do begin + DstPixel^ := _Gamma[SrcPixel^]; + Inc(SrcPixel, BytesPerPixel); + Inc(DstPixel, BytesPerPixel); + end; + Dec(SrcLine, BytesPerLine); + Dec(DstLine, BytesPerLine); + end; +end; + +procedure TBitmap8_ApplyMultiGamma(_SrcBmp, _DstBmp: TBitmap; const _GammaArr: array of TGammaCurve); +const + BytesPerPixel = 1; +var + x: Integer; + y: Integer; + w: Integer; + h: Integer; + SrcLine: PByte; + DstLine: PByte; + SrcPixel: PByte; + DstPixel: PByte; + BytesPerLine: Integer; + i: Integer; + Value: Byte; +begin + Assert(Assigned(_SrcBmp)); + Assert(_SrcBmp.PixelFormat = pf8bit); + + _DstBmp.Assign(nil); + _DstBmp.PixelFormat := pf8bit; + w := _SrcBmp.Width; + h := _SrcBmp.Height; + _DstBmp.Palette := MakeGrayPalette; + TBitmap_SetSize(_DstBmp, w, h); + + BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; + Assert(BytesPerLine = Graphics.BytesPerScanline(w, BytesPerPixel * 8, 32)); + + SrcLine := _SrcBmp.ScanLine[0]; + DstLine := _DstBmp.ScanLine[0]; + for y := 0 to h - 1 do begin + Assert(SrcLine = _SrcBmp.ScanLine[y]); + Assert(DstLine = _DstBmp.ScanLine[y]); + SrcPixel := SrcLine; + DstPixel := DstLine; + for x := 0 to w - 1 do begin + Value := SrcPixel^; + for i := Low(_GammaArr) to High(_GammaArr) do + Value := _GammaArr[i][Value]; + DstPixel^ := Value; + Inc(SrcPixel, BytesPerPixel); + Inc(DstPixel, BytesPerPixel); + end; + Dec(SrcLine, BytesPerLine); + Dec(DstLine, BytesPerLine); + end; +end; + // source: https://www.swissdelphicenter.ch/en/showcode.php?id=1948 procedure TBitmap_Sharpen(_SrcBmp, _DstBmp: TBitmap; _Alpha: Single); @@ -1880,7 +2211,7 @@ WorkAreaWidth := _SrcBmp.Width - 2; WorkAreaHeight := _SrcBmp.Height - 2; BytesPerLine := (((WorkAreaWidth + 2) * 8 * BytesPerPixel + 31) and not 31) div 8; -// Assert(BytesPerLine = Graphics.BytesPerScanline(WorkAreaWidth + 2, BytesPerPixel * 8, 32)); + Assert(BytesPerLine = Graphics.BytesPerScanline(WorkAreaWidth + 2, BytesPerPixel * 8, 32)); // Copy first row unchanged SrcRow := _SrcBmp.ScanLine[0]; @@ -2135,6 +2466,8 @@ CenterBrightness: Integer; AvgBrightness: Integer; BytesPerLine: Integer; + AlphaEntrySize: NativeInt; + AlphaPtr: PSingle; begin // sharpening is blending of the current pixel // with the average of the surrounding ones, @@ -2151,8 +2484,10 @@ WorkAreaWidth := _SrcBmp.Width - 2; WorkAreaHeight := _SrcBmp.Height - 2; BytesPerLine := (((WorkAreaWidth + 2) * 8 * BytesPerPixel + 31) and not 31) div 8; -// Assert(BytesPerLine = Graphics.BytesPerScanline(WorkAreaWidth + 2, BytesPerPixel * 8, 32)); + Assert(BytesPerLine = Graphics.BytesPerScanline(WorkAreaWidth + 2, BytesPerPixel * 8, 32)); + AlphaEntrySize := PtrDiff(@(_AlphaMap[0][1]), @(_AlphaMap[0][0])); + SrcRow := _SrcBmp.ScanLine[0]; DstRow := _DstBmp.ScanLine[0]; SrcPixelCenter := PPixel(SrcRow); @@ -2192,10 +2527,12 @@ SrcPixelTop := PPixel(Integer(SrcPixelCenter) + BytesPerLine); SrcPixelBottom := PPixel(Integer(SrcPixelCenter) - BytesPerLine); + AlphaPtr := @(_AlphaMap[Row][0]); for Column := 1 to WorkAreaWidth do begin CenterBrightness := SrcPixelCenter^; - Alpha := _AlphaMap[Row][Column]; + Assert(AlphaPtr = @(_AlphaMap[Row][Column])); + Alpha := AlphaPtr^; Assert((Alpha >= 0) and (Alpha <= 5), Format('Alpha[%d][%d] must be >=1 and <=5', [Row, Column])); // since 0 <= Alpha <= 5 we can be sure that 0 <= Beta <= 1 Beta := Alpha / 5; @@ -2232,6 +2569,8 @@ Inc(SrcPixelCenter); Inc(SrcPixelRight); Inc(SrcPixelBottom); + + AlphaPtr := AddToPtr(AlphaPtr, AlphaEntrySize); end; // copy Last column unchanged @@ -2454,6 +2793,11 @@ Result := Pointer(NativeInt(_Ptr) + _Offset); end; +function PtrDiff(const _Ptr1, _Ptr2: Pointer): NativeInt; inline; +begin + Result := NativeInt(_Ptr1) - NativeInt(_Ptr2); +end; + function TBitmap8_TryCalcAverage(_bmp: TBitmap; _LowCutoff, _HighCutoff: Byte; out _Average: Byte): Boolean; const @@ -2463,9 +2807,10 @@ h: Integer; x: Integer; y: Integer; - ScanLine: PByteArray; + ScanLine: PByte; + Pixel: PByte; Value: Byte; - Sum: Extended; + Sum: Integer; cnt: Integer; BytesPerLine: Integer; begin @@ -2479,18 +2824,20 @@ ScanLine := _bmp.ScanLine[0]; for y := 0 to h - 1 do begin Assert(ScanLine = _bmp.ScanLine[y]); + Pixel := ScanLine; for x := 0 to w - 1 do begin - Value := ScanLine^[x]; + Value := Pixel^; if (Value >= _LowCutoff) and (Value <= _HighCutoff) then begin Sum := Sum + Value; Inc(cnt); end; + Inc(Pixel, BytesPerPixel); end; - ScanLine := AddToPtr(ScanLine, -BytesPerLine); + Dec(ScanLine, BytesPerLine); end; Result := (cnt > 0); if Result then - _Average := Round(Sum / cnt); + _Average := Sum div cnt; end; function TBitmap24_TryCalcAverage(_bmp: TBitmap; _LowCutoff, _HighCutoff: Byte; @@ -2503,14 +2850,12 @@ h: Integer; x: Integer; y: Integer; - ScanLine: PdzRgbTripleArray; + ScanLine: PByte; + Pixel: PByte; Value: Byte; - Sum: Extended; + Sum: Integer; cnt: Integer; BytesPerLine: Integer; -{$IFNDEF SUPPORTS_ENHANCED_RECORDS} - Pixel: ^TdzRgbTriple; -{$ENDIF} begin w := _bmp.Width; h := _bmp.Height; @@ -2522,25 +2867,69 @@ ScanLine := _bmp.ScanLine[0]; for y := 0 to h - 1 do begin Assert(ScanLine = _bmp.ScanLine[y]); + Pixel := ScanLine; for x := 0 to w - 1 do begin {$IFDEF SUPPORTS_ENHANCED_RECORDS} - Value := ScanLine^[x].GetBrightness(_Channel); + Value := PdzRgbTriple(Pixel).GetBrightness(_Channel); {$ELSE} - Pixel := @(ScanLine^[x]); - Value := GetRgbBrightness(Pixel.Red, Pixel.Green, Pixel.Blue, _Channel); + Value := GetRgbBrightness(PdzRgbTriple(Pixel).Red, PdzRgbTriple(Pixel).Green, PdzRgbTriple(Pixel).Blue, _Channel); {$ENDIF} if (Value >= _LowCutoff) and (Value <= _HighCutoff) then begin Sum := Sum + Value; Inc(cnt); end; + Inc(Pixel, BytesPerPixel); end; - ScanLine := AddToPtr(ScanLine, -BytesPerLine); + Dec(ScanLine, BytesPerLine); end; Result := (cnt > 0); if Result then - _Average := Round(Sum / cnt); + _Average := Sum div cnt; end; +function TBitmap24_TryCalcAverageBlue(_bmp: TBitmap; _LowCutoff, _HighCutoff: Byte; + out _Average: Byte): Boolean; +const + BytesPerPixel = SizeOf(TdzRgbTriple); +var + w: Integer; + h: Integer; + x: Integer; + y: Integer; + ScanLine: PByte; + Pixel: PByte; + Value: Byte; + Sum: Integer; + cnt: Integer; + BytesPerLine: Integer; +begin + w := _bmp.Width; + h := _bmp.Height; + BytesPerLine := ((w * 8 * BytesPerPixel + 31) and not 31) div 8; + Assert(BytesPerLine = Graphics.BytesPerScanline(w, BytesPerPixel * 8, 32)); + + Sum := 0; + cnt := 0; + ScanLine := _bmp.ScanLine[0]; + for y := 0 to h - 1 do begin + Assert(ScanLine = _bmp.ScanLine[y]); + Pixel := ScanLine; + for x := 0 to w - 1 do begin + // the first byte of the triple is the blue value + Value := Pixel^; + if (Value >= _LowCutoff) and (Value <= _HighCutoff) then begin + Sum := Sum + Value; + Inc(cnt); + end; + Inc(Pixel, BytesPerPixel); + end; + Dec(ScanLine, BytesPerLine); + end; + Result := (cnt > 0); + if Result then + _Average := Sum div cnt; +end; + function ColorBrightness(_Red, _Green, _Blue: Byte): Byte; begin Result := GetFastLuminance(_Red, _Green, _Blue); @@ -2612,7 +3001,7 @@ inherited Create; FLowCutOff := _LowCutoff; FHighCutOff := _HighCutoff; - FFactor := 256 / (_HighCutoff - _LowCutoff); + FDivisor := _HighCutoff - _LowCutoff; end; procedure TPixelFilterStretch.StretchColor(var _Color: Byte); @@ -2621,10 +3010,8 @@ begin Value := _Color; if (Value > FLowCutOff) and (Value < FHighCutOff) then begin - Value := Round((Value - FLowCutOff) * FFactor); - if Value > 255 then - Value := 255; - _Color := Value; + Value := ((Value - FLowCutOff) * 256) div FDivisor; + _Color := ReduceToByte(Value); end; end; @@ -2656,13 +3043,9 @@ var Value: Integer; begin - Value := _Color + FMoveBy; - if Value < 0 then - _Color := 0 - else if Value > 255 then - _Color := 255 - else - _Color := Value; + Value := _Color; + Value := Value + FMoveBy; + _Color := ReduceToByte(Value); end; procedure TPixelFilterMove.FilterCallback(_x, _y: Integer; var _Pixel: TdzRgbTriple); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |