unit sepiaf05; interface uses Windows, Graphics; type TRGB = record R: Integer; {Red } G: Integer; {Green} B: Integer; {Blue } end; TRGBColor = record R: Extended; {Red : 0..1} G: Extended; {Green : 0..1} B: Extended; {Blue : 0..1} end; TYUVColor = record Y: Extended; {Brightness : 0..1 } U: Extended; {Color Difference : -0.5..0.5 } V: Extended; {Color Difference : -0.5..0.5 } end; TRGBTripleArray = array[0 .. $FFFF] of TRGBTriple; PRGBTripleArray = ^TRGBTripleArray; function NormalizeRGB(C: TRGBColor): TRGBTriple; function YUV2RGB(C: TYUVColor): TRGBColor; procedure SepiaFilter(Bmp: TBitmap); implementation const YPrec = 1 shl 16; XR: Cardinal = Trunc(0.299 * YPrec * (256 / 255) + 0.5); XG: Cardinal = Trunc(0.587 * YPrec * (256 / 255) + 0.5); XB: Cardinal = Trunc(0.114 * YPrec * (256 / 255) + 0.5); procedure SepiaFilter(Bmp: TBitmap); var P: PRGBTripleArray; X, Y: Integer; YUVColor: TYUVColor; Table: array[0 .. YPrec] of RGBTriple; begin YUVColor.U := -0.080; //-0.091 YUVColor.V := 0.071; //0.056 for Y := 0 to YPrec do begin YUVColor.Y := Y / YPrec; Table[Y] := NormalizeRGB(YUV2RGB(YUVColor)); end; for Y := 0 to Bmp.Height - 1 do begin P := Bmp.Scanline[Y]; for X := 0 to Bmp.Width - 1 do begin P[X] := Table[(XB * P[X].rgbtBlue + XG * P[X].rgbtGreen + XR * P[X].rgbtRed) shr 8]; end; end; end; function NormalizeRGB(C: TRGBColor): TRGBTriple; begin if C.R > 1 then C.R := 1 else if C.R < 0 then C.R := 0; if C.G > 1 then C.G := 1 else if C.G < 0 then C.G := 0; if C.B > 1 then C.B := 1 else if C.B < 0 then C.B := 0; Result.rgbtBlue := Trunc(C.B * 255 + 0.5); Result.rgbtGreen := Trunc(C.G * 255 + 0.5); Result.rgbtRed := Trunc(C.R * 255 + 0.5); end; function YUV2RGB(C: TYUVColor): TRGBColor; begin Result.R := C.Y + 1.4026 * C.V; Result.G := C.Y - 0.3444 * C.U - 0.7114 * C.V; result.B := C.Y + 1.7330 * C.U; end; end.