source: trunk/Packages/bgrabitmap/bgracolorspace.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 4.3 KB
Line 
1unit BGRAColorspace;
2
3{$mode objfpc}{$H+}
4
5interface
6
7uses
8 Classes, SysUtils, BGRABitmapTypes;
9
10type
11 { TCIERGB }
12
13 TCIERGB = packed record
14 //components are between 0 and 1
15 R,G,B,A: single;
16 function ToBGRA: TBGRAPixel;
17 procedure FromBGRA(AValue: TBGRAPixel);
18 function ToExpanded: TExpandedPixel;
19 procedure FromExpanded(AValue: TExpandedPixel);
20 end;
21
22 { TCIEXYZ }
23
24 TCIEXYZ = packed record
25 //components are between 0 and 1
26 X, Y, Z,
27 A: single;
28 function ToRGB: TCIERGB;
29 procedure FromRGB(AValue: TCIERGB);
30 end;
31
32 { TBGRAPixelColorspaceHelper }
33
34 TBGRAPixelColorspaceHelper = record helper(TBGRAPixelHelper) for TBGRAPixel
35 function ToXYZ: TCIEXYZ;
36 procedure FromXYZ(const AValue: TCIEXYZ);
37 end;
38
39 { TExpandedPixelColorspaceHelper }
40
41 TExpandedPixelColorspaceHelper = record helper(TExpandedPixelHelper) for TExpandedPixel
42 function ToXYZ: TCIEXYZ;
43 procedure FromXYZ(const AValue: TCIEXYZ);
44 end;
45
46procedure RGBToXYZ(R, G, B: single; out X, Y, Z: single);
47procedure XYZToRGB(X, Y, Z: single; out R, G, B: single);
48
49implementation
50
51function ClampF(AValue,AMin,AMax: single): single;
52begin
53 if AValue <= AMin then result := AMin
54 else if AValue >= AMax then result := AMax
55 else result := AValue;
56end;
57
58procedure RGBToXYZ(R, G, B: single; out X, Y, Z: single);
59begin
60 // Observer= 2°, Illuminant= D65
61 X := R * 0.4124 + G * 0.3576 + B * 0.1805;
62 Y := R * 0.2126 + G * 0.7152 + B * 0.0722;
63 Z := R * 0.0193 + G * 0.1192 + B * 0.9505;
64end;
65
66procedure XYZToRGB(X, Y, Z: single; out R, G, B: single);
67begin
68 R := ClampF(X * 3.2406 + Y * (-1.5372) + Z * (-0.49), 0, 1);
69 G := ClampF(X * (-0.969) + Y * 1.8758 + Z * 0.0415, 0, 1);
70 B := ClampF(X * 0.0557 + Y * (-0.2040) + Z * 1.0570, 0, 1);
71end;
72
73{ TCIERGB }
74
75function TCIERGB.ToBGRA: TBGRAPixel;
76var
77 redF,greenF,blueF: single;
78begin
79 if r > 0.00313 then
80 redF := 1.055 * Power(r, 1 / 2.4) - 0.055
81 else
82 redF := 12.92 * r;
83 if g > 0.00313 then
84 greenF := 1.055 * Power(g, 1 / 2.4) - 0.055
85 else
86 greenF := 12.92 * g;
87 if b > 0.00313 then
88 blueF := 1.055 * Power(b, 1 / 2.4) - 0.055
89 else
90 blueF := 12.92 * b;
91
92 result.red := round(clampF(redF,0,1)*255);
93 result.green := round(clampF(greenF,0,1)*255);
94 result.blue := round(clampF(blueF,0,1)*255);
95 result.alpha := round(clampF(A,0,1)*255);
96end;
97
98procedure TCIERGB.FromBGRA(AValue: TBGRAPixel);
99begin
100 R := AValue.red/255;
101 G := AValue.green/255;
102 B := AValue.blue/255;
103 A := AValue.alpha/255;
104
105 if R > 0.04045 then
106 R := Power((R + 0.055) / 1.055, 2.4)
107 else
108 R := R / 12.92;
109 if G > 0.04045 then
110 G := Power((G + 0.055) / 1.055, 2.4)
111 else
112 G := G / 12.92;
113 if B > 0.04045 then
114 B := Power((B + 0.055) / 1.055, 2.4)
115 else
116 B := B / 12.92;
117end;
118
119function TCIERGB.ToExpanded: TExpandedPixel;
120begin
121 result.red := round(ClampF(R,0,1)*65535);
122 result.green := round(ClampF(G,0,1)*65535);
123 result.blue := round(ClampF(B,0,1)*65535);
124 result.alpha := round(ClampF(A,0,1)*65535);
125end;
126
127procedure TCIERGB.FromExpanded(AValue: TExpandedPixel);
128begin
129 R := AValue.red/65535;
130 G := AValue.green/65535;
131 B := AValue.blue/65535;
132 A := AValue.alpha/65535;
133end;
134
135{ TCIEXYZ }
136
137function TCIEXYZ.ToBGRA: TBGRAPixel;
138begin
139 result.FromXYZ(self);
140end;
141
142procedure TCIEXYZ.FromBGRA(AValue: TBGRAPixel);
143begin
144 self := AValue.ToXYZ;
145end;
146
147function TCIEXYZ.ToExpanded: TExpandedPixel;
148begin
149 result.FromXYZ(self);
150end;
151
152procedure TCIEXYZ.FromExpanded(AValue: TExpandedPixel);
153begin
154 self := AValue.ToXYZ;
155end;
156
157function TCIEXYZ.ToRGB: TCIERGB;
158begin
159 XYZToRGB(X,Y,Z, result.R,result.G,result.B);
160 result.A := A;
161end;
162
163procedure TCIEXYZ.FromRGB(AValue: TCIERGB);
164begin
165 RGBToXYZ(AValue.R,AValue.G,AValue.B, X,Y,Z);
166 A := AValue.A;
167end;
168
169{ TExpandedPixelColorspaceHelper }
170
171function TExpandedPixelColorspaceHelper.ToXYZ: TCIEXYZ;
172var RGB: TCIERGB;
173begin
174 RGB.FromExpanded(Self);
175 result.FromRGB(RGB);
176end;
177
178procedure TExpandedPixelColorspaceHelper.FromXYZ(const AValue: TCIEXYZ);
179var redF,greenF,blueF: single;
180begin
181 self := AValue.ToRGB.ToExpanded;
182end;
183
184{ TBGRAPixelColorspaceHelper }
185
186function TBGRAPixelColorspaceHelper.ToXYZ: TCIEXYZ;
187var RGB: TCIERGB;
188begin
189 RGB.FromBGRA(Self);
190 result.FromRGB(RGB);
191end;
192
193procedure TBGRAPixelColorspaceHelper.FromXYZ(const AValue: TCIEXYZ);
194begin
195 self := AValue.ToRGB.ToBGRA;
196end;
197
198end.
199
Note: See TracBrowser for help on using the repository browser.