Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 |
|
Matt Giuca
2015/07/01 01:46:59
The upstream patch says "range of this functions".
Noel Gordon
2015/07/01 04:12:22
well "... the output range of this functions is 0.
Matt Giuca
2015/07/01 07:10:50
If this were an ordinary code review, I'd tell the
| |
| 40 float lut_interp_linear(double input_value, uint16_t *table, size_t length) | |
|
Matt Giuca
2015/07/01 01:46:59
Why is length size_t instead of int? (The upstream
Noel Gordon
2015/07/01 04:12:22
Local bug fix, upstream was advised iirc and is st
Matt Giuca
2015/07/01 07:10:50
Acknowledged.
| |
| 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 Loading... | |
| 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 | |
|
Matt Giuca
2015/07/01 01:46:59
The upstream patch has 16 spaces here, not 2 tabs.
Noel Gordon
2015/07/01 04:12:22
Acknowledged. The qcms story re tabs and spaces i
Matt Giuca
2015/07/01 07:10:50
Absolutely ... if you were writing code for Mozill
| |
| 131 » » gamma_table[i] = pow(i/255., gamma_float); | |
| 132 » } | |
| 133 } | |
| 134 | |
| 135 void compute_curve_gamma_table_type2(float gamma_table[256], uint16_t *table, si ze_t length) | |
|
Matt Giuca
2015/07/01 01:46:59
The upstream patch doesn't change "int length" to
Noel Gordon
2015/07/01 04:12:22
Refer back to the reply for line 40, we want size_
Matt Giuca
2015/07/01 07:10:50
Acknowledged.
| |
| 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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) { |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |