 Chromium Code Reviews
 Chromium Code Reviews Issue 1214343002:
  [qcms] Keep the output of the TRC between 0 and 1  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master
    
  
    Issue 1214343002:
  [qcms] Keep the output of the TRC between 0 and 1  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/src.git@master| 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 |