OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. | 2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
3 * | 3 * |
4 * This library is free software; you can redistribute it and/or | 4 * This library is free software; you can redistribute it and/or |
5 * modify it under the terms of the GNU Library General Public | 5 * modify it under the terms of the GNU Library General Public |
6 * License as published by the Free Software Foundation; either | 6 * License as published by the Free Software Foundation; either |
7 * version 2 of the License, or (at your option) any later version. | 7 * version 2 of the License, or (at your option) any later version. |
8 * | 8 * |
9 * This library is distributed in the hope that it will be useful, | 9 * This library is distributed in the hope that it will be useful, |
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
(...skipping 17 matching lines...) Expand all Loading... | |
28 #include "platform/image-decoders/gif/GIFImageDecoder.h" | 28 #include "platform/image-decoders/gif/GIFImageDecoder.h" |
29 #include "platform/image-decoders/ico/ICOImageDecoder.h" | 29 #include "platform/image-decoders/ico/ICOImageDecoder.h" |
30 #include "platform/image-decoders/jpeg/JPEGImageDecoder.h" | 30 #include "platform/image-decoders/jpeg/JPEGImageDecoder.h" |
31 #include "platform/image-decoders/png/PNGImageDecoder.h" | 31 #include "platform/image-decoders/png/PNGImageDecoder.h" |
32 #include "platform/image-decoders/webp/WEBPImageDecoder.h" | 32 #include "platform/image-decoders/webp/WEBPImageDecoder.h" |
33 #include "wtf/PtrUtil.h" | 33 #include "wtf/PtrUtil.h" |
34 #include <memory> | 34 #include <memory> |
35 | 35 |
36 namespace blink { | 36 namespace blink { |
37 | 37 |
38 #if USE(QCMSLIB) | |
39 struct QCMSProfileDeleter { | |
40 void operator()(qcms_profile* profile) { | |
41 if (profile) | |
42 qcms_profile_release(profile); | |
43 } | |
44 }; | |
45 | |
46 using QCMSProfileUniquePtr = std::unique_ptr<qcms_profile, QCMSProfileDeleter>; | |
47 #endif // USE(QCMSLIB) | |
48 | |
49 inline bool matchesJPEGSignature(const char* contents) { | 38 inline bool matchesJPEGSignature(const char* contents) { |
50 return !memcmp(contents, "\xFF\xD8\xFF", 3); | 39 return !memcmp(contents, "\xFF\xD8\xFF", 3); |
51 } | 40 } |
52 | 41 |
53 inline bool matchesPNGSignature(const char* contents) { | 42 inline bool matchesPNGSignature(const char* contents) { |
54 return !memcmp(contents, "\x89PNG\r\n\x1A\n", 8); | 43 return !memcmp(contents, "\x89PNG\r\n\x1A\n", 8); |
55 } | 44 } |
56 | 45 |
57 inline bool matchesGIFSignature(const char* contents) { | 46 inline bool matchesGIFSignature(const char* contents) { |
58 return !memcmp(contents, "GIF87a", 6) || !memcmp(contents, "GIF89a", 6); | 47 return !memcmp(contents, "GIF87a", 6) || !memcmp(contents, "GIF89a", 6); |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
334 void* ImagePlanes::plane(int i) { | 323 void* ImagePlanes::plane(int i) { |
335 ASSERT((i >= 0) && i < 3); | 324 ASSERT((i >= 0) && i < 3); |
336 return m_planes[i]; | 325 return m_planes[i]; |
337 } | 326 } |
338 | 327 |
339 size_t ImagePlanes::rowBytes(int i) const { | 328 size_t ImagePlanes::rowBytes(int i) const { |
340 ASSERT((i >= 0) && i < 3); | 329 ASSERT((i >= 0) && i < 3); |
341 return m_rowBytes[i]; | 330 return m_rowBytes[i]; |
342 } | 331 } |
343 | 332 |
344 namespace { | 333 // The output device color space is global and shared across multiple threads. |
345 | 334 SpinLock gTargetColorSpaceLock; |
scroggo_chromium
2016/10/19 18:26:25
Why not leave these in an anonymous namespace?
msarett
2016/10/19 19:55:43
Didn't mean to remove this, adding it back.
| |
346 #if USE(QCMSLIB) | 335 SkColorSpace* gTargetColorSpace = nullptr; |
347 | |
348 const unsigned kIccColorProfileHeaderLength = 128; | |
349 | |
350 bool rgbColorProfile(const char* profileData, unsigned profileLength) { | |
351 DCHECK_GE(profileLength, kIccColorProfileHeaderLength); | |
352 | |
353 return !memcmp(&profileData[16], "RGB ", 4); | |
354 } | |
355 | |
356 bool inputDeviceColorProfile(const char* profileData, unsigned profileLength) { | |
357 DCHECK_GE(profileLength, kIccColorProfileHeaderLength); | |
358 | |
359 return !memcmp(&profileData[12], "mntr", 4) || | |
360 !memcmp(&profileData[12], "scnr", 4); | |
361 } | |
362 | |
363 // The output device color profile is global and shared across multiple threads. | |
364 SpinLock gTargetColorProfileLock; | |
365 qcms_profile* gTargetColorProfile = nullptr; | |
366 | |
367 #endif // USE(QCMSLIB) | |
368 | |
369 } // namespace | |
370 | 336 |
371 // static | 337 // static |
372 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { | 338 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { |
373 #if USE(QCMSLIB) | |
374 if (profile.isEmpty()) | 339 if (profile.isEmpty()) |
375 return; | 340 return; |
376 | 341 |
377 // Take a lock around initializing and accessing the global device color | 342 // Take a lock around initializing and accessing the global device color |
378 // profile. | 343 // profile. |
379 SpinLock::Guard guard(gTargetColorProfileLock); | 344 SpinLock::Guard guard(gTargetColorSpaceLock); |
380 | 345 |
381 // Layout tests expect that only the first call will take effect. | 346 // Layout tests expect that only the first call will take effect. |
382 if (gTargetColorProfile) | 347 if (gTargetColorSpace) |
383 return; | 348 return; |
384 | 349 |
385 { | 350 gTargetColorSpace = |
386 sk_sp<SkColorSpace> colorSpace = | 351 SkColorSpace::NewICC(profile.data(), profile.size()).release(); |
scroggo_chromium
2016/10/19 18:26:25
nit: Can this fit on one line?
msarett
2016/10/19 19:55:43
Autoformatter actually keeps forcing me to less th
| |
387 SkColorSpace::NewICC(profile.data(), profile.size()); | |
388 BitmapImageMetrics::countGamma(colorSpace.get()); | |
389 } | |
390 | 352 |
391 // FIXME: Add optional ICCv4 support and support for multiple monitors. | 353 // UMA statistics. |
392 gTargetColorProfile = | 354 BitmapImageMetrics::countGamma(gTargetColorSpace); |
393 qcms_profile_from_memory(profile.data(), profile.size()); | |
394 if (!gTargetColorProfile) | |
395 return; | |
396 | |
397 if (qcms_profile_is_bogus(gTargetColorProfile)) { | |
398 qcms_profile_release(gTargetColorProfile); | |
399 gTargetColorProfile = nullptr; | |
400 return; | |
401 } | |
402 | |
403 qcms_profile_precache_output_transform(gTargetColorProfile); | |
404 #endif // USE(QCMSLIB) | |
405 } | 355 } |
406 | 356 |
407 void ImageDecoder::setColorProfileAndComputeTransform(const char* iccData, | 357 void ImageDecoder::setColorSpaceAndComputeTransform(const char* iccData, |
408 unsigned iccLength, | 358 unsigned iccLength, |
409 bool hasAlpha, | 359 bool useSRGB) { |
410 bool useSRGB) { | |
411 // Sub-classes should not call this if they were instructed to ignore embedded | 360 // Sub-classes should not call this if they were instructed to ignore embedded |
412 // color profiles. | 361 // color profiles. |
413 DCHECK(!m_ignoreGammaAndColorProfile); | 362 DCHECK(!m_ignoreGammaAndColorProfile); |
414 | 363 |
415 m_colorProfile.assign(iccData, iccLength); | 364 m_colorProfile.assign(iccData, iccLength); |
416 m_hasColorProfile = true; | 365 m_hasColorProfile = true; |
417 | 366 |
418 // With color correct rendering, we use Skia instead of QCMS to color correct | 367 // With color correct rendering, we do not transform to the output color space |
419 // images. | 368 // at decode time. Instead, we tag the raw image pixels and pass the tagged |
369 // SkImage to Skia. | |
420 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 370 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
421 return; | 371 return; |
422 | 372 |
423 #if USE(QCMSLIB) | 373 m_sourceToOutputDeviceColorTransform = nullptr; |
424 m_sourceToOutputDeviceColorTransform.reset(); | |
425 | 374 |
426 // Create the input profile | 375 // Create the input profile. |
427 QCMSProfileUniquePtr inputProfile; | 376 sk_sp<SkColorSpace> srcSpace = nullptr; |
428 if (useSRGB) { | 377 if (useSRGB) { |
429 inputProfile.reset(qcms_profile_sRGB()); | 378 srcSpace = SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named); |
430 } else { | 379 } else { |
431 // Only accept RGB color profiles from input class devices. | 380 srcSpace = SkColorSpace::NewICC(iccData, iccLength); |
432 if (iccLength < kIccColorProfileHeaderLength) | |
433 return; | |
434 if (!rgbColorProfile(iccData, iccLength)) | |
435 return; | |
436 if (!inputDeviceColorProfile(iccData, iccLength)) | |
437 return; | |
438 inputProfile.reset(qcms_profile_from_memory(iccData, iccLength)); | |
439 } | 381 } |
440 if (!inputProfile) | 382 |
383 if (!srcSpace) | |
441 return; | 384 return; |
442 | 385 |
443 // We currently only support color profiles for RGB profiled images. | |
444 ASSERT(rgbData == qcms_profile_get_color_space(inputProfile.get())); | |
445 | |
446 // Take a lock around initializing and accessing the global device color | 386 // Take a lock around initializing and accessing the global device color |
447 // profile. | 387 // profile. |
448 SpinLock::Guard guard(gTargetColorProfileLock); | 388 SpinLock::Guard guard(gTargetColorSpaceLock); |
449 | 389 |
450 // Initialize the output device profile to sRGB if it has not yet been | 390 // Initialize the output device profile to sRGB if it has not yet been |
451 // initialized. | 391 // initialized. |
452 if (!gTargetColorProfile) { | 392 if (!gTargetColorSpace) { |
453 gTargetColorProfile = qcms_profile_sRGB(); | 393 gTargetColorSpace = |
scroggo_chromium
2016/10/19 18:26:25
nit: Can this fit on one line?
msarett
2016/10/19 19:55:43
Autoformatter puts it on two lines.
| |
454 qcms_profile_precache_output_transform(gTargetColorProfile); | 394 SkColorSpace::NewNamed(SkColorSpace::kSRGB_Named).release(); |
455 } | 395 } |
456 | 396 |
457 if (qcms_profile_match(inputProfile.get(), gTargetColorProfile)) | 397 if (SkColorSpace::Equals(srcSpace.get(), gTargetColorSpace)) { |
458 return; | 398 return; |
399 } | |
459 | 400 |
460 qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; | 401 m_sourceToOutputDeviceColorTransform = |
461 | 402 SkColorSpaceXform::New(srcSpace.get(), gTargetColorSpace); |
462 // FIXME: Don't force perceptual intent if the image profile contains an | |
463 // intent. | |
464 m_sourceToOutputDeviceColorTransform.reset( | |
465 qcms_transform_create(inputProfile.get(), dataFormat, gTargetColorProfile, | |
466 QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL)); | |
467 #endif // USE(QCMSLIB) | |
468 } | 403 } |
469 | 404 |
470 } // namespace blink | 405 } // namespace blink |
OLD | NEW |