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 |