Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(372)

Side by Side Diff: third_party/qcms/src/transform_util.c

Issue 1214343002: [qcms] Keep the output of the TRC between 0 and 1 (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase to HEAD. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « third_party/qcms/src/transform_util.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // qcms 1 // qcms
2 // Copyright (C) 2009 Mozilla Foundation 2 // Copyright (C) 2009 Mozilla Foundation
3 // 3 //
4 // Permission is hereby granted, free of charge, to any person obtaining 4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the "Software"), 5 // a copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation 6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense, 7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the Softwar e 8 // and/or sell copies of the Software, and to permit persons to whom the Softwar e
9 // is furnished to do so, subject to the following conditions: 9 // is furnished to do so, subject to the following conditions:
10 // 10 //
(...skipping 18 matching lines...) Expand all
29 #include "matrix.h" 29 #include "matrix.h"
30 30
31 #if !defined(INFINITY) 31 #if !defined(INFINITY)
32 #define INFINITY HUGE_VAL 32 #define INFINITY HUGE_VAL
33 #endif 33 #endif
34 34
35 #define PARAMETRIC_CURVE_TYPE 0x70617261 //'para' 35 #define PARAMETRIC_CURVE_TYPE 0x70617261 //'para'
36 36
37 /* value must be a value between 0 and 1 */ 37 /* value must be a value between 0 and 1 */
38 //XXX: is the above a good restriction to have? 38 //XXX: is the above a good restriction to have?
39 float lut_interp_linear(double value, uint16_t *table, size_t length) 39 // the output range of this function is 0..1
40 float lut_interp_linear(double input_value, uint16_t *table, size_t length)
40 { 41 {
41 int upper, lower; 42 int upper, lower;
42 » value = value * (length - 1); // scale to length of the array 43 » float value;
43 » upper = ceil(value); 44 » input_value = input_value * (length - 1); // scale to length of the arra y
44 » lower = floor(value); 45 » upper = ceil(input_value);
46 » lower = floor(input_value);
45 //XXX: can we be more performant here? 47 //XXX: can we be more performant here?
46 » value = table[upper]*(1. - (upper - value)) + table[lower]*(upper - valu e); 48 » value = table[upper]*(1. - (upper - input_value)) + table[lower]*(upper - input_value);
47 /* scale the value */ 49 /* scale the value */
48 » return value * (1./65535.); 50 » return value * (1.f/65535.f);
49 } 51 }
50 52
51 /* same as above but takes and returns a uint16_t value representing a range fro m 0..1 */ 53 /* same as above but takes and returns a uint16_t value representing a range fro m 0..1 */
52 uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t lengt h) 54 uint16_t lut_interp_linear16(uint16_t input_value, uint16_t *table, size_t lengt h)
53 { 55 {
54 /* Start scaling input_value to the length of the array: 65535*(length-1 ). 56 /* Start scaling input_value to the length of the array: 65535*(length-1 ).
55 * We'll divide out the 65535 next */ 57 * We'll divide out the 65535 next */
56 uintptr_t value = (input_value * (length - 1)); 58 uintptr_t value = (input_value * (length - 1));
57 uint32_t upper = (value + 65534) / 65535; /* equivalent to ceil(value/65 535) */ 59 uint32_t upper = (value + 65534) / 65535; /* equivalent to ceil(value/65 535) */
58 uint32_t lower = value / 65535; /* equivalent to floor(value/6 5535) */ 60 uint32_t lower = value / 65535; /* equivalent to floor(value/6 5535) */
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 uint32_t upper = (value + 4095) / 4096; /* equivalent to ceil(value/4096 ) */ 115 uint32_t upper = (value + 4095) / 4096; /* equivalent to ceil(value/4096 ) */
114 uint32_t lower = value / 4096; /* equivalent to floor(value/40 96) */ 116 uint32_t lower = value / 4096; /* equivalent to floor(value/40 96) */
115 uint32_t interp = value % 4096; 117 uint32_t interp = value % 4096;
116 118
117 value = (table[upper]*(interp) + table[lower]*(4096 - interp))/4096; // 0..4096*4096 119 value = (table[upper]*(interp) + table[lower]*(4096 - interp))/4096; // 0..4096*4096
118 120
119 return value; 121 return value;
120 } 122 }
121 #endif 123 #endif
122 124
123 void compute_curve_gamma_table_type1(float gamma_table[256], double gamma) 125 void compute_curve_gamma_table_type1(float gamma_table[256], uint16_t gamma)
126 {
127 » unsigned int i;
128 » float gamma_float = u8Fixed8Number_to_float(gamma);
129 » for (i = 0; i < 256; i++) {
130 » » // 0..1^(0..255 + 255/256) will always be between 0 and 1
131 » » gamma_table[i] = pow(i/255., gamma_float);
robert.bradford 2015/07/01 12:10:50 I don't think we need to do the calculation in dou
Noel Gordon 2015/07/02 05:51:49 Resolved by your subsequent measurements: use pow.
132 » }
133 }
134
135 void compute_curve_gamma_table_type2(float gamma_table[256], uint16_t *table, si ze_t length)
124 { 136 {
125 unsigned int i; 137 unsigned int i;
126 for (i = 0; i < 256; i++) { 138 for (i = 0; i < 256; i++) {
127 gamma_table[i] = pow(i/255., gamma);
128 }
129 }
130
131 void compute_curve_gamma_table_type2(float gamma_table[256], uint16_t *table, in t length)
132 {
133 unsigned int i;
134 for (i = 0; i < 256; i++) {
135 gamma_table[i] = lut_interp_linear(i/255., table, length); 139 gamma_table[i] = lut_interp_linear(i/255., table, length);
136 } 140 }
137 } 141 }
138 142
139 void compute_curve_gamma_table_type_parametric(float gamma_table[256], float par ameter[7], int count) 143 void compute_curve_gamma_table_type_parametric(float gamma_table[256], float par ameter[7], int count)
140 { 144 {
141 size_t X; 145 size_t X;
142 float interval; 146 float interval;
143 float a, b, c, e, f; 147 float a, b, c, e, f;
144 float y = parameter[0]; 148 float y = parameter[0];
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 } else { 184 } else {
181 assert(0 && "invalid parametric function type."); 185 assert(0 && "invalid parametric function type.");
182 a = 1; 186 a = 1;
183 b = 0; 187 b = 0;
184 c = 0; 188 c = 0;
185 e = 0; 189 e = 0;
186 f = 0; 190 f = 0;
187 interval = -INFINITY; 191 interval = -INFINITY;
188 } 192 }
189 for (X = 0; X < 256; X++) { 193 for (X = 0; X < 256; X++) {
190 if (X >= interval) { 194 if (X >= interval) {
Noel Gordon 2015/07/07 08:00:55 Oh and spot the bug: interval is a float on 0.0 ..
191 // XXX The equations are not exactly as definied in the spec but are 195 // XXX The equations are not exactly as definied in the spec but are
192 // algebraic equivilent. 196 // algebraic equivilent.
193 // TODO Should division by 255 be for the whole expressi on. 197 // TODO Should division by 255 be for the whole expressi on.
194 gamma_table[X] = pow(a * X / 255. + b, y) + c + e; 198 gamma_table[X] = clamp_float(pow(a * X / 255. + b, y) + c + e);
195 } else { 199 } else {
196 gamma_table[X] = c * X / 255. + f; 200 gamma_table[X] = clamp_float(c * X / 255. + f);
197 } 201 }
198 } 202 }
199 } 203 }
200 204
201 void compute_curve_gamma_table_type0(float gamma_table[256]) 205 void compute_curve_gamma_table_type0(float gamma_table[256])
202 { 206 {
203 unsigned int i; 207 unsigned int i;
204 for (i = 0; i < 256; i++) { 208 for (i = 0; i < 256; i++) {
205 gamma_table[i] = i/255.; 209 gamma_table[i] = i/255.;
206 } 210 }
207 } 211 }
208 212
209
210 float clamp_float(float a) 213 float clamp_float(float a)
211 { 214 {
212 if (a > 1.) 215 » /* One would naturally write this function as the following:
213 return 1.; 216 » if (a > 1.)
214 else if (a < 0) 217 » » return 1.;
215 return 0; 218 » else if (a < 0)
216 else 219 » » return 0;
217 return a; 220 » else
221 » » return a;
222
223 » However, that version will let NaNs pass through which is undesirable
224 » for most consumers.
225 » */
226
227 » if (a > 1.)
228 » » return 1.;
229 » else if (a >= 0)
230 » » return a;
231 » else // a < 0 or a is NaN
232 » » return 0;
218 } 233 }
219 234
220 unsigned char clamp_u8(float v) 235 unsigned char clamp_u8(float v)
221 { 236 {
222 if (v > 255.) 237 if (v > 255.)
223 return 255; 238 return 255;
224 else if (v < 0) 239 else if (v < 0)
225 return 0; 240 return 0;
226 else 241 else
227 return floor(v+.5); 242 return floor(v+.5);
(...skipping 28 matching lines...) Expand all
256 271
257 if (!TRC) return NULL; 272 if (!TRC) return NULL;
258 gamma_table = malloc(sizeof(float)*256); 273 gamma_table = malloc(sizeof(float)*256);
259 if (gamma_table) { 274 if (gamma_table) {
260 if (TRC->type == PARAMETRIC_CURVE_TYPE) { 275 if (TRC->type == PARAMETRIC_CURVE_TYPE) {
261 compute_curve_gamma_table_type_parametric(gamma_table, T RC->parameter, TRC->count); 276 compute_curve_gamma_table_type_parametric(gamma_table, T RC->parameter, TRC->count);
262 } else { 277 } else {
263 if (TRC->count == 0) { 278 if (TRC->count == 0) {
264 compute_curve_gamma_table_type0(gamma_table); 279 compute_curve_gamma_table_type0(gamma_table);
265 } else if (TRC->count == 1) { 280 } else if (TRC->count == 1) {
266 » » » » compute_curve_gamma_table_type1(gamma_table, u8F ixed8Number_to_float(TRC->data[0])); 281 » » » » compute_curve_gamma_table_type1(gamma_table, TRC ->data[0]);
267 } else { 282 } else {
268 compute_curve_gamma_table_type2(gamma_table, TRC ->data, TRC->count); 283 compute_curve_gamma_table_type2(gamma_table, TRC ->data, TRC->count);
269 } 284 }
270 } 285 }
271 } 286 }
272 287
273 validate_gamma_table(gamma_table); 288 validate_gamma_table(gamma_table);
274 289
275 return gamma_table; 290 return gamma_table;
276 } 291 }
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 // measurement or data, however it is what lcms uses . 612 // measurement or data, however it is what lcms uses .
598 *output_gamma_lut_length = trc->count; 613 *output_gamma_lut_length = trc->count;
599 if (*output_gamma_lut_length < 256) 614 if (*output_gamma_lut_length < 256)
600 *output_gamma_lut_length = 256; 615 *output_gamma_lut_length = 256;
601 616
602 *output_gamma_lut = invert_lut(trc->data, trc->count, *o utput_gamma_lut_length); 617 *output_gamma_lut = invert_lut(trc->data, trc->count, *o utput_gamma_lut_length);
603 } 618 }
604 } 619 }
605 620
606 } 621 }
OLDNEW
« no previous file with comments | « third_party/qcms/src/transform_util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698