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 13 matching lines...) Expand all Loading... |
24 #include <stdlib.h> | 24 #include <stdlib.h> |
25 #include <math.h> | 25 #include <math.h> |
26 #include <assert.h> | 26 #include <assert.h> |
27 #include <string.h> //memcpy | 27 #include <string.h> //memcpy |
28 #include "qcmsint.h" | 28 #include "qcmsint.h" |
29 #include "chain.h" | 29 #include "chain.h" |
30 #include "halffloat.h" | 30 #include "halffloat.h" |
31 #include "matrix.h" | 31 #include "matrix.h" |
32 #include "transform_util.h" | 32 #include "transform_util.h" |
33 | 33 |
| 34 #ifdef USE_LIBFUZZER |
| 35 #define ASSERT(x) |
| 36 #else |
| 37 #define ASSERT(x) assert(x) |
| 38 #endif |
| 39 |
34 /* for MSVC, GCC, Intel, and Sun compilers */ | 40 /* for MSVC, GCC, Intel, and Sun compilers */ |
35 #if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_M_AMD64
) || defined(__x86_64__) || defined(__x86_64) | 41 #if defined(_M_IX86) || defined(__i386__) || defined(__i386) || defined(_M_AMD64
) || defined(__x86_64__) || defined(__x86_64) |
36 #define X86 | 42 #define X86 |
37 #endif /* _M_IX86 || __i386__ || __i386 || _M_AMD64 || __x86_64__ || __x86_64 */ | 43 #endif /* _M_IX86 || __i386__ || __i386 || _M_AMD64 || __x86_64__ || __x86_64 */ |
38 | 44 |
39 // Build a White point, primary chromas transfer matrix from RGB to CIE XYZ | 45 // Build a White point, primary chromas transfer matrix from RGB to CIE XYZ |
40 // This is just an approximation, I am not handling all the non-linear | 46 // This is just an approximation, I am not handling all the non-linear |
41 // aspects of the RGB to XYZ process, and assumming that the gamma correction | 47 // aspects of the RGB to XYZ process, and assumming that the gamma correction |
42 // has transitive property in the tranformation chain. | 48 // has transitive property in the tranformation chain. |
43 // | 49 // |
(...skipping 1245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1289 qcms_transform *transform = NULL; | 1295 qcms_transform *transform = NULL; |
1290 bool precache = false; | 1296 bool precache = false; |
1291 int i, j; | 1297 int i, j; |
1292 | 1298 |
1293 transform = transform_alloc(); | 1299 transform = transform_alloc(); |
1294 if (!transform) { | 1300 if (!transform) { |
1295 return NULL; | 1301 return NULL; |
1296 } | 1302 } |
1297 | 1303 |
1298 if (out_type != QCMS_DATA_RGB_8 && out_type != QCMS_DATA_RGBA_8) { | 1304 if (out_type != QCMS_DATA_RGB_8 && out_type != QCMS_DATA_RGBA_8) { |
1299 » » assert(0 && "output type"); | 1305 » » ASSERT(0 && "output type"); |
1300 qcms_transform_release(transform); | 1306 qcms_transform_release(transform); |
1301 return NULL; | 1307 return NULL; |
1302 } | 1308 } |
1303 | 1309 |
1304 transform->transform_flags = 0; | 1310 transform->transform_flags = 0; |
1305 | 1311 |
1306 if (out->output_table_r && out->output_table_g && out->output_table_b) { | 1312 if (out->output_table_r && out->output_table_g && out->output_table_b) { |
1307 precache = true; | 1313 precache = true; |
1308 } | 1314 } |
1309 | 1315 |
1310 if (qcms_supports_iccv4 && (in->A2B0 || out->B2A0 || in->mAB || out->mAB
)) { | 1316 if (qcms_supports_iccv4 && (in->A2B0 || out->B2A0 || in->mAB || out->mAB
)) { |
1311 // Precache the transformation to a CLUT 33x33x33 in size. | 1317 // Precache the transformation to a CLUT 33x33x33 in size. |
1312 // 33 is used by many profiles and works well in practice. | 1318 // 33 is used by many profiles and works well in practice. |
1313 // This evenly divides 256 into blocks of 8x8x8. | 1319 // This evenly divides 256 into blocks of 8x8x8. |
1314 // TODO For transforming small data sets of about 200x200 or les
s | 1320 // TODO For transforming small data sets of about 200x200 or les
s |
1315 // precaching should be avoided. | 1321 // precaching should be avoided. |
1316 qcms_transform *result = qcms_transform_precacheLUT_float(transf
orm, in, out, 33, in_type); | 1322 qcms_transform *result = qcms_transform_precacheLUT_float(transf
orm, in, out, 33, in_type); |
1317 if (!result) { | 1323 if (!result) { |
1318 » » » assert(0 && "precacheLUT failed"); | 1324 » » » ASSERT(0 && "precacheLUT failed"); |
1319 qcms_transform_release(transform); | 1325 qcms_transform_release(transform); |
1320 return NULL; | 1326 return NULL; |
1321 } | 1327 } |
1322 return result; | 1328 return result; |
1323 } | 1329 } |
1324 | 1330 |
1325 /* A matrix-based transform will be selected: check that the PCS | 1331 /* A matrix-based transform will be selected: check that the PCS |
1326 of the input/output profiles are the same, crbug.com/5120682 */ | 1332 of the input/output profiles are the same, crbug.com/5120682 */ |
1327 if (in->pcs != out->pcs) { | 1333 if (in->pcs != out->pcs) { |
1328 qcms_transform_release(transform); | 1334 qcms_transform_release(transform); |
(...skipping 17 matching lines...) Expand all Loading... |
1346 if (!transform->output_gamma_lut_r || !transform->output_gamma_l
ut_g || !transform->output_gamma_lut_b) { | 1352 if (!transform->output_gamma_lut_r || !transform->output_gamma_l
ut_g || !transform->output_gamma_lut_b) { |
1347 qcms_transform_release(transform); | 1353 qcms_transform_release(transform); |
1348 return NO_MEM_TRANSFORM; | 1354 return NO_MEM_TRANSFORM; |
1349 } | 1355 } |
1350 } | 1356 } |
1351 | 1357 |
1352 if (in->color_space == RGB_SIGNATURE) { | 1358 if (in->color_space == RGB_SIGNATURE) { |
1353 struct matrix in_matrix, out_matrix, result; | 1359 struct matrix in_matrix, out_matrix, result; |
1354 | 1360 |
1355 if (in_type != QCMS_DATA_RGB_8 && in_type != QCMS_DATA_RGBA_8) { | 1361 if (in_type != QCMS_DATA_RGB_8 && in_type != QCMS_DATA_RGBA_8) { |
1356 » » » assert(0 && "input type"); | 1362 » » » ASSERT(0 && "input type"); |
1357 qcms_transform_release(transform); | 1363 qcms_transform_release(transform); |
1358 return NULL; | 1364 return NULL; |
1359 } | 1365 } |
1360 | 1366 |
1361 if (precache) { | 1367 if (precache) { |
1362 #if defined(SSE2_ENABLE) | 1368 #if defined(SSE2_ENABLE) |
1363 if (sse_version_available() >= 2) { | 1369 if (sse_version_available() >= 2) { |
1364 if (in_type == QCMS_DATA_RGB_8) | 1370 if (in_type == QCMS_DATA_RGB_8) |
1365 transform->transform_fn = qcms_transform
_data_rgb_out_lut_sse2; | 1371 transform->transform_fn = qcms_transform
_data_rgb_out_lut_sse2; |
1366 else | 1372 else |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1421 transform->matrix[2][1] = result.m[1][2]; | 1427 transform->matrix[2][1] = result.m[1][2]; |
1422 transform->matrix[0][2] = result.m[2][0]; | 1428 transform->matrix[0][2] = result.m[2][0]; |
1423 transform->matrix[1][2] = result.m[2][1]; | 1429 transform->matrix[1][2] = result.m[2][1]; |
1424 transform->matrix[2][2] = result.m[2][2]; | 1430 transform->matrix[2][2] = result.m[2][2]; |
1425 | 1431 |
1426 /* Flag transform as matrix. */ | 1432 /* Flag transform as matrix. */ |
1427 transform->transform_flags |= TRANSFORM_FLAG_MATRIX; | 1433 transform->transform_flags |= TRANSFORM_FLAG_MATRIX; |
1428 | 1434 |
1429 } else if (in->color_space == GRAY_SIGNATURE) { | 1435 } else if (in->color_space == GRAY_SIGNATURE) { |
1430 if (in_type != QCMS_DATA_GRAY_8 && in_type != QCMS_DATA_GRAYA_8)
{ | 1436 if (in_type != QCMS_DATA_GRAY_8 && in_type != QCMS_DATA_GRAYA_8)
{ |
1431 » » » assert(0 && "input type"); | 1437 » » » ASSERT(0 && "input type"); |
1432 qcms_transform_release(transform); | 1438 qcms_transform_release(transform); |
1433 return NULL; | 1439 return NULL; |
1434 } | 1440 } |
1435 | 1441 |
1436 transform->input_gamma_table_gray = build_input_gamma_table(in->
grayTRC); | 1442 transform->input_gamma_table_gray = build_input_gamma_table(in->
grayTRC); |
1437 | 1443 |
1438 if (!transform->input_gamma_table_gray) { | 1444 if (!transform->input_gamma_table_gray) { |
1439 qcms_transform_release(transform); | 1445 qcms_transform_release(transform); |
1440 return NO_MEM_TRANSFORM; | 1446 return NO_MEM_TRANSFORM; |
1441 } | 1447 } |
1442 | 1448 |
1443 if (precache) { | 1449 if (precache) { |
1444 if (in_type == QCMS_DATA_GRAY_8) { | 1450 if (in_type == QCMS_DATA_GRAY_8) { |
1445 transform->transform_fn = qcms_transform_data_gr
ay_out_precache; | 1451 transform->transform_fn = qcms_transform_data_gr
ay_out_precache; |
1446 } else { | 1452 } else { |
1447 transform->transform_fn = qcms_transform_data_gr
aya_out_precache; | 1453 transform->transform_fn = qcms_transform_data_gr
aya_out_precache; |
1448 } | 1454 } |
1449 } else { | 1455 } else { |
1450 if (in_type == QCMS_DATA_GRAY_8) { | 1456 if (in_type == QCMS_DATA_GRAY_8) { |
1451 transform->transform_fn = qcms_transform_data_gr
ay_out_lut; | 1457 transform->transform_fn = qcms_transform_data_gr
ay_out_lut; |
1452 } else { | 1458 } else { |
1453 transform->transform_fn = qcms_transform_data_gr
aya_out_lut; | 1459 transform->transform_fn = qcms_transform_data_gr
aya_out_lut; |
1454 } | 1460 } |
1455 } | 1461 } |
1456 } else { | 1462 } else { |
1457 » » assert(0 && "unexpected colorspace"); | 1463 » » ASSERT(0 && "unexpected colorspace"); |
1458 qcms_transform_release(transform); | 1464 qcms_transform_release(transform); |
1459 return NULL; | 1465 return NULL; |
1460 } | 1466 } |
1461 | 1467 |
1462 return transform; | 1468 return transform; |
1463 } | 1469 } |
1464 | 1470 |
1465 /* __force_align_arg_pointer__ is an x86-only attribute, and gcc/clang warns on
unused | 1471 /* __force_align_arg_pointer__ is an x86-only attribute, and gcc/clang warns on
unused |
1466 * attributes. Don't use this on ARM or AMD64. __has_attribute can detect the pr
esence | 1472 * attributes. Don't use this on ARM or AMD64. __has_attribute can detect the pr
esence |
1467 * of the attribute but is currently only supported by clang */ | 1473 * of the attribute but is currently only supported by clang */ |
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1560 case QCMS_TRC_USHORT: | 1566 case QCMS_TRC_USHORT: |
1561 for (i = 0; i < size; ++i) { | 1567 for (i = 0; i < size; ++i) { |
1562 *data++ = roundf(t->input_gamma_table_r[i] * 655
35.0); // r | 1568 *data++ = roundf(t->input_gamma_table_r[i] * 655
35.0); // r |
1563 *data++ = roundf(t->input_gamma_table_g[i] * 655
35.0); // g | 1569 *data++ = roundf(t->input_gamma_table_g[i] * 655
35.0); // g |
1564 *data++ = roundf(t->input_gamma_table_b[i] * 655
35.0); // b | 1570 *data++ = roundf(t->input_gamma_table_b[i] * 655
35.0); // b |
1565 *data++ = 65535;
// a | 1571 *data++ = 65535;
// a |
1566 } | 1572 } |
1567 break; | 1573 break; |
1568 default: | 1574 default: |
1569 /* should not be reached */ | 1575 /* should not be reached */ |
1570 » » » assert(0); | 1576 » » » ASSERT(0); |
1571 } | 1577 } |
1572 | 1578 |
1573 return size; | 1579 return size; |
1574 } | 1580 } |
1575 | 1581 |
1576 const float inverse65535 = (float) (1.0 / 65535.0); | 1582 const float inverse65535 = (float) (1.0 / 65535.0); |
1577 | 1583 |
1578 size_t qcms_transform_get_output_trc_rgba(qcms_transform *t, qcms_profile *out,
qcms_trc_type type, unsigned short *data) | 1584 size_t qcms_transform_get_output_trc_rgba(qcms_transform *t, qcms_profile *out,
qcms_trc_type type, unsigned short *data) |
1579 { | 1585 { |
1580 size_t size, i; | 1586 size_t size, i; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1627 case QCMS_TRC_USHORT: | 1633 case QCMS_TRC_USHORT: |
1628 for (i = 0; i < size; ++i) { | 1634 for (i = 0; i < size; ++i) { |
1629 *data++ = t->output_gamma_lut_r[i]; // r | 1635 *data++ = t->output_gamma_lut_r[i]; // r |
1630 *data++ = t->output_gamma_lut_g[i]; // g | 1636 *data++ = t->output_gamma_lut_g[i]; // g |
1631 *data++ = t->output_gamma_lut_b[i]; // b | 1637 *data++ = t->output_gamma_lut_b[i]; // b |
1632 *data++ = 65535; // a | 1638 *data++ = 65535; // a |
1633 } | 1639 } |
1634 break; | 1640 break; |
1635 default: | 1641 default: |
1636 /* should not be reached */ | 1642 /* should not be reached */ |
1637 » » » assert(0); | 1643 » » » ASSERT(0); |
1638 } | 1644 } |
1639 | 1645 |
1640 return size; | 1646 return size; |
1641 } | 1647 } |
OLD | NEW |