OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkColorPriv.h" | 8 #include "SkColorPriv.h" |
9 #include "SkColorSpace_Base.h" | 9 #include "SkColorSpace_Base.h" |
10 #include "SkColorSpacePriv.h" | 10 #include "SkColorSpacePriv.h" |
(...skipping 1311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1322 default: | 1322 default: |
1323 SkASSERT(false); | 1323 SkASSERT(false); |
1324 return; | 1324 return; |
1325 } | 1325 } |
1326 default: | 1326 default: |
1327 SkASSERT(false); | 1327 SkASSERT(false); |
1328 return; | 1328 return; |
1329 } | 1329 } |
1330 } | 1330 } |
1331 | 1331 |
| 1332 static inline Sk4f srgb_to_linear(const Sk4f& x) { |
| 1333 // Approximation of the sRGB gamma curve (within 1 when scaled to 8-bit pixe
ls). |
| 1334 // For 0.00000f <= x < 0.00349f, 12.92 * x |
| 1335 // For 0.00349f <= x <= 1.00000f, 0.679*(x.^0.5) + 0.423*x.^(0.25) - 0.10
1 |
| 1336 // Note that 0.00349 was selected because it is a point where both functions
produce the |
| 1337 // same pixel value when rounded. |
| 1338 auto y = (x + 0.055f) * (1.0f / 1.055f); |
| 1339 auto twodotfive = y * y * y.rsqrt().invert(); |
| 1340 auto lo = ((1.0f / 12.92f)) * x; |
| 1341 auto hi = twodotfive; |
| 1342 auto out = (x < 0.04045f).thenElse(lo, hi); |
| 1343 return out; |
| 1344 } |
| 1345 |
| 1346 template <SrcGamma kSrc, DstGamma kDst, ColorSpaceMatch kCSM> |
| 1347 void SkColorSpaceXform_Base<kSrc, kDst, kCSM> |
| 1348 ::applyYUV(void* dst, const uint8_t* srcY, const uint8_t* srcU, const uint8_t* s
rcV, int len) |
| 1349 const |
| 1350 { |
| 1351 Sk4f rXgXbX, rYgYbY, rZgZbZ, rTgTbT; |
| 1352 load_matrix(fSrcToDst, rXgXbX, rYgYbY, rZgZbZ, rTgTbT); |
| 1353 |
| 1354 if (len >= 4) { |
| 1355 // Naively this would be a loop of load-transform-store, but we found it
faster to |
| 1356 // move the N+1th load ahead of the Nth store. We don't bother doing th
is for N<4. |
| 1357 Sk4f r, g, b, a; |
| 1358 |
| 1359 Sk4f y = (1.0f / 255.0f) * SkNx_cast<float, uint8_t>(Sk4b::Load(srcY)); |
| 1360 Sk4f u = (1.0f / 255.0f) * (SkNx_cast<float, uint8_t>(Sk4b::Load(srcU))
- 128.0f); |
| 1361 Sk4f v = (1.0f / 255.0f) * (SkNx_cast<float, uint8_t>(Sk4b::Load(srcV))
- 128.0f); |
| 1362 |
| 1363 r = (y + 1.402f * v); |
| 1364 g = (y - 0.34414f * u - 0.71414f * v); |
| 1365 b = (y + 1.772f * u); |
| 1366 |
| 1367 r = srgb_to_linear(r); |
| 1368 g = srgb_to_linear(g); |
| 1369 b = srgb_to_linear(b); |
| 1370 |
| 1371 srcY += 4; |
| 1372 srcU += 4; |
| 1373 srcV += 4; |
| 1374 len -= 4; |
| 1375 |
| 1376 Sk4f dr, dg, db, da; |
| 1377 while (len >= 4) { |
| 1378 transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); |
| 1379 translate_gamut(rTgTbT, dr, dg, db); |
| 1380 |
| 1381 y = (1.0f / 255.0f) * SkNx_cast<float, uint8_t>(Sk4b::Load(srcY)); |
| 1382 u = (1.0f / 255.0f) * (SkNx_cast<float, uint8_t>(Sk4b::Load(srcU)) -
128.0f); |
| 1383 v = (1.0f / 255.0f) * (SkNx_cast<float, uint8_t>(Sk4b::Load(srcV)) -
128.0f); |
| 1384 |
| 1385 r = (y + 1.402f * v); |
| 1386 g = (y - 0.34414f * u - 0.71414f * v); |
| 1387 b = (y + 1.772f * u); |
| 1388 |
| 1389 r = srgb_to_linear(r); |
| 1390 g = srgb_to_linear(g); |
| 1391 b = srgb_to_linear(b); |
| 1392 |
| 1393 srcY += 4; |
| 1394 srcU += 4; |
| 1395 srcV += 4; |
| 1396 len -= 4; |
| 1397 |
| 1398 dr = sk_linear_to_srgb_needs_trunc(dr); |
| 1399 dg = sk_linear_to_srgb_needs_trunc(dg); |
| 1400 db = sk_linear_to_srgb_needs_trunc(db); |
| 1401 |
| 1402 dr = sk_clamp_0_255(dr); |
| 1403 dg = sk_clamp_0_255(dg); |
| 1404 db = sk_clamp_0_255(db); |
| 1405 |
| 1406 Sk4i rgba = (SkNx_cast<int>(dr) << 16) |
| 1407 | (SkNx_cast<int>(dg) << 8) |
| 1408 | (SkNx_cast<int>(db) << 0) |
| 1409 | (0xFF << 24 ); |
| 1410 rgba.store(dst); |
| 1411 dst = SkTAddOffset<void>(dst, 4 * 4); |
| 1412 } |
| 1413 |
| 1414 transform_gamut(r, g, b, a, rXgXbX, rYgYbY, rZgZbZ, dr, dg, db, da); |
| 1415 translate_gamut(rTgTbT, dr, dg, db); |
| 1416 |
| 1417 dr = sk_linear_to_srgb_needs_trunc(dr); |
| 1418 dg = sk_linear_to_srgb_needs_trunc(dg); |
| 1419 db = sk_linear_to_srgb_needs_trunc(db); |
| 1420 |
| 1421 dr = sk_clamp_0_255(dr); |
| 1422 dg = sk_clamp_0_255(dg); |
| 1423 db = sk_clamp_0_255(db); |
| 1424 |
| 1425 Sk4i rgba = (SkNx_cast<int>(dr) << 16) |
| 1426 | (SkNx_cast<int>(dg) << 8) |
| 1427 | (SkNx_cast<int>(db) << 0) |
| 1428 | (0xFF << 24 ); |
| 1429 rgba.store(dst); |
| 1430 dst = SkTAddOffset<void>(dst, 4 * 4); |
| 1431 } |
| 1432 } |
| 1433 |
| 1434 |
| 1435 |
| 1436 |
| 1437 |
| 1438 |
| 1439 |
| 1440 |
| 1441 |
| 1442 |
| 1443 |
| 1444 |
| 1445 |
| 1446 |
| 1447 |
| 1448 |
| 1449 |
| 1450 |
| 1451 |
| 1452 |
| 1453 |
| 1454 |
| 1455 |
| 1456 |
| 1457 |
| 1458 |
| 1459 |
| 1460 |
| 1461 |
| 1462 |
| 1463 |
| 1464 |
| 1465 |
| 1466 |
| 1467 |
| 1468 |
| 1469 |
| 1470 |
| 1471 |
| 1472 |
| 1473 |
| 1474 |
| 1475 |
| 1476 |
| 1477 |
| 1478 |
| 1479 |
| 1480 |
| 1481 |
| 1482 |
| 1483 |
| 1484 |
| 1485 |
| 1486 |
| 1487 |
| 1488 |
| 1489 |
| 1490 |
| 1491 |
| 1492 |
| 1493 |
| 1494 |
| 1495 |
| 1496 |
| 1497 |
| 1498 |
1332 ////////////////////////////////////////////////////////////////////////////////
/////////////////// | 1499 ////////////////////////////////////////////////////////////////////////////////
/////////////////// |
1333 | 1500 |
1334 std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(const sk_sp<SkColorSpace>&
space) { | 1501 std::unique_ptr<SkColorSpaceXform> SlowIdentityXform(const sk_sp<SkColorSpace>&
space) { |
1335 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base | 1502 return std::unique_ptr<SkColorSpaceXform>(new SkColorSpaceXform_Base |
1336 <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> | 1503 <kTable_SrcGamma, kTable_DstGamma, kNone_ColorSpaceMatch> |
1337 (space, SkMatrix::I(), space)); | 1504 (space, SkMatrix::I(), space)); |
1338 } | 1505 } |
OLD | NEW |