| OLD | NEW |
| 1 /* vim: set ts=8 sw=8 noexpandtab: */ | 1 /* vim: set ts=8 sw=8 noexpandtab: */ |
| 2 // qcms | 2 // qcms |
| 3 // Copyright (C) 2009 Mozilla Corporation | 3 // Copyright (C) 2009 Mozilla Corporation |
| 4 // Copyright (C) 1998-2007 Marti Maria | 4 // Copyright (C) 1998-2007 Marti Maria |
| 5 // | 5 // |
| 6 // Permission is hereby granted, free of charge, to any person obtaining | 6 // Permission is hereby granted, free of charge, to any person obtaining |
| 7 // a copy of this software and associated documentation files (the "Software"), | 7 // a copy of this software and associated documentation files (the "Software"), |
| 8 // to deal in the Software without restriction, including without limitation | 8 // to deal in the Software without restriction, including without limitation |
| 9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, | 9 // the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| 10 // and/or sell copies of the Software, and to permit persons to whom the Softwar
e | 10 // and/or sell copies of the Software, and to permit persons to whom the Softwar
e |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 174 // Normalize | 174 // Normalize |
| 175 return matrix_multiply(chad_inv, matrix_multiply(cone, chad)); | 175 return matrix_multiply(chad_inv, matrix_multiply(cone, chad)); |
| 176 } | 176 } |
| 177 | 177 |
| 178 /* from lcms: cmsAdaptionMatrix */ | 178 /* from lcms: cmsAdaptionMatrix */ |
| 179 // Returns the final chrmatic adaptation from illuminant FromIll to Illuminant T
oIll | 179 // Returns the final chrmatic adaptation from illuminant FromIll to Illuminant T
oIll |
| 180 // Bradford is assumed | 180 // Bradford is assumed |
| 181 static struct matrix | 181 static struct matrix |
| 182 adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illumi
nation) | 182 adaption_matrix(struct CIE_XYZ source_illumination, struct CIE_XYZ target_illumi
nation) |
| 183 { | 183 { |
| 184 #if defined (_MSC_VER) |
| 185 #pragma warning(push) |
| 186 /* Disable double to float truncation warning 4305 */ |
| 187 #pragma warning(disable:4305) |
| 188 #endif |
| 184 struct matrix lam_rigg = {{ // Bradford matrix | 189 struct matrix lam_rigg = {{ // Bradford matrix |
| 185 { 0.8951, 0.2664, -0.1614 }, | 190 { 0.8951, 0.2664, -0.1614 }, |
| 186 { -0.7502, 1.7135, 0.0367 }, | 191 { -0.7502, 1.7135, 0.0367 }, |
| 187 { 0.0389, -0.0685, 1.0296 } | 192 { 0.0389, -0.0685, 1.0296 } |
| 188 }}; | 193 }}; |
| 194 #if defined (_MSC_VER) |
| 195 /* Restore warnings */ |
| 196 #pragma warning(pop) |
| 197 #endif |
| 189 return compute_chromatic_adaption(source_illumination, target_illuminati
on, lam_rigg); | 198 return compute_chromatic_adaption(source_illumination, target_illuminati
on, lam_rigg); |
| 190 } | 199 } |
| 191 | 200 |
| 192 /* from lcms: cmsAdaptMatrixToD50 */ | 201 /* from lcms: cmsAdaptMatrixToD50 */ |
| 193 static struct matrix adapt_matrix_to_D50(struct matrix r, qcms_CIE_xyY source_wh
ite_pt) | 202 static struct matrix adapt_matrix_to_D50(struct matrix r, qcms_CIE_xyY source_wh
ite_pt) |
| 194 { | 203 { |
| 195 struct CIE_XYZ Dn; | 204 struct CIE_XYZ Dn; |
| 196 struct matrix Bradford; | 205 struct matrix Bradford; |
| 197 | 206 |
| 198 if (source_white_pt.y == 0.0) | 207 if (source_white_pt.y == 0.0) |
| (...skipping 24 matching lines...) Expand all Loading... |
| 223 profile->greenColorant.Z = double_to_s15Fixed16Number(colorants.m[2][1])
; | 232 profile->greenColorant.Z = double_to_s15Fixed16Number(colorants.m[2][1])
; |
| 224 | 233 |
| 225 profile->blueColorant.X = double_to_s15Fixed16Number(colorants.m[0][2]); | 234 profile->blueColorant.X = double_to_s15Fixed16Number(colorants.m[0][2]); |
| 226 profile->blueColorant.Y = double_to_s15Fixed16Number(colorants.m[1][2]); | 235 profile->blueColorant.Y = double_to_s15Fixed16Number(colorants.m[1][2]); |
| 227 profile->blueColorant.Z = double_to_s15Fixed16Number(colorants.m[2][2]); | 236 profile->blueColorant.Z = double_to_s15Fixed16Number(colorants.m[2][2]); |
| 228 | 237 |
| 229 return true; | 238 return true; |
| 230 } | 239 } |
| 231 | 240 |
| 232 #if 0 | 241 #if 0 |
| 233 static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned
char *src, unsigned char *dest, size_t length) | 242 static void qcms_transform_data_rgb_out_pow(qcms_transform *transform, unsigned
char *src, unsigned char *dest, size_t length, qcms_format_type output_format) |
| 234 { | 243 { |
| 244 const int r_out = output_format.r; |
| 245 const int b_out = output_format.b; |
| 246 |
| 235 int i; | 247 int i; |
| 236 float (*mat)[4] = transform->matrix; | 248 float (*mat)[4] = transform->matrix; |
| 237 for (i=0; i<length; i++) { | 249 for (i=0; i<length; i++) { |
| 238 unsigned char device_r = *src++; | 250 unsigned char device_r = *src++; |
| 239 unsigned char device_g = *src++; | 251 unsigned char device_g = *src++; |
| 240 unsigned char device_b = *src++; | 252 unsigned char device_b = *src++; |
| 241 | 253 |
| 242 float linear_r = transform->input_gamma_table_r[device_r]; | 254 float linear_r = transform->input_gamma_table_r[device_r]; |
| 243 float linear_g = transform->input_gamma_table_g[device_g]; | 255 float linear_g = transform->input_gamma_table_g[device_g]; |
| 244 float linear_b = transform->input_gamma_table_b[device_b]; | 256 float linear_b = transform->input_gamma_table_b[device_b]; |
| 245 | 257 |
| 246 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; | 258 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; |
| 247 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; | 259 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; |
| 248 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; | 260 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; |
| 249 | 261 |
| 250 float out_device_r = pow(out_linear_r, transform->out_gamma_r); | 262 float out_device_r = pow(out_linear_r, transform->out_gamma_r); |
| 251 float out_device_g = pow(out_linear_g, transform->out_gamma_g); | 263 float out_device_g = pow(out_linear_g, transform->out_gamma_g); |
| 252 float out_device_b = pow(out_linear_b, transform->out_gamma_b); | 264 float out_device_b = pow(out_linear_b, transform->out_gamma_b); |
| 253 | 265 |
| 254 » » *dest++ = clamp_u8(255*out_device_r); | 266 » » dest[r_out] = clamp_u8(out_device_r*255); |
| 255 » » *dest++ = clamp_u8(255*out_device_g); | 267 » » dest[1] = clamp_u8(out_device_g*255); |
| 256 » » *dest++ = clamp_u8(255*out_device_b); | 268 » » dest[b_out] = clamp_u8(out_device_b*255); |
| 269 » » dest += 3; |
| 257 } | 270 } |
| 258 } | 271 } |
| 259 #endif | 272 #endif |
| 260 | 273 |
| 261 static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned
char *src, unsigned char *dest, size_t length) | 274 static void qcms_transform_data_gray_out_lut(qcms_transform *transform, unsigned
char *src, unsigned char *dest, size_t length, qcms_format_type output_format) |
| 262 { | 275 { |
| 276 const int r_out = output_format.r; |
| 277 const int b_out = output_format.b; |
| 278 |
| 263 unsigned int i; | 279 unsigned int i; |
| 264 for (i = 0; i < length; i++) { | 280 for (i = 0; i < length; i++) { |
| 265 float out_device_r, out_device_g, out_device_b; | 281 float out_device_r, out_device_g, out_device_b; |
| 266 unsigned char device = *src++; | 282 unsigned char device = *src++; |
| 267 | 283 |
| 268 float linear = transform->input_gamma_table_gray[device]; | 284 float linear = transform->input_gamma_table_gray[device]; |
| 269 | 285 |
| 270 out_device_r = lut_interp_linear(linear, transform->output_gamma
_lut_r, transform->output_gamma_lut_r_length); | 286 » » out_device_r = lut_interp_linear(linear, transform->output_gamma
_lut_r, transform->output_gamma_lut_r_length); |
| 271 out_device_g = lut_interp_linear(linear, transform->output_gamma
_lut_g, transform->output_gamma_lut_g_length); | 287 out_device_g = lut_interp_linear(linear, transform->output_gamma
_lut_g, transform->output_gamma_lut_g_length); |
| 272 out_device_b = lut_interp_linear(linear, transform->output_gamma
_lut_b, transform->output_gamma_lut_b_length); | 288 out_device_b = lut_interp_linear(linear, transform->output_gamma
_lut_b, transform->output_gamma_lut_b_length); |
| 273 | 289 |
| 274 » » *dest++ = clamp_u8(out_device_r*255); | 290 » » dest[r_out] = clamp_u8(out_device_r*255); |
| 275 » » *dest++ = clamp_u8(out_device_g*255); | 291 » » dest[1] = clamp_u8(out_device_g*255); |
| 276 » » *dest++ = clamp_u8(out_device_b*255); | 292 » » dest[b_out] = clamp_u8(out_device_b*255); |
| 293 » » dest += 3; |
| 277 } | 294 } |
| 278 } | 295 } |
| 279 | 296 |
| 280 /* Alpha is not corrected. | 297 /* Alpha is not corrected. |
| 281 A rationale for this is found in Alvy Ray's "Should Alpha Be Nonlinear If | 298 A rationale for this is found in Alvy Ray's "Should Alpha Be Nonlinear If |
| 282 RGB Is?" Tech Memo 17 (December 14, 1998). | 299 RGB Is?" Tech Memo 17 (December 14, 1998). |
| 283 See: ftp://ftp.alvyray.com/Acrobat/17_Nonln.pdf | 300 See: ftp://ftp.alvyray.com/Acrobat/17_Nonln.pdf |
| 284 */ | 301 */ |
| 285 | 302 |
| 286 static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigne
d char *src, unsigned char *dest, size_t length) | 303 static void qcms_transform_data_graya_out_lut(qcms_transform *transform, unsigne
d char *src, unsigned char *dest, size_t length, qcms_format_type output_format) |
| 287 { | 304 { |
| 305 const int r_out = output_format.r; |
| 306 const int b_out = output_format.b; |
| 307 |
| 288 unsigned int i; | 308 unsigned int i; |
| 289 for (i = 0; i < length; i++) { | 309 for (i = 0; i < length; i++) { |
| 290 float out_device_r, out_device_g, out_device_b; | 310 float out_device_r, out_device_g, out_device_b; |
| 291 unsigned char device = *src++; | 311 unsigned char device = *src++; |
| 292 unsigned char alpha = *src++; | 312 unsigned char alpha = *src++; |
| 293 | 313 |
| 294 float linear = transform->input_gamma_table_gray[device]; | 314 float linear = transform->input_gamma_table_gray[device]; |
| 295 | 315 |
| 296 out_device_r = lut_interp_linear(linear, transform->output_gamma
_lut_r, transform->output_gamma_lut_r_length); | 316 » » out_device_r = lut_interp_linear(linear, transform->output_gamma
_lut_r, transform->output_gamma_lut_r_length); |
| 297 out_device_g = lut_interp_linear(linear, transform->output_gamma
_lut_g, transform->output_gamma_lut_g_length); | 317 out_device_g = lut_interp_linear(linear, transform->output_gamma
_lut_g, transform->output_gamma_lut_g_length); |
| 298 out_device_b = lut_interp_linear(linear, transform->output_gamma
_lut_b, transform->output_gamma_lut_b_length); | 318 out_device_b = lut_interp_linear(linear, transform->output_gamma
_lut_b, transform->output_gamma_lut_b_length); |
| 299 | 319 |
| 300 » » *dest++ = clamp_u8(out_device_r*255); | 320 » » dest[r_out] = clamp_u8(out_device_r*255); |
| 301 » » *dest++ = clamp_u8(out_device_g*255); | 321 » » dest[1] = clamp_u8(out_device_g*255); |
| 302 » » *dest++ = clamp_u8(out_device_b*255); | 322 » » dest[b_out] = clamp_u8(out_device_b*255); |
| 303 » » *dest++ = alpha; | 323 » » dest[3] = alpha; |
| 324 » » dest += 4; |
| 304 } | 325 } |
| 305 } | 326 } |
| 306 | 327 |
| 307 | 328 |
| 308 static void qcms_transform_data_gray_out_precache(qcms_transform *transform, uns
igned char *src, unsigned char *dest, size_t length) | 329 static void qcms_transform_data_gray_out_precache(qcms_transform *transform, uns
igned char *src, unsigned char *dest, size_t length, qcms_format_type output_for
mat) |
| 309 { | 330 { |
| 331 const int r_out = output_format.r; |
| 332 const int b_out = output_format.b; |
| 333 |
| 310 unsigned int i; | 334 unsigned int i; |
| 311 for (i = 0; i < length; i++) { | 335 for (i = 0; i < length; i++) { |
| 312 unsigned char device = *src++; | 336 unsigned char device = *src++; |
| 313 uint16_t gray; | 337 uint16_t gray; |
| 314 | 338 |
| 315 float linear = transform->input_gamma_table_gray[device]; | 339 float linear = transform->input_gamma_table_gray[device]; |
| 316 | 340 |
| 317 /* we could round here... */ | 341 /* we could round here... */ |
| 318 gray = linear * PRECACHE_OUTPUT_MAX; | 342 gray = linear * PRECACHE_OUTPUT_MAX; |
| 319 | 343 |
| 320 » » *dest++ = transform->output_table_r->data[gray]; | 344 » » dest[r_out] = transform->output_table_r->data[gray]; |
| 321 » » *dest++ = transform->output_table_g->data[gray]; | 345 » » dest[1] = transform->output_table_g->data[gray]; |
| 322 » » *dest++ = transform->output_table_b->data[gray]; | 346 » » dest[b_out] = transform->output_table_b->data[gray]; |
| 347 » » dest += 3; |
| 323 } | 348 } |
| 324 } | 349 } |
| 325 | 350 |
| 326 static void qcms_transform_data_graya_out_precache(qcms_transform *transform, un
signed char *src, unsigned char *dest, size_t length) | 351 |
| 352 static void qcms_transform_data_graya_out_precache(qcms_transform *transform, un
signed char *src, unsigned char *dest, size_t length, qcms_format_type output_fo
rmat) |
| 327 { | 353 { |
| 354 const int r_out = output_format.r; |
| 355 const int b_out = output_format.b; |
| 356 |
| 328 unsigned int i; | 357 unsigned int i; |
| 329 for (i = 0; i < length; i++) { | 358 for (i = 0; i < length; i++) { |
| 330 unsigned char device = *src++; | 359 unsigned char device = *src++; |
| 331 unsigned char alpha = *src++; | 360 unsigned char alpha = *src++; |
| 332 uint16_t gray; | 361 uint16_t gray; |
| 333 | 362 |
| 334 float linear = transform->input_gamma_table_gray[device]; | 363 float linear = transform->input_gamma_table_gray[device]; |
| 335 | 364 |
| 336 /* we could round here... */ | 365 /* we could round here... */ |
| 337 gray = linear * PRECACHE_OUTPUT_MAX; | 366 gray = linear * PRECACHE_OUTPUT_MAX; |
| 338 | 367 |
| 339 » » *dest++ = transform->output_table_r->data[gray]; | 368 » » dest[r_out] = transform->output_table_r->data[gray]; |
| 340 » » *dest++ = transform->output_table_g->data[gray]; | 369 » » dest[1] = transform->output_table_g->data[gray]; |
| 341 » » *dest++ = transform->output_table_b->data[gray]; | 370 » » dest[b_out] = transform->output_table_b->data[gray]; |
| 342 » » *dest++ = alpha; | 371 » » dest[3] = alpha; |
| 372 » » dest += 4; |
| 343 } | 373 } |
| 344 } | 374 } |
| 345 | 375 |
| 346 static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform,
unsigned char *src, unsigned char *dest, size_t length) | 376 static void qcms_transform_data_rgb_out_lut_precache(qcms_transform *transform,
unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output_
format) |
| 347 { | 377 { |
| 378 const int r_out = output_format.r; |
| 379 const int b_out = output_format.b; |
| 380 |
| 348 unsigned int i; | 381 unsigned int i; |
| 349 float (*mat)[4] = transform->matrix; | 382 float (*mat)[4] = transform->matrix; |
| 350 for (i = 0; i < length; i++) { | 383 for (i = 0; i < length; i++) { |
| 351 unsigned char device_r = *src++; | 384 unsigned char device_r = *src++; |
| 352 unsigned char device_g = *src++; | 385 unsigned char device_g = *src++; |
| 353 unsigned char device_b = *src++; | 386 unsigned char device_b = *src++; |
| 354 uint16_t r, g, b; | 387 uint16_t r, g, b; |
| 355 | 388 |
| 356 float linear_r = transform->input_gamma_table_r[device_r]; | 389 float linear_r = transform->input_gamma_table_r[device_r]; |
| 357 float linear_g = transform->input_gamma_table_g[device_g]; | 390 float linear_g = transform->input_gamma_table_g[device_g]; |
| 358 float linear_b = transform->input_gamma_table_b[device_b]; | 391 float linear_b = transform->input_gamma_table_b[device_b]; |
| 359 | 392 |
| 360 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; | 393 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; |
| 361 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; | 394 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; |
| 362 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; | 395 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; |
| 363 | 396 |
| 364 out_linear_r = clamp_float(out_linear_r); | 397 out_linear_r = clamp_float(out_linear_r); |
| 365 out_linear_g = clamp_float(out_linear_g); | 398 out_linear_g = clamp_float(out_linear_g); |
| 366 out_linear_b = clamp_float(out_linear_b); | 399 out_linear_b = clamp_float(out_linear_b); |
| 367 | 400 |
| 368 /* we could round here... */ | 401 /* we could round here... */ |
| 369 r = out_linear_r * PRECACHE_OUTPUT_MAX; | 402 r = out_linear_r * PRECACHE_OUTPUT_MAX; |
| 370 g = out_linear_g * PRECACHE_OUTPUT_MAX; | 403 g = out_linear_g * PRECACHE_OUTPUT_MAX; |
| 371 b = out_linear_b * PRECACHE_OUTPUT_MAX; | 404 b = out_linear_b * PRECACHE_OUTPUT_MAX; |
| 372 | 405 |
| 373 » » *dest++ = transform->output_table_r->data[r]; | 406 » » dest[r_out] = transform->output_table_r->data[r]; |
| 374 » » *dest++ = transform->output_table_g->data[g]; | 407 » » dest[1] = transform->output_table_g->data[g]; |
| 375 » » *dest++ = transform->output_table_b->data[b]; | 408 » » dest[b_out] = transform->output_table_b->data[b]; |
| 409 » » dest += 3; |
| 376 } | 410 } |
| 377 } | 411 } |
| 378 | 412 |
| 379 static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform,
unsigned char *src, unsigned char *dest, size_t length) | 413 static void qcms_transform_data_rgba_out_lut_precache(qcms_transform *transform,
unsigned char *src, unsigned char *dest, size_t length, qcms_format_type output
_format) |
| 380 { | 414 { |
| 415 const int r_out = output_format.r; |
| 416 const int b_out = output_format.b; |
| 417 |
| 381 unsigned int i; | 418 unsigned int i; |
| 382 float (*mat)[4] = transform->matrix; | 419 float (*mat)[4] = transform->matrix; |
| 383 for (i = 0; i < length; i++) { | 420 for (i = 0; i < length; i++) { |
| 384 unsigned char device_r = *src++; | 421 unsigned char device_r = *src++; |
| 385 unsigned char device_g = *src++; | 422 unsigned char device_g = *src++; |
| 386 unsigned char device_b = *src++; | 423 unsigned char device_b = *src++; |
| 387 unsigned char alpha = *src++; | 424 unsigned char alpha = *src++; |
| 388 uint16_t r, g, b; | 425 uint16_t r, g, b; |
| 389 | 426 |
| 390 float linear_r = transform->input_gamma_table_r[device_r]; | 427 float linear_r = transform->input_gamma_table_r[device_r]; |
| 391 float linear_g = transform->input_gamma_table_g[device_g]; | 428 float linear_g = transform->input_gamma_table_g[device_g]; |
| 392 float linear_b = transform->input_gamma_table_b[device_b]; | 429 float linear_b = transform->input_gamma_table_b[device_b]; |
| 393 | 430 |
| 394 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; | 431 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; |
| 395 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; | 432 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; |
| 396 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; | 433 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; |
| 397 | 434 |
| 398 out_linear_r = clamp_float(out_linear_r); | 435 out_linear_r = clamp_float(out_linear_r); |
| 399 out_linear_g = clamp_float(out_linear_g); | 436 out_linear_g = clamp_float(out_linear_g); |
| 400 out_linear_b = clamp_float(out_linear_b); | 437 out_linear_b = clamp_float(out_linear_b); |
| 401 | 438 |
| 402 /* we could round here... */ | 439 /* we could round here... */ |
| 403 r = out_linear_r * PRECACHE_OUTPUT_MAX; | 440 r = out_linear_r * PRECACHE_OUTPUT_MAX; |
| 404 g = out_linear_g * PRECACHE_OUTPUT_MAX; | 441 g = out_linear_g * PRECACHE_OUTPUT_MAX; |
| 405 b = out_linear_b * PRECACHE_OUTPUT_MAX; | 442 b = out_linear_b * PRECACHE_OUTPUT_MAX; |
| 406 | 443 |
| 407 » » *dest++ = transform->output_table_r->data[r]; | 444 » » dest[r_out] = transform->output_table_r->data[r]; |
| 408 » » *dest++ = transform->output_table_g->data[g]; | 445 » » dest[1] = transform->output_table_g->data[g]; |
| 409 » » *dest++ = transform->output_table_b->data[b]; | 446 » » dest[b_out] = transform->output_table_b->data[b]; |
| 410 » » *dest++ = alpha; | 447 » » dest[3] = alpha; |
| 448 » » dest += 4; |
| 411 } | 449 } |
| 412 } | 450 } |
| 413 | 451 |
| 414 // Not used | 452 // Not used |
| 415 /* | 453 /* |
| 416 static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *s
rc, unsigned char *dest, size_t length) { | 454 static void qcms_transform_data_clut(qcms_transform *transform, unsigned char *s
rc, unsigned char *dest, size_t length, qcms_format_type output_format) |
| 455 { |
| 456 » const int r_out = output_format.r; |
| 457 » const int b_out = output_format.b; |
| 458 |
| 417 unsigned int i; | 459 unsigned int i; |
| 418 int xy_len = 1; | 460 int xy_len = 1; |
| 419 int x_len = transform->grid_size; | 461 int x_len = transform->grid_size; |
| 420 int len = x_len * x_len; | 462 int len = x_len * x_len; |
| 421 float* r_table = transform->r_clut; | 463 float* r_table = transform->r_clut; |
| 422 float* g_table = transform->g_clut; | 464 float* g_table = transform->g_clut; |
| 423 float* b_table = transform->b_clut; | 465 float* b_table = transform->b_clut; |
| 424 | 466 |
| 425 for (i = 0; i < length; i++) { | 467 for (i = 0; i < length; i++) { |
| 426 unsigned char in_r = *src++; | 468 unsigned char in_r = *src++; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 455 float clut_g = lerp(g_y1, g_y2, z_d); | 497 float clut_g = lerp(g_y1, g_y2, z_d); |
| 456 | 498 |
| 457 float b_x1 = lerp(CLU(b_table,x,y,z), CLU(b_table,x_n,y,z), x_d)
; | 499 float b_x1 = lerp(CLU(b_table,x,y,z), CLU(b_table,x_n,y,z), x_d)
; |
| 458 float b_x2 = lerp(CLU(b_table,x,y_n,z), CLU(b_table,x_n,y_n,z),
x_d); | 500 float b_x2 = lerp(CLU(b_table,x,y_n,z), CLU(b_table,x_n,y_n,z),
x_d); |
| 459 float b_y1 = lerp(b_x1, b_x2, y_d); | 501 float b_y1 = lerp(b_x1, b_x2, y_d); |
| 460 float b_x3 = lerp(CLU(b_table,x,y,z_n), CLU(b_table,x_n,y,z_n),
x_d); | 502 float b_x3 = lerp(CLU(b_table,x,y,z_n), CLU(b_table,x_n,y,z_n),
x_d); |
| 461 float b_x4 = lerp(CLU(b_table,x,y_n,z_n), CLU(b_table,x_n,y_n,z_
n), x_d); | 503 float b_x4 = lerp(CLU(b_table,x,y_n,z_n), CLU(b_table,x_n,y_n,z_
n), x_d); |
| 462 float b_y2 = lerp(b_x3, b_x4, y_d); | 504 float b_y2 = lerp(b_x3, b_x4, y_d); |
| 463 float clut_b = lerp(b_y1, b_y2, z_d); | 505 float clut_b = lerp(b_y1, b_y2, z_d); |
| 464 | 506 |
| 465 » » *dest++ = clamp_u8(clut_r*255.0f); | 507 » » dest[r_out] = clamp_u8(clut_r*255.0f); |
| 466 » » *dest++ = clamp_u8(clut_g*255.0f); | 508 » » dest[1] = clamp_u8(clut_g*255.0f); |
| 467 » » *dest++ = clamp_u8(clut_b*255.0f); | 509 » » dest[b_out] = clamp_u8(clut_b*255.0f); |
| 468 » }» | 510 » » dest += 3; |
| 511 » } |
| 469 } | 512 } |
| 470 */ | 513 */ |
| 471 | 514 |
| 472 // Using lcms' tetra interpolation algorithm. | 515 // Using lcms' tetra interpolation algorithm. |
| 473 static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsig
ned char *src, unsigned char *dest, size_t length) { | 516 static void qcms_transform_data_tetra_clut_rgba(qcms_transform *transform, unsig
ned char *src, unsigned char *dest, size_t length, qcms_format_type output_forma
t) |
| 517 { |
| 518 » const int r_out = output_format.r; |
| 519 » const int b_out = output_format.b; |
| 520 |
| 474 unsigned int i; | 521 unsigned int i; |
| 475 int xy_len = 1; | 522 int xy_len = 1; |
| 476 int x_len = transform->grid_size; | 523 int x_len = transform->grid_size; |
| 477 int len = x_len * x_len; | 524 int len = x_len * x_len; |
| 478 float* r_table = transform->r_clut; | 525 float* r_table = transform->r_clut; |
| 479 float* g_table = transform->g_clut; | 526 float* g_table = transform->g_clut; |
| 480 float* b_table = transform->b_clut; | 527 float* b_table = transform->b_clut; |
| 481 float c0_r, c1_r, c2_r, c3_r; | 528 float c0_r, c1_r, c2_r, c3_r; |
| 482 float c0_g, c1_g, c2_g, c3_g; | 529 float c0_g, c1_g, c2_g, c3_g; |
| 483 float c0_b, c1_b, c2_b, c3_b; | 530 float c0_b, c1_b, c2_b, c3_b; |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 570 c2_b = CLU(b_table, x, y_n, z_n) - CLU(b
_table, x, y, z_n); | 617 c2_b = CLU(b_table, x, y_n, z_n) - CLU(b
_table, x, y, z_n); |
| 571 c3_b = CLU(b_table, x, y, z_n) - c0_b; | 618 c3_b = CLU(b_table, x, y, z_n) - c0_b; |
| 572 } | 619 } |
| 573 } | 620 } |
| 574 } | 621 } |
| 575 | 622 |
| 576 clut_r = c0_r + c1_r*rx + c2_r*ry + c3_r*rz; | 623 clut_r = c0_r + c1_r*rx + c2_r*ry + c3_r*rz; |
| 577 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz; | 624 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz; |
| 578 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz; | 625 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz; |
| 579 | 626 |
| 580 » » *dest++ = clamp_u8(clut_r*255.0f); | 627 » » dest[r_out] = clamp_u8(clut_r*255.0f); |
| 581 » » *dest++ = clamp_u8(clut_g*255.0f); | 628 » » dest[1] = clamp_u8(clut_g*255.0f); |
| 582 » » *dest++ = clamp_u8(clut_b*255.0f); | 629 » » dest[b_out] = clamp_u8(clut_b*255.0f); |
| 583 » » *dest++ = in_a; | 630 » » dest[3] = in_a; |
| 584 » }» | 631 » » dest += 4; |
| 632 » } |
| 585 } | 633 } |
| 586 | 634 |
| 587 // Using lcms' tetra interpolation code. | 635 // Using lcms' tetra interpolation code. |
| 588 static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned c
har *src, unsigned char *dest, size_t length) { | 636 static void qcms_transform_data_tetra_clut(qcms_transform *transform, unsigned c
har *src, unsigned char *dest, size_t length, qcms_format_type output_format) |
| 637 { |
| 638 » const int r_out = output_format.r; |
| 639 » const int b_out = output_format.b; |
| 640 |
| 589 unsigned int i; | 641 unsigned int i; |
| 590 int xy_len = 1; | 642 int xy_len = 1; |
| 591 int x_len = transform->grid_size; | 643 int x_len = transform->grid_size; |
| 592 int len = x_len * x_len; | 644 int len = x_len * x_len; |
| 593 float* r_table = transform->r_clut; | 645 float* r_table = transform->r_clut; |
| 594 float* g_table = transform->g_clut; | 646 float* g_table = transform->g_clut; |
| 595 float* b_table = transform->b_clut; | 647 float* b_table = transform->b_clut; |
| 596 float c0_r, c1_r, c2_r, c3_r; | 648 float c0_r, c1_r, c2_r, c3_r; |
| 597 float c0_g, c1_g, c2_g, c3_g; | 649 float c0_g, c1_g, c2_g, c3_g; |
| 598 float c0_b, c1_b, c2_b, c3_b; | 650 float c0_b, c1_b, c2_b, c3_b; |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 684 c2_b = CLU(b_table, x, y_n, z_n) - CLU(b
_table, x, y, z_n); | 736 c2_b = CLU(b_table, x, y_n, z_n) - CLU(b
_table, x, y, z_n); |
| 685 c3_b = CLU(b_table, x, y, z_n) - c0_b; | 737 c3_b = CLU(b_table, x, y, z_n) - c0_b; |
| 686 } | 738 } |
| 687 } | 739 } |
| 688 } | 740 } |
| 689 | 741 |
| 690 clut_r = c0_r + c1_r*rx + c2_r*ry + c3_r*rz; | 742 clut_r = c0_r + c1_r*rx + c2_r*ry + c3_r*rz; |
| 691 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz; | 743 clut_g = c0_g + c1_g*rx + c2_g*ry + c3_g*rz; |
| 692 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz; | 744 clut_b = c0_b + c1_b*rx + c2_b*ry + c3_b*rz; |
| 693 | 745 |
| 694 » » *dest++ = clamp_u8(clut_r*255.0f); | 746 » » dest[r_out] = clamp_u8(clut_r*255.0f); |
| 695 » » *dest++ = clamp_u8(clut_g*255.0f); | 747 » » dest[1] = clamp_u8(clut_g*255.0f); |
| 696 » » *dest++ = clamp_u8(clut_b*255.0f); | 748 » » dest[b_out] = clamp_u8(clut_b*255.0f); |
| 697 » }» | 749 » » dest += 3; |
| 750 » } |
| 698 } | 751 } |
| 699 | 752 |
| 700 static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned
char *src, unsigned char *dest, size_t length) | 753 static void qcms_transform_data_rgb_out_lut(qcms_transform *transform, unsigned
char *src, unsigned char *dest, size_t length, qcms_format_type output_format) |
| 701 { | 754 { |
| 755 const int r_out = output_format.r; |
| 756 const int b_out = output_format.b; |
| 757 |
| 702 unsigned int i; | 758 unsigned int i; |
| 703 float (*mat)[4] = transform->matrix; | 759 float (*mat)[4] = transform->matrix; |
| 704 for (i = 0; i < length; i++) { | 760 for (i = 0; i < length; i++) { |
| 705 unsigned char device_r = *src++; | 761 unsigned char device_r = *src++; |
| 706 unsigned char device_g = *src++; | 762 unsigned char device_g = *src++; |
| 707 unsigned char device_b = *src++; | 763 unsigned char device_b = *src++; |
| 708 float out_device_r, out_device_g, out_device_b; | 764 float out_device_r, out_device_g, out_device_b; |
| 709 | 765 |
| 710 float linear_r = transform->input_gamma_table_r[device_r]; | 766 float linear_r = transform->input_gamma_table_r[device_r]; |
| 711 float linear_g = transform->input_gamma_table_g[device_g]; | 767 float linear_g = transform->input_gamma_table_g[device_g]; |
| 712 float linear_b = transform->input_gamma_table_b[device_b]; | 768 float linear_b = transform->input_gamma_table_b[device_b]; |
| 713 | 769 |
| 714 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; | 770 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; |
| 715 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; | 771 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; |
| 716 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; | 772 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; |
| 717 | 773 |
| 718 out_linear_r = clamp_float(out_linear_r); | 774 out_linear_r = clamp_float(out_linear_r); |
| 719 out_linear_g = clamp_float(out_linear_g); | 775 out_linear_g = clamp_float(out_linear_g); |
| 720 out_linear_b = clamp_float(out_linear_b); | 776 out_linear_b = clamp_float(out_linear_b); |
| 721 | 777 |
| 722 out_device_r = lut_interp_linear(out_linear_r, | 778 out_device_r = lut_interp_linear(out_linear_r, |
| 723 transform->output_gamma_lut_r, transform->output
_gamma_lut_r_length); | 779 transform->output_gamma_lut_r, transform->output
_gamma_lut_r_length); |
| 724 out_device_g = lut_interp_linear(out_linear_g, | 780 out_device_g = lut_interp_linear(out_linear_g, |
| 725 transform->output_gamma_lut_g, transform->output
_gamma_lut_g_length); | 781 transform->output_gamma_lut_g, transform->output
_gamma_lut_g_length); |
| 726 out_device_b = lut_interp_linear(out_linear_b, | 782 out_device_b = lut_interp_linear(out_linear_b, |
| 727 transform->output_gamma_lut_b, transform->output
_gamma_lut_b_length); | 783 transform->output_gamma_lut_b, transform->output
_gamma_lut_b_length); |
| 728 | 784 |
| 729 » » *dest++ = clamp_u8(out_device_r*255); | 785 » » dest[r_out] = clamp_u8(out_device_r*255); |
| 730 » » *dest++ = clamp_u8(out_device_g*255); | 786 » » dest[1] = clamp_u8(out_device_g*255); |
| 731 » » *dest++ = clamp_u8(out_device_b*255); | 787 » » dest[b_out] = clamp_u8(out_device_b*255); |
| 788 » » dest += 3; |
| 732 } | 789 } |
| 733 } | 790 } |
| 734 | 791 |
| 735 static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned
char *src, unsigned char *dest, size_t length) | 792 static void qcms_transform_data_rgba_out_lut(qcms_transform *transform, unsigned
char *src, unsigned char *dest, size_t length, qcms_format_type output_format) |
| 736 { | 793 { |
| 794 const int r_out = output_format.r; |
| 795 const int b_out = output_format.b; |
| 796 |
| 737 unsigned int i; | 797 unsigned int i; |
| 738 float (*mat)[4] = transform->matrix; | 798 float (*mat)[4] = transform->matrix; |
| 739 for (i = 0; i < length; i++) { | 799 for (i = 0; i < length; i++) { |
| 740 unsigned char device_r = *src++; | 800 unsigned char device_r = *src++; |
| 741 unsigned char device_g = *src++; | 801 unsigned char device_g = *src++; |
| 742 unsigned char device_b = *src++; | 802 unsigned char device_b = *src++; |
| 743 unsigned char alpha = *src++; | 803 unsigned char alpha = *src++; |
| 744 float out_device_r, out_device_g, out_device_b; | 804 float out_device_r, out_device_g, out_device_b; |
| 745 | 805 |
| 746 float linear_r = transform->input_gamma_table_r[device_r]; | 806 float linear_r = transform->input_gamma_table_r[device_r]; |
| 747 float linear_g = transform->input_gamma_table_g[device_g]; | 807 float linear_g = transform->input_gamma_table_g[device_g]; |
| 748 float linear_b = transform->input_gamma_table_b[device_b]; | 808 float linear_b = transform->input_gamma_table_b[device_b]; |
| 749 | 809 |
| 750 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; | 810 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; |
| 751 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; | 811 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; |
| 752 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; | 812 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; |
| 753 | 813 |
| 754 out_linear_r = clamp_float(out_linear_r); | 814 out_linear_r = clamp_float(out_linear_r); |
| 755 out_linear_g = clamp_float(out_linear_g); | 815 out_linear_g = clamp_float(out_linear_g); |
| 756 out_linear_b = clamp_float(out_linear_b); | 816 out_linear_b = clamp_float(out_linear_b); |
| 757 | 817 |
| 758 out_device_r = lut_interp_linear(out_linear_r, | 818 out_device_r = lut_interp_linear(out_linear_r, |
| 759 transform->output_gamma_lut_r, transform->output
_gamma_lut_r_length); | 819 transform->output_gamma_lut_r, transform->output
_gamma_lut_r_length); |
| 760 out_device_g = lut_interp_linear(out_linear_g, | 820 out_device_g = lut_interp_linear(out_linear_g, |
| 761 transform->output_gamma_lut_g, transform->output
_gamma_lut_g_length); | 821 transform->output_gamma_lut_g, transform->output
_gamma_lut_g_length); |
| 762 out_device_b = lut_interp_linear(out_linear_b, | 822 out_device_b = lut_interp_linear(out_linear_b, |
| 763 transform->output_gamma_lut_b, transform->output
_gamma_lut_b_length); | 823 transform->output_gamma_lut_b, transform->output
_gamma_lut_b_length); |
| 764 | 824 |
| 765 » » *dest++ = clamp_u8(out_device_r*255); | 825 » » dest[r_out] = clamp_u8(out_device_r*255); |
| 766 » » *dest++ = clamp_u8(out_device_g*255); | 826 » » dest[1] = clamp_u8(out_device_g*255); |
| 767 » » *dest++ = clamp_u8(out_device_b*255); | 827 » » dest[b_out] = clamp_u8(out_device_b*255); |
| 768 » » *dest++ = alpha; | 828 » » dest[3] = alpha; |
| 829 » » dest += 4; |
| 769 } | 830 } |
| 770 } | 831 } |
| 771 | 832 |
| 772 #if 0 | 833 #if 0 |
| 773 static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsign
ed char *src, unsigned char *dest, size_t length) | 834 static void qcms_transform_data_rgb_out_linear(qcms_transform *transform, unsign
ed char *src, unsigned char *dest, size_t length, qcms_format_type output_format
) |
| 774 { | 835 { |
| 836 const int r_out = output_format.r; |
| 837 const int b_out = output_format.b; |
| 838 |
| 775 int i; | 839 int i; |
| 776 float (*mat)[4] = transform->matrix; | 840 float (*mat)[4] = transform->matrix; |
| 777 for (i = 0; i < length; i++) { | 841 for (i = 0; i < length; i++) { |
| 778 unsigned char device_r = *src++; | 842 unsigned char device_r = *src++; |
| 779 unsigned char device_g = *src++; | 843 unsigned char device_g = *src++; |
| 780 unsigned char device_b = *src++; | 844 unsigned char device_b = *src++; |
| 781 | 845 |
| 782 float linear_r = transform->input_gamma_table_r[device_r]; | 846 float linear_r = transform->input_gamma_table_r[device_r]; |
| 783 float linear_g = transform->input_gamma_table_g[device_g]; | 847 float linear_g = transform->input_gamma_table_g[device_g]; |
| 784 float linear_b = transform->input_gamma_table_b[device_b]; | 848 float linear_b = transform->input_gamma_table_b[device_b]; |
| 785 | 849 |
| 786 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; | 850 float out_linear_r = mat[0][0]*linear_r + mat[1][0]*linear_g + m
at[2][0]*linear_b; |
| 787 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; | 851 float out_linear_g = mat[0][1]*linear_r + mat[1][1]*linear_g + m
at[2][1]*linear_b; |
| 788 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; | 852 float out_linear_b = mat[0][2]*linear_r + mat[1][2]*linear_g + m
at[2][2]*linear_b; |
| 789 | 853 |
| 790 » » *dest++ = clamp_u8(out_linear_r*255); | 854 » » dest[r_out] = clamp_u8(out_linear_r*255); |
| 791 » » *dest++ = clamp_u8(out_linear_g*255); | 855 » » dest[1] = clamp_u8(out_linear_g*255); |
| 792 » » *dest++ = clamp_u8(out_linear_b*255); | 856 » » dest[b_out] = clamp_u8(out_linear_b*255); |
| 857 » » dest += 3; |
| 793 } | 858 } |
| 794 } | 859 } |
| 795 #endif | 860 #endif |
| 796 | 861 |
| 797 static struct precache_output *precache_reference(struct precache_output *p) | 862 static struct precache_output *precache_reference(struct precache_output *p) |
| 798 { | 863 { |
| 799 p->ref_count++; | 864 p->ref_count++; |
| 800 return p; | 865 return p; |
| 801 } | 866 } |
| 802 | 867 |
| (...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1255 } | 1320 } |
| 1256 return transform; | 1321 return transform; |
| 1257 } | 1322 } |
| 1258 | 1323 |
| 1259 #if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) | 1324 #if defined(__GNUC__) && !defined(__x86_64__) && !defined(__amd64__) |
| 1260 /* we need this to avoid crashes when gcc assumes the stack is 128bit aligned */ | 1325 /* we need this to avoid crashes when gcc assumes the stack is 128bit aligned */ |
| 1261 __attribute__((__force_align_arg_pointer__)) | 1326 __attribute__((__force_align_arg_pointer__)) |
| 1262 #endif | 1327 #endif |
| 1263 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_
t length) | 1328 void qcms_transform_data(qcms_transform *transform, void *src, void *dest, size_
t length) |
| 1264 { | 1329 { |
| 1265 » transform->transform_fn(transform, src, dest, length); | 1330 » static const struct _qcms_format_type output_rgbx = { 0, 2 }; |
| 1331 |
| 1332 » transform->transform_fn(transform, src, dest, length, output_rgbx); |
| 1333 } |
| 1334 |
| 1335 void qcms_transform_data_type(qcms_transform *transform, void *src, void *dest,
size_t length, qcms_output_type type) |
| 1336 { |
| 1337 » static const struct _qcms_format_type output_rgbx = { 0, 2 }; |
| 1338 » static const struct _qcms_format_type output_bgrx = { 2, 0 }; |
| 1339 |
| 1340 » transform->transform_fn(transform, src, dest, length, type == QCMS_OUTPU
T_BGRX ? output_bgrx : output_rgbx); |
| 1266 } | 1341 } |
| 1267 | 1342 |
| 1268 qcms_bool qcms_supports_iccv4; | 1343 qcms_bool qcms_supports_iccv4; |
| 1269 void qcms_enable_iccv4() | 1344 void qcms_enable_iccv4() |
| 1270 { | 1345 { |
| 1271 qcms_supports_iccv4 = true; | 1346 qcms_supports_iccv4 = true; |
| 1272 } | 1347 } |
| OLD | NEW |