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 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
67 } | 67 } |
68 | 68 |
69 inline bool matchesCURSignature(const char* contents) { | 69 inline bool matchesCURSignature(const char* contents) { |
70 return !memcmp(contents, "\x00\x00\x02\x00", 4); | 70 return !memcmp(contents, "\x00\x00\x02\x00", 4); |
71 } | 71 } |
72 | 72 |
73 inline bool matchesBMPSignature(const char* contents) { | 73 inline bool matchesBMPSignature(const char* contents) { |
74 return !memcmp(contents, "BM", 2); | 74 return !memcmp(contents, "BM", 2); |
75 } | 75 } |
76 | 76 |
77 // This needs to be updated if we ever add a matches*Signature() which requires
more characters. | 77 // This needs to be updated if we ever add a matches*Signature() which requires |
| 78 // more characters. |
78 static constexpr size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1; | 79 static constexpr size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1; |
79 | 80 |
80 std::unique_ptr<ImageDecoder> ImageDecoder::create( | 81 std::unique_ptr<ImageDecoder> ImageDecoder::create( |
81 PassRefPtr<SegmentReader> passData, | 82 PassRefPtr<SegmentReader> passData, |
82 bool dataComplete, | 83 bool dataComplete, |
83 AlphaOption alphaOption, | 84 AlphaOption alphaOption, |
84 GammaAndColorProfileOption colorOptions) { | 85 GammaAndColorProfileOption colorOptions) { |
85 RefPtr<SegmentReader> data = passData; | 86 RefPtr<SegmentReader> data = passData; |
86 | 87 |
87 // We need at least kLongestSignatureLength bytes to run the signature matcher
. | 88 // We need at least kLongestSignatureLength bytes to run the signature |
| 89 // matcher. |
88 if (data->size() < kLongestSignatureLength) | 90 if (data->size() < kLongestSignatureLength) |
89 return nullptr; | 91 return nullptr; |
90 | 92 |
91 const size_t maxDecodedBytes = | 93 const size_t maxDecodedBytes = |
92 Platform::current() ? Platform::current()->maxDecodedImageBytes() | 94 Platform::current() ? Platform::current()->maxDecodedImageBytes() |
93 : noDecodedImageByteLimit; | 95 : noDecodedImageByteLimit; |
94 | 96 |
95 // Access the first kLongestSignatureLength chars to sniff the signature. | 97 // Access the first kLongestSignatureLength chars to sniff the signature. |
96 // (note: FastSharedBufferReader only makes a copy if the bytes are segmented) | 98 // (note: FastSharedBufferReader only makes a copy if the bytes are segmented) |
97 char buffer[kLongestSignatureLength]; | 99 char buffer[kLongestSignatureLength]; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
248 | 250 |
249 // The starting state for this frame depends on the previous frame's | 251 // The starting state for this frame depends on the previous frame's |
250 // disposal method. | 252 // disposal method. |
251 size_t prevFrame = frameIndex - 1; | 253 size_t prevFrame = frameIndex - 1; |
252 const ImageFrame* prevBuffer = &m_frameBufferCache[prevFrame]; | 254 const ImageFrame* prevBuffer = &m_frameBufferCache[prevFrame]; |
253 | 255 |
254 switch (prevBuffer->getDisposalMethod()) { | 256 switch (prevBuffer->getDisposalMethod()) { |
255 case ImageFrame::DisposeNotSpecified: | 257 case ImageFrame::DisposeNotSpecified: |
256 case ImageFrame::DisposeKeep: | 258 case ImageFrame::DisposeKeep: |
257 // prevFrame will be used as the starting state for this frame. | 259 // prevFrame will be used as the starting state for this frame. |
258 // FIXME: Be even smarter by checking the frame sizes and/or alpha-contain
ing regions. | 260 // FIXME: Be even smarter by checking the frame sizes and/or |
| 261 // alpha-containing regions. |
259 return prevFrame; | 262 return prevFrame; |
260 case ImageFrame::DisposeOverwritePrevious: | 263 case ImageFrame::DisposeOverwritePrevious: |
261 // Frames that use the DisposeOverwritePrevious method are effectively | 264 // Frames that use the DisposeOverwritePrevious method are effectively |
262 // no-ops in terms of changing the starting state of a frame compared to | 265 // no-ops in terms of changing the starting state of a frame compared to |
263 // the starting state of the previous frame, so skip over them and | 266 // the starting state of the previous frame, so skip over them and |
264 // return the required previous frame of it. | 267 // return the required previous frame of it. |
265 return prevBuffer->requiredPreviousFrameIndex(); | 268 return prevBuffer->requiredPreviousFrameIndex(); |
266 case ImageFrame::DisposeOverwriteBgcolor: | 269 case ImageFrame::DisposeOverwriteBgcolor: |
267 // If the previous frame fills the whole image, then the current frame | 270 // If the previous frame fills the whole image, then the current frame |
268 // can be decoded alone. Likewise, if the previous frame could be | 271 // can be decoded alone. Likewise, if the previous frame could be |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 #endif // USE(QCMSLIB) | 333 #endif // USE(QCMSLIB) |
331 | 334 |
332 } // namespace | 335 } // namespace |
333 | 336 |
334 // static | 337 // static |
335 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { | 338 void ImageDecoder::setTargetColorProfile(const WebVector<char>& profile) { |
336 #if USE(QCMSLIB) | 339 #if USE(QCMSLIB) |
337 if (profile.isEmpty()) | 340 if (profile.isEmpty()) |
338 return; | 341 return; |
339 | 342 |
340 // Take a lock around initializing and accessing the global device color profi
le. | 343 // Take a lock around initializing and accessing the global device color |
| 344 // profile. |
341 SpinLock::Guard guard(gTargetColorProfileLock); | 345 SpinLock::Guard guard(gTargetColorProfileLock); |
342 | 346 |
343 // Layout tests expect that only the first call will take effect. | 347 // Layout tests expect that only the first call will take effect. |
344 if (gTargetColorProfile) | 348 if (gTargetColorProfile) |
345 return; | 349 return; |
346 | 350 |
347 { | 351 { |
348 sk_sp<SkColorSpace> colorSpace = | 352 sk_sp<SkColorSpace> colorSpace = |
349 SkColorSpace::NewICC(profile.data(), profile.size()); | 353 SkColorSpace::NewICC(profile.data(), profile.size()); |
350 BitmapImageMetrics::countGamma(colorSpace.get()); | 354 BitmapImageMetrics::countGamma(colorSpace.get()); |
(...skipping 12 matching lines...) Expand all Loading... |
363 } | 367 } |
364 | 368 |
365 qcms_profile_precache_output_transform(gTargetColorProfile); | 369 qcms_profile_precache_output_transform(gTargetColorProfile); |
366 #endif // USE(QCMSLIB) | 370 #endif // USE(QCMSLIB) |
367 } | 371 } |
368 | 372 |
369 void ImageDecoder::setColorProfileAndComputeTransform(const char* iccData, | 373 void ImageDecoder::setColorProfileAndComputeTransform(const char* iccData, |
370 unsigned iccLength, | 374 unsigned iccLength, |
371 bool hasAlpha, | 375 bool hasAlpha, |
372 bool useSRGB) { | 376 bool useSRGB) { |
373 // Sub-classes should not call this if they were instructed to ignore embedded
color profiles. | 377 // Sub-classes should not call this if they were instructed to ignore embedded |
| 378 // color profiles. |
374 DCHECK(!m_ignoreGammaAndColorProfile); | 379 DCHECK(!m_ignoreGammaAndColorProfile); |
375 | 380 |
376 m_colorProfile.assign(iccData, iccLength); | 381 m_colorProfile.assign(iccData, iccLength); |
377 m_hasColorProfile = true; | 382 m_hasColorProfile = true; |
378 | 383 |
379 // With color correct rendering, we use Skia instead of QCMS to color correct
images. | 384 // With color correct rendering, we use Skia instead of QCMS to color correct |
| 385 // images. |
380 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) | 386 if (RuntimeEnabledFeatures::colorCorrectRenderingEnabled()) |
381 return; | 387 return; |
382 | 388 |
383 #if USE(QCMSLIB) | 389 #if USE(QCMSLIB) |
384 m_sourceToOutputDeviceColorTransform.reset(); | 390 m_sourceToOutputDeviceColorTransform.reset(); |
385 | 391 |
386 // Create the input profile | 392 // Create the input profile |
387 QCMSProfileUniquePtr inputProfile; | 393 QCMSProfileUniquePtr inputProfile; |
388 if (useSRGB) { | 394 if (useSRGB) { |
389 inputProfile.reset(qcms_profile_sRGB()); | 395 inputProfile.reset(qcms_profile_sRGB()); |
390 } else { | 396 } else { |
391 // Only accept RGB color profiles from input class devices. | 397 // Only accept RGB color profiles from input class devices. |
392 if (iccLength < kIccColorProfileHeaderLength) | 398 if (iccLength < kIccColorProfileHeaderLength) |
393 return; | 399 return; |
394 if (!rgbColorProfile(iccData, iccLength)) | 400 if (!rgbColorProfile(iccData, iccLength)) |
395 return; | 401 return; |
396 if (!inputDeviceColorProfile(iccData, iccLength)) | 402 if (!inputDeviceColorProfile(iccData, iccLength)) |
397 return; | 403 return; |
398 inputProfile.reset(qcms_profile_from_memory(iccData, iccLength)); | 404 inputProfile.reset(qcms_profile_from_memory(iccData, iccLength)); |
399 } | 405 } |
400 if (!inputProfile) | 406 if (!inputProfile) |
401 return; | 407 return; |
402 | 408 |
403 // We currently only support color profiles for RGB profiled images. | 409 // We currently only support color profiles for RGB profiled images. |
404 ASSERT(rgbData == qcms_profile_get_color_space(inputProfile.get())); | 410 ASSERT(rgbData == qcms_profile_get_color_space(inputProfile.get())); |
405 | 411 |
406 // Take a lock around initializing and accessing the global device color profi
le. | 412 // Take a lock around initializing and accessing the global device color |
| 413 // profile. |
407 SpinLock::Guard guard(gTargetColorProfileLock); | 414 SpinLock::Guard guard(gTargetColorProfileLock); |
408 | 415 |
409 // Initialize the output device profile to sRGB if it has not yet been initial
ized. | 416 // Initialize the output device profile to sRGB if it has not yet been |
| 417 // initialized. |
410 if (!gTargetColorProfile) { | 418 if (!gTargetColorProfile) { |
411 gTargetColorProfile = qcms_profile_sRGB(); | 419 gTargetColorProfile = qcms_profile_sRGB(); |
412 qcms_profile_precache_output_transform(gTargetColorProfile); | 420 qcms_profile_precache_output_transform(gTargetColorProfile); |
413 } | 421 } |
414 | 422 |
415 if (qcms_profile_match(inputProfile.get(), gTargetColorProfile)) | 423 if (qcms_profile_match(inputProfile.get(), gTargetColorProfile)) |
416 return; | 424 return; |
417 | 425 |
418 qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; | 426 qcms_data_type dataFormat = hasAlpha ? QCMS_DATA_RGBA_8 : QCMS_DATA_RGB_8; |
419 | 427 |
420 // FIXME: Don't force perceptual intent if the image profile contains an inten
t. | 428 // FIXME: Don't force perceptual intent if the image profile contains an |
| 429 // intent. |
421 m_sourceToOutputDeviceColorTransform.reset( | 430 m_sourceToOutputDeviceColorTransform.reset( |
422 qcms_transform_create(inputProfile.get(), dataFormat, gTargetColorProfile, | 431 qcms_transform_create(inputProfile.get(), dataFormat, gTargetColorProfile, |
423 QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL)); | 432 QCMS_DATA_RGBA_8, QCMS_INTENT_PERCEPTUAL)); |
424 #endif // USE(QCMSLIB) | 433 #endif // USE(QCMSLIB) |
425 } | 434 } |
426 | 435 |
427 } // namespace blink | 436 } // namespace blink |
OLD | NEW |