source: trunk/Packages/bgrabitmap/bgracolorint.pas

Last change on this file was 2, checked in by chronos, 5 years ago
File size: 8.8 KB
Line 
1unit BGRAColorInt;
2
3{$mode objfpc}{$H+}
4{$ifdef CPUI386}
5 {$define BGRACOLORINT_USEASM}
6{$endif}
7{$ifdef DARWIN}
8 {$undef BGRACOLORINT_USEASM}
9{$endif}
10
11interface
12
13uses
14 BGRABitmapTypes;
15
16type
17 TColorInt65536 = packed record
18 r,g,b,a: integer;
19 end;
20
21function ColorInt65536(r,g,b,a: integer): TColorInt65536; inline; overload;
22function ColorInt65536(r,g,b: integer): TColorInt65536; inline; overload;
23function ColorFToColorInt65536(colorF: TColorF): TColorInt65536; inline;
24function ColorInt65536ToColorF(color: TColorInt65536): TColorF;
25operator +(const color1,color2: TColorInt65536): TColorInt65536; inline;
26operator *(const color1,color2: TColorInt65536): TColorInt65536;
27operator *(const color1: TColorInt65536; factor65536: integer): TColorInt65536;
28function ColorIntToBGRA(const AColor: TColorInt65536; AGammaCompression: boolean = false): TBGRAPixel;
29function BGRAToColorInt(const AColor: TBGRAPixel; AGammaExpansion: boolean = false): TColorInt65536;
30function BGRAToColorIntMultiply(const color1: TBGRAPixel; const color2: TColorInt65536): TColorInt65536;
31
32implementation
33
34function ColorInt65536(r, g, b, a: integer): TColorInt65536;
35begin
36 result.r := r;
37 result.g := g;
38 result.b := b;
39 result.a := a;
40end;
41
42function ColorInt65536(r, g, b: integer): TColorInt65536;
43begin
44 result.r := r;
45 result.g := g;
46 result.b := b;
47 result.a := 65536;
48end;
49
50function ColorFToColorInt65536(colorF: TColorF): TColorInt65536;
51begin
52 result.r := round(colorF[1]*65536);
53 result.g := round(colorF[2]*65536);
54 result.b := round(colorF[3]*65536);
55 result.a := round(colorF[4]*65536);
56end;
57
58function ColorInt65536ToColorF(color: TColorInt65536): TColorF;
59const oneOver65536 = 1/65536;
60begin
61 result[1] := color.r*oneOver65536;
62 result[2] := color.g*oneOver65536;
63 result[3] := color.b*oneOver65536;
64 result[4] := color.a*oneOver65536;
65end;
66
67operator+(const color1, color2: TColorInt65536): TColorInt65536;
68begin
69 result.r := color1.r+color2.r;
70 result.g := color1.g+color2.g;
71 result.b := color1.b+color2.b;
72 result.a := color1.a+color2.a;
73end;
74
75operator*(const color1, color2: TColorInt65536): TColorInt65536;
76{$ifdef BGRACOLORINT_USEASM} {$asmmode intel} assembler;
77 asm
78 push edx
79 push ebx
80 push esi
81 mov ebx, Color1
82 mov esi, Color2
83 //ecx = @result
84
85 mov eax, [ebx] //r
86 imul [esi]
87 shl edx, 16
88 shr eax, 16
89 or edx, eax
90 mov [ecx], edx
91
92 mov eax, [ebx+4] //g
93 imul [esi+4]
94 shl edx, 16
95 shr eax, 16
96 or edx, eax
97 mov [ecx+4], edx
98
99 mov eax, [ebx+8] //b
100 imul [esi+8]
101 shl edx, 16
102 shr eax, 16
103 or edx, eax
104 mov [ecx+8], edx
105
106 mov eax, [ebx+12] //a
107 imul [esi+12]
108 shl edx, 16
109 shr eax, 16
110 or edx, eax
111 mov [ecx+12], edx
112
113 pop esi
114 pop ebx
115 pop edx
116 end;
117{$ELSE}
118begin
119 result.r := int64(color1.r)*color2.r shr 16;
120 result.g := int64(color1.g)*color2.g shr 16;
121 result.b := int64(color1.b)*color2.b shr 16;
122 result.a := int64(color1.a)*color2.a shr 16;
123end;
124{$ENDIF}
125
126operator*(const color1: TColorInt65536; factor65536: integer): TColorInt65536;
127{$ifdef BGRACOLORINT_USEASM} {$asmmode intel} assembler;
128 asm
129 push edx
130 push ebx
131 push esi
132 mov ebx, Color1
133 mov esi, factor65536
134 //ecx = @result
135
136 mov eax, [ebx] //r
137 imul esi
138 shl edx, 16
139 shr eax, 16
140 or edx, eax
141 mov [ecx], edx
142
143 mov eax, [ebx+4] //g
144 imul esi
145 shl edx, 16
146 shr eax, 16
147 or edx, eax
148 mov [ecx+4], edx
149
150 mov eax, [ebx+8] //b
151 imul esi
152 shl edx, 16
153 shr eax, 16
154 or edx, eax
155 mov [ecx+8], edx
156
157 mov eax, [ebx+12] //a
158 imul esi
159 shl edx, 16
160 shr eax, 16
161 or edx, eax
162 mov [ecx+12], edx
163
164 pop esi
165 pop ebx
166 pop edx
167 end;
168{$else}
169var prod: int64;
170begin
171 prod := int64(color1.r)*factor65536;
172 if prod >= 0 then result.r := prod shr 16
173 else result.r := -((-prod) shr 16);
174 prod := int64(color1.g)*factor65536;
175 if prod >= 0 then result.g := prod shr 16
176 else result.g := -((-prod) shr 16);
177 prod := int64(color1.b)*factor65536;
178 if prod >= 0 then result.b := prod shr 16
179 else result.b := -((-prod) shr 16);
180 prod := int64(color1.a)*factor65536;
181 if prod >= 0 then result.a := prod shr 16
182 else result.a := -((-prod) shr 16);
183end;
184{$endif}
185
186function BGRAToColorInt(const AColor: TBGRAPixel; AGammaExpansion: boolean): TColorInt65536;
187begin
188 if AGammaExpansion then
189 begin
190 result.r := GammaExpansionTab[AColor.red] + (AColor.red shr 7);
191 result.g := GammaExpansionTab[AColor.green] + (AColor.green shr 7);
192 result.b := GammaExpansionTab[AColor.blue] + (AColor.blue shr 7);
193 end else
194 begin
195 result.r := AColor.red shl 8 + AColor.red + (AColor.red shr 7);
196 result.g := AColor.green shl 8 + AColor.green + (AColor.green shr 7);
197 result.b := AColor.blue shl 8 + AColor.blue + (AColor.blue shr 7);
198 end;
199 result.a := AColor.alpha shl 8 + AColor.alpha+ (AColor.alpha shr 7);
200end;
201
202function BGRAToColorIntMultiply(const color1: TBGRAPixel;
203 const color2: TColorInt65536): TColorInt65536;
204{$ifdef BGRACOLORINT_USEASM} {$asmmode intel} assembler;
205 asm
206 push ebx
207 push esi
208
209 mov esi, Color2
210 mov ebx, result
211 mov ecx, [Color1]
212
213 mov eax, ecx
214 shr eax, TBGRAPixel_RedShift
215 and eax, 255
216 mov edx, eax
217 shr edx, 7
218 add eax, edx
219 imul [esi]
220 shl edx, 24
221 shr eax, 8
222 or edx, eax
223 mov [ebx], edx
224
225 mov eax, ecx
226 shr eax, TBGRAPixel_GreenShift
227 and eax, 255
228 mov edx, eax
229 shr edx, 7
230 add eax, edx
231 imul [esi+4]
232 shl edx, 24
233 shr eax, 8
234 or edx, eax
235 mov [ebx+4], edx
236
237 mov eax, ecx
238 shr eax, TBGRAPixel_BlueShift
239 and eax, 255
240 mov edx, eax
241 shr edx, 7
242 add eax, edx
243 imul [esi+8]
244 shl edx, 24
245 shr eax, 8
246 or edx, eax
247 mov [ebx+8], edx
248
249 mov eax, ecx
250 shr eax, TBGRAPixel_AlphaShift
251 and eax, 255
252 mov edx, eax
253 shr edx, 7
254 add eax, edx
255 imul [esi+12]
256 shl edx, 24
257 shr eax, 8
258 or edx, eax
259 mov [ebx+12], edx
260
261 pop esi
262 pop ebx
263 end;
264{$ELSE}
265begin
266 result.r := int64(color2.r)*(color1.red shr 7+color1.red) shr 8;
267 result.g := int64(color2.g)*(color1.green shr 7+color1.green) shr 8;
268 result.b := int64(color2.b)*(color1.blue shr 7+color1.blue) shr 8;
269 result.a := int64(color2.a)*(color1.alpha shr 7+color1.alpha) shr 8;
270end;
271{$ENDIF}
272
273function ColorIntToBGRA(const AColor: TColorInt65536; AGammaCompression: boolean): TBGRAPixel;
274var maxValue,invMaxValue,r,g,b: integer;
275begin
276 if AColor.a <= 0 then
277 result.alpha := 0;
278 if AColor.a >= 65536 then
279 result.alpha := 255
280 else
281 result.alpha := AColor.a shr 8 - (AColor.a shr 15);
282
283 maxValue := AColor.r;
284 if AColor.g > maxValue then maxValue := AColor.g;
285 if AColor.b > maxValue then maxValue := AColor.b;
286
287 if maxValue <= 0 then
288 begin
289 result.red := 0;
290 result.green := 0;
291 result.blue := 0;
292 exit;
293 end;
294
295 if AGammaCompression then
296 begin
297 if maxValue <= 65535 then
298 begin
299 if AColor.r <= 0 then result.red := 0 else
300 result.red := GammaCompressionTab[AColor.r - (AColor.r shr 15)];
301
302 if AColor.g <= 0 then result.green := 0 else
303 result.green :=GammaCompressionTab[AColor.g - (AColor.g shr 15)];
304
305 if AColor.b <= 0 then result.blue := 0 else
306 result.blue := GammaCompressionTab[AColor.b - (AColor.b shr 15)];
307 exit;
308 end;
309
310 invMaxValue := (1073741824+maxValue-1) div maxValue;
311
312 maxValue := (maxValue-65535) shr 1;
313 if AColor.r < 0 then r := maxValue else
314 r := AColor.r*invMaxValue shr 14 + maxValue;
315 if AColor.g < 0 then g := maxValue else
316 g := AColor.g*invMaxValue shr 14 + maxValue;
317 if AColor.b < 0 then b := maxValue else
318 b := AColor.b*invMaxValue shr 14 + maxValue;
319
320 if r >= 65535 then result.red := 255 else
321 result.red := GammaCompressionTab[r];
322 if g >= 65535 then result.green := 255 else
323 result.green := GammaCompressionTab[g];
324 if b >= 65535 then result.blue := 255 else
325 result.blue := GammaCompressionTab[b];
326 end else
327 begin
328 if maxValue <= 65535 then
329 begin
330 if AColor.r <= 0 then result.red := 0 else
331 result.red := AColor.r shr 8 - (AColor.r shr 15);
332
333 if AColor.g <= 0 then result.green := 0 else
334 result.green := AColor.g shr 8 - (AColor.g shr 15);
335
336 if AColor.b <= 0 then result.blue := 0 else
337 result.blue := AColor.b shr 8 - (AColor.b shr 15);
338 exit;
339 end;
340
341 invMaxValue := (1073741824+maxValue-1) div maxValue;
342
343 maxValue := (maxValue-65535) shr 9;
344 if AColor.r < 0 then r := maxValue else
345 r := AColor.r*invMaxValue shr 22 + maxValue;
346 if AColor.g < 0 then g := maxValue else
347 g := AColor.g*invMaxValue shr 22 + maxValue;
348 if AColor.b < 0 then b := maxValue else
349 b := AColor.b*invMaxValue shr 22 + maxValue;
350
351 if r >= 255 then result.red := 255 else
352 result.red := r;
353 if g >= 255 then result.green := 255 else
354 result.green := g;
355 if b >= 255 then result.blue := 255 else
356 result.blue := b;
357 end;
358end;
359
360
361end.
362
Note: See TracBrowser for help on using the repository browser.