1 /*
2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21 #include "third_party/blink/renderer/platform/image-decoders/image_decoder.h"
22
23 #include <memory>
24
25 #include "base/numerics/safe_conversions.h"
26 #include "base/sys_byteorder.h"
27 #include "build/build_config.h"
28 #include "media/media_buildflags.h"
29 #include "third_party/blink/public/common/features.h"
30 #include "third_party/blink/public/platform/platform.h"
31 #include "third_party/blink/renderer/platform/image-decoders/bmp/bmp_image_decoder.h"
32 #include "third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader.h"
33 #include "third_party/blink/renderer/platform/image-decoders/gif/gif_image_decoder.h"
34 #include "third_party/blink/renderer/platform/image-decoders/ico/ico_image_decoder.h"
35 #include "third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.h"
36 #include "third_party/blink/renderer/platform/image-decoders/png/png_image_decoder.h"
37 #include "third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h"
38 #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"
39 #include "third_party/blink/renderer/platform/network/mime/mime_type_registry.h"
40 #include "ui/gfx/geometry/size.h"
41
42 #if BUILDFLAG(ENABLE_AV1_DECODER)
43 #include "third_party/blink/renderer/platform/image-decoders/avif/avif_image_decoder.h"
44 #endif
45
46 namespace blink {
47
48 namespace {
49
FileExtensionToImageType(String image_extension)50 cc::ImageType FileExtensionToImageType(String image_extension) {
51 if (image_extension == "png")
52 return cc::ImageType::kPNG;
53 if (image_extension == "jpg")
54 return cc::ImageType::kJPEG;
55 if (image_extension == "webp")
56 return cc::ImageType::kWEBP;
57 if (image_extension == "gif")
58 return cc::ImageType::kGIF;
59 if (image_extension == "ico")
60 return cc::ImageType::kICO;
61 if (image_extension == "bmp")
62 return cc::ImageType::kBMP;
63 #if BUILDFLAG(ENABLE_AV1_DECODER)
64 if (image_extension == "avif")
65 return cc::ImageType::kAVIF;
66 #endif
67 return cc::ImageType::kInvalid;
68 }
69
CalculateMaxDecodedBytes(ImageDecoder::HighBitDepthDecodingOption high_bit_depth_decoding_option,const SkISize & desired_size)70 size_t CalculateMaxDecodedBytes(
71 ImageDecoder::HighBitDepthDecodingOption high_bit_depth_decoding_option,
72 const SkISize& desired_size) {
73 const size_t max_decoded_bytes =
74 Platform::Current() ? Platform::Current()->MaxDecodedImageBytes()
75 : ImageDecoder::kNoDecodedImageByteLimit;
76 if (desired_size.isEmpty())
77 return max_decoded_bytes;
78
79 const size_t num_pixels = desired_size.width() * desired_size.height();
80 if (high_bit_depth_decoding_option == ImageDecoder::kDefaultBitDepth)
81 return std::min(4 * num_pixels, max_decoded_bytes);
82
83 // ImageDecoder::kHighBitDepthToHalfFloat
84 return std::min(8 * num_pixels, max_decoded_bytes);
85 }
86
MatchesJPEGSignature(const char * contents)87 inline bool MatchesJPEGSignature(const char* contents) {
88 return !memcmp(contents, "\xFF\xD8\xFF", 3);
89 }
90
MatchesPNGSignature(const char * contents)91 inline bool MatchesPNGSignature(const char* contents) {
92 return !memcmp(contents, "\x89PNG\r\n\x1A\n", 8);
93 }
94
MatchesGIFSignature(const char * contents)95 inline bool MatchesGIFSignature(const char* contents) {
96 return !memcmp(contents, "GIF87a", 6) || !memcmp(contents, "GIF89a", 6);
97 }
98
MatchesWebPSignature(const char * contents)99 inline bool MatchesWebPSignature(const char* contents) {
100 return !memcmp(contents, "RIFF", 4) && !memcmp(contents + 8, "WEBPVP", 6);
101 }
102
MatchesICOSignature(const char * contents)103 inline bool MatchesICOSignature(const char* contents) {
104 return !memcmp(contents, "\x00\x00\x01\x00", 4);
105 }
106
MatchesCURSignature(const char * contents)107 inline bool MatchesCURSignature(const char* contents) {
108 return !memcmp(contents, "\x00\x00\x02\x00", 4);
109 }
110
MatchesBMPSignature(const char * contents)111 inline bool MatchesBMPSignature(const char* contents) {
112 return !memcmp(contents, "BM", 2) || !memcmp(contents, "BA", 2);
113 }
114
115 constexpr size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1;
116
117 // static
SniffMimeTypeInternal(scoped_refptr<SegmentReader> reader)118 String SniffMimeTypeInternal(scoped_refptr<SegmentReader> reader) {
119 // At least kLongestSignatureLength bytes are needed to sniff the signature.
120 if (reader->size() < kLongestSignatureLength)
121 return String();
122
123 // Access the first kLongestSignatureLength chars to sniff the signature.
124 // (note: FastSharedBufferReader only makes a copy if the bytes are segmented)
125 char buffer[kLongestSignatureLength];
126 const FastSharedBufferReader fast_reader(reader);
127 const char* contents =
128 fast_reader.GetConsecutiveData(0, kLongestSignatureLength, buffer);
129
130 if (MatchesJPEGSignature(contents))
131 return "image/jpeg";
132 if (MatchesPNGSignature(contents))
133 return "image/png";
134 if (MatchesGIFSignature(contents))
135 return "image/gif";
136 if (MatchesWebPSignature(contents))
137 return "image/webp";
138 if (MatchesICOSignature(contents) || MatchesCURSignature(contents))
139 return "image/x-icon";
140 if (MatchesBMPSignature(contents))
141 return "image/bmp";
142 #if BUILDFLAG(ENABLE_AV1_DECODER)
143 if (base::FeatureList::IsEnabled(features::kAVIF) &&
144 AVIFImageDecoder::MatchesAVIFSignature(fast_reader)) {
145 return "image/avif";
146 }
147 #endif
148
149 return String();
150 }
151
152 } // namespace
153
154 const size_t ImageDecoder::kNoDecodedImageByteLimit =
155 Platform::kNoDecodedImageByteLimit;
156
Create(scoped_refptr<SegmentReader> data,bool data_complete,AlphaOption alpha_option,HighBitDepthDecodingOption high_bit_depth_decoding_option,const ColorBehavior & color_behavior,const SkISize & desired_size,AnimationOption animation_option)157 std::unique_ptr<ImageDecoder> ImageDecoder::Create(
158 scoped_refptr<SegmentReader> data,
159 bool data_complete,
160 AlphaOption alpha_option,
161 HighBitDepthDecodingOption high_bit_depth_decoding_option,
162 const ColorBehavior& color_behavior,
163 const SkISize& desired_size,
164 AnimationOption animation_option) {
165 auto type = SniffMimeTypeInternal(data);
166 if (type.IsEmpty())
167 return nullptr;
168
169 return CreateByMimeType(type, std::move(data), data_complete, alpha_option,
170 high_bit_depth_decoding_option, color_behavior,
171 desired_size, animation_option);
172 }
173
CreateByMimeType(String mime_type,scoped_refptr<SegmentReader> data,bool data_complete,AlphaOption alpha_option,HighBitDepthDecodingOption high_bit_depth_decoding_option,const ColorBehavior & color_behavior,const SkISize & desired_size,AnimationOption animation_option)174 std::unique_ptr<ImageDecoder> ImageDecoder::CreateByMimeType(
175 String mime_type,
176 scoped_refptr<SegmentReader> data,
177 bool data_complete,
178 AlphaOption alpha_option,
179 HighBitDepthDecodingOption high_bit_depth_decoding_option,
180 const ColorBehavior& color_behavior,
181 const SkISize& desired_size,
182 AnimationOption animation_option) {
183 const size_t max_decoded_bytes =
184 CalculateMaxDecodedBytes(high_bit_depth_decoding_option, desired_size);
185
186 // Note: The mime types below should match those supported by
187 // MimeUtil::IsSupportedImageMimeType().
188 std::unique_ptr<ImageDecoder> decoder;
189 if (mime_type == "image/jpeg" || mime_type == "image/pjpeg" ||
190 mime_type == "image/jpg") {
191 decoder = std::make_unique<JPEGImageDecoder>(alpha_option, color_behavior,
192 max_decoded_bytes);
193 } else if (mime_type == "image/png" || mime_type == "image/x-png" ||
194 mime_type == "image/apng") {
195 decoder = std::make_unique<PNGImageDecoder>(
196 alpha_option, high_bit_depth_decoding_option, color_behavior,
197 max_decoded_bytes);
198 } else if (mime_type == "image/gif") {
199 decoder = std::make_unique<GIFImageDecoder>(alpha_option, color_behavior,
200 max_decoded_bytes);
201 } else if (mime_type == "image/webp") {
202 decoder = std::make_unique<WEBPImageDecoder>(alpha_option, color_behavior,
203 max_decoded_bytes);
204 } else if (mime_type == "image/x-icon" ||
205 mime_type == "image/vnd.microsoft.icon") {
206 decoder = std::make_unique<ICOImageDecoder>(alpha_option, color_behavior,
207 max_decoded_bytes);
208 } else if (mime_type == "image/bmp" || mime_type == "image/x-xbitmap") {
209 decoder = std::make_unique<BMPImageDecoder>(alpha_option, color_behavior,
210 max_decoded_bytes);
211 #if BUILDFLAG(ENABLE_AV1_DECODER)
212 } else if (base::FeatureList::IsEnabled(features::kAVIF) &&
213 mime_type == "image/avif") {
214 decoder = std::make_unique<AVIFImageDecoder>(
215 alpha_option, high_bit_depth_decoding_option, color_behavior,
216 max_decoded_bytes, animation_option);
217 #endif
218 }
219
220 if (decoder)
221 decoder->SetData(std::move(data), data_complete);
222
223 return decoder;
224 }
225
HasSufficientDataToSniffMimeType(const SharedBuffer & data)226 bool ImageDecoder::HasSufficientDataToSniffMimeType(const SharedBuffer& data) {
227 // At least kLongestSignatureLength bytes are needed to sniff the signature.
228 if (data.size() < kLongestSignatureLength)
229 return false;
230
231 #if BUILDFLAG(ENABLE_AV1_DECODER)
232 if (base::FeatureList::IsEnabled(features::kAVIF)) {
233 // Check for an ISO BMFF File Type Box. Assume that 'largesize' is not used.
234 // The first eight bytes would be a big-endian 32-bit unsigned integer
235 // 'size' and a four-byte 'type'.
236 struct {
237 uint32_t size; // unsigned int(32) size;
238 char type[4]; // unsigned int(32) type = boxtype;
239 } box;
240 static_assert(sizeof(box) == 8, "");
241 static_assert(8 <= kLongestSignatureLength, "");
242 bool ok = data.GetBytes(&box, 8u);
243 DCHECK(ok);
244 if (memcmp(box.type, "ftyp", 4) == 0) {
245 // Returns whether we have received the File Type Box in its entirety.
246 box.size = base::NetToHost32(box.size);
247 return box.size <= data.size();
248 }
249 }
250 #endif
251 return true;
252 }
253
254 // static
SniffMimeType(scoped_refptr<SharedBuffer> image_data)255 String ImageDecoder::SniffMimeType(scoped_refptr<SharedBuffer> image_data) {
256 return SniffMimeTypeInternal(
257 SegmentReader::CreateFromSharedBuffer(std::move(image_data)));
258 }
259
260 // static
GetCompressionFormat(scoped_refptr<SharedBuffer> image_data,String mime_type)261 ImageDecoder::CompressionFormat ImageDecoder::GetCompressionFormat(
262 scoped_refptr<SharedBuffer> image_data,
263 String mime_type) {
264 // Attempt to sniff the image content to determine the true MIME type of the
265 // image, and fall back on the provided MIME type if this is not possible.
266 //
267 // Note that if the type cannot be sniffed AND the provided type is incorrect
268 // (for example, due to a misconfigured web server), then it is possible that
269 // the wrong compression format will be returned. However, this case should be
270 // exceedingly rare.
271 if (image_data && HasSufficientDataToSniffMimeType(*image_data.get()))
272 mime_type = SniffMimeType(image_data);
273 if (!mime_type)
274 return kUndefinedFormat;
275
276 // Attempt to sniff whether a WebP image is using a lossy or lossless
277 // compression algorithm. Note: Will return kWebPAnimationFormat in the case
278 // of an animated WebP image.
279 size_t available_data = image_data ? image_data->size() : 0;
280 if (EqualIgnoringASCIICase(mime_type, "image/webp") && available_data >= 16) {
281 // Attempt to sniff only 8 bytes (the second half of the first 16). This
282 // will be sufficient to determine lossy vs. lossless in most WebP images
283 // (all but the extended format).
284 const FastSharedBufferReader fast_reader(
285 SegmentReader::CreateFromSharedBuffer(image_data));
286 char buffer[8];
287 const unsigned char* contents = reinterpret_cast<const unsigned char*>(
288 fast_reader.GetConsecutiveData(8, 8, buffer));
289 if (!memcmp(contents, "WEBPVP8 ", 8)) {
290 // Simple lossy WebP format.
291 return kLossyFormat;
292 }
293 if (!memcmp(contents, "WEBPVP8L", 8)) {
294 // Simple Lossless WebP format.
295 return kLosslessFormat;
296 }
297 if (!memcmp(contents, "WEBPVP8X", 8)) {
298 // Extended WebP format; more content will need to be sniffed to make a
299 // determination.
300 std::unique_ptr<char[]> long_buffer(new char[available_data]);
301 contents = reinterpret_cast<const unsigned char*>(
302 fast_reader.GetConsecutiveData(0, available_data, long_buffer.get()));
303 WebPBitstreamFeatures webp_features{};
304 VP8StatusCode status =
305 WebPGetFeatures(contents, available_data, &webp_features);
306 // It is possible that there is not have enough image data available to
307 // make a determination.
308 if (status == VP8_STATUS_OK) {
309 DCHECK_LT(webp_features.format,
310 CompressionFormat::kWebPAnimationFormat);
311 return webp_features.has_animation
312 ? CompressionFormat::kWebPAnimationFormat
313 : static_cast<CompressionFormat>(webp_features.format);
314 }
315 DCHECK_EQ(status, VP8_STATUS_NOT_ENOUGH_DATA);
316 } else {
317 NOTREACHED();
318 }
319 }
320
321 #if BUILDFLAG(ENABLE_AV1_DECODER)
322 // Attempt to sniff whether an AVIF image is using a lossy or lossless
323 // compression algorithm.
324 // TODO(wtc): Implement this. Figure out whether to return kUndefinedFormat or
325 // a new kAVIFAnimationFormat in the case of an animated AVIF image.
326 if (base::FeatureList::IsEnabled(features::kAVIF) &&
327 EqualIgnoringASCIICase(mime_type, "image/avif")) {
328 return kLossyFormat;
329 }
330 #endif
331
332 if (MIMETypeRegistry::IsLossyImageMIMEType(mime_type))
333 return kLossyFormat;
334 if (MIMETypeRegistry::IsLosslessImageMIMEType(mime_type))
335 return kLosslessFormat;
336
337 return kUndefinedFormat;
338 }
339
IsSizeAvailable()340 bool ImageDecoder::IsSizeAvailable() {
341 if (failed_)
342 return false;
343 if (!size_available_)
344 DecodeSize();
345
346 if (!IsDecodedSizeAvailable())
347 return false;
348
349 #if defined(OS_FUCHSIA)
350 unsigned decoded_bytes_per_pixel = 4;
351 if (ImageIsHighBitDepth() &&
352 high_bit_depth_decoding_option_ == kHighBitDepthToHalfFloat) {
353 decoded_bytes_per_pixel = 8;
354 }
355
356 const IntSize size = DecodedSize();
357 const size_t decoded_size_bytes =
358 size.Width() * size.Height() * decoded_bytes_per_pixel;
359 if (decoded_size_bytes > max_decoded_bytes_) {
360 LOG(WARNING) << "Blocked decode of oversized image: " << size.Width() << "x"
361 << size.Height();
362 return SetFailed();
363 }
364 #endif
365
366 return true;
367 }
368
MakeMetadataForDecodeAcceleration() const369 cc::ImageHeaderMetadata ImageDecoder::MakeMetadataForDecodeAcceleration()
370 const {
371 DCHECK(IsDecodedSizeAvailable());
372 cc::ImageHeaderMetadata image_metadata{};
373 image_metadata.image_type = FileExtensionToImageType(FilenameExtension());
374 image_metadata.yuv_subsampling = GetYUVSubsampling();
375 image_metadata.image_size = static_cast<gfx::Size>(size_);
376 image_metadata.has_embedded_color_profile = HasEmbeddedColorProfile();
377 return image_metadata;
378 }
379
FrameCount()380 size_t ImageDecoder::FrameCount() {
381 const size_t old_size = frame_buffer_cache_.size();
382 const size_t new_size = DecodeFrameCount();
383 if (old_size != new_size) {
384 frame_buffer_cache_.resize(new_size);
385 for (size_t i = old_size; i < new_size; ++i) {
386 frame_buffer_cache_[i].SetPremultiplyAlpha(premultiply_alpha_);
387 InitializeNewFrame(i);
388 }
389 }
390 return new_size;
391 }
392
DecodeFrameBufferAtIndex(size_t index)393 ImageFrame* ImageDecoder::DecodeFrameBufferAtIndex(size_t index) {
394 TRACE_EVENT0("blink", "ImageDecoder::DecodeFrameBufferAtIndex");
395
396 if (index >= FrameCount())
397 return nullptr;
398 ImageFrame* frame = &frame_buffer_cache_[index];
399 if (frame->GetStatus() != ImageFrame::kFrameComplete) {
400 TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "Decode Image",
401 "imageType", FilenameExtension().Ascii());
402 Decode(index);
403 }
404
405 frame->NotifyBitmapIfPixelsChanged();
406 return frame;
407 }
408
FrameHasAlphaAtIndex(size_t index) const409 bool ImageDecoder::FrameHasAlphaAtIndex(size_t index) const {
410 return !FrameIsReceivedAtIndex(index) ||
411 frame_buffer_cache_[index].HasAlpha();
412 }
413
FrameIsReceivedAtIndex(size_t index) const414 bool ImageDecoder::FrameIsReceivedAtIndex(size_t index) const {
415 // Animated images override this method to return the status based on the data
416 // received for the queried frame.
417 return IsAllDataReceived();
418 }
419
FrameIsDecodedAtIndex(size_t index) const420 bool ImageDecoder::FrameIsDecodedAtIndex(size_t index) const {
421 return index < frame_buffer_cache_.size() &&
422 frame_buffer_cache_[index].GetStatus() == ImageFrame::kFrameComplete;
423 }
424
FrameBytesAtIndex(size_t index) const425 size_t ImageDecoder::FrameBytesAtIndex(size_t index) const {
426 if (index >= frame_buffer_cache_.size() ||
427 frame_buffer_cache_[index].GetStatus() == ImageFrame::kFrameEmpty)
428 return 0;
429
430 size_t decoded_bytes_per_pixel = 4;
431 if (frame_buffer_cache_[index].GetPixelFormat() ==
432 ImageFrame::PixelFormat::kRGBA_F16) {
433 decoded_bytes_per_pixel = 8;
434 }
435 IntSize size = FrameSizeAtIndex(index);
436 base::CheckedNumeric<size_t> area = size.Width();
437 area *= size.Height();
438 area *= decoded_bytes_per_pixel;
439 return area.ValueOrDie();
440 }
441
ClearCacheExceptFrame(size_t clear_except_frame)442 size_t ImageDecoder::ClearCacheExceptFrame(size_t clear_except_frame) {
443 // Don't clear if there are no frames or only one frame.
444 if (frame_buffer_cache_.size() <= 1)
445 return 0;
446
447 // We expect that after this call, we'll be asked to decode frames after this
448 // one. So we want to avoid clearing frames such that those requests would
449 // force re-decoding from the beginning of the image. There are two cases in
450 // which preserving |clear_except_frame| is not enough to avoid that:
451 //
452 // 1. |clear_except_frame| is not yet sufficiently decoded to decode
453 // subsequent frames. We need the previous frame to sufficiently decode
454 // this frame.
455 // 2. The disposal method of |clear_except_frame| is DisposeOverwritePrevious.
456 // In that case, we need to keep the required previous frame in the cache
457 // to prevent re-decoding that frame when |clear_except_frame| is disposed.
458 //
459 // If either 1 or 2 is true, store the required previous frame in
460 // |clear_except_frame2| so it won't be cleared.
461 size_t clear_except_frame2 = kNotFound;
462 if (clear_except_frame < frame_buffer_cache_.size()) {
463 const ImageFrame& frame = frame_buffer_cache_[clear_except_frame];
464 if (!FrameStatusSufficientForSuccessors(clear_except_frame) ||
465 frame.GetDisposalMethod() == ImageFrame::kDisposeOverwritePrevious)
466 clear_except_frame2 = frame.RequiredPreviousFrameIndex();
467 }
468
469 // Now |clear_except_frame2| indicates the frame that |clear_except_frame|
470 // depends on, as described above. But if decoding is skipping forward past
471 // intermediate frames, this frame may be insufficiently decoded. So we need
472 // to keep traversing back through the required previous frames until we find
473 // the nearest ancestor that is sufficiently decoded. Preserving that will
474 // minimize the amount of future decoding needed.
475 while (clear_except_frame2 < frame_buffer_cache_.size() &&
476 !FrameStatusSufficientForSuccessors(clear_except_frame2)) {
477 clear_except_frame2 =
478 frame_buffer_cache_[clear_except_frame2].RequiredPreviousFrameIndex();
479 }
480
481 return ClearCacheExceptTwoFrames(clear_except_frame, clear_except_frame2);
482 }
483
ClearCacheExceptTwoFrames(size_t clear_except_frame1,size_t clear_except_frame2)484 size_t ImageDecoder::ClearCacheExceptTwoFrames(size_t clear_except_frame1,
485 size_t clear_except_frame2) {
486 size_t frame_bytes_cleared = 0;
487 for (size_t i = 0; i < frame_buffer_cache_.size(); ++i) {
488 if (frame_buffer_cache_[i].GetStatus() != ImageFrame::kFrameEmpty &&
489 i != clear_except_frame1 && i != clear_except_frame2) {
490 frame_bytes_cleared += FrameBytesAtIndex(i);
491 ClearFrameBuffer(i);
492 }
493 }
494 return frame_bytes_cleared;
495 }
496
ClearFrameBuffer(size_t frame_index)497 void ImageDecoder::ClearFrameBuffer(size_t frame_index) {
498 frame_buffer_cache_[frame_index].ClearPixelData();
499 }
500
FindFramesToDecode(size_t index) const501 Vector<size_t> ImageDecoder::FindFramesToDecode(size_t index) const {
502 DCHECK_LT(index, frame_buffer_cache_.size());
503
504 Vector<size_t> frames_to_decode;
505 do {
506 frames_to_decode.push_back(index);
507 index = frame_buffer_cache_[index].RequiredPreviousFrameIndex();
508 } while (index != kNotFound && frame_buffer_cache_[index].GetStatus() !=
509 ImageFrame::kFrameComplete);
510 return frames_to_decode;
511 }
512
PostDecodeProcessing(size_t index)513 bool ImageDecoder::PostDecodeProcessing(size_t index) {
514 DCHECK(index < frame_buffer_cache_.size());
515
516 if (frame_buffer_cache_[index].GetStatus() != ImageFrame::kFrameComplete)
517 return false;
518
519 if (purge_aggressively_)
520 ClearCacheExceptFrame(index);
521
522 return true;
523 }
524
CorrectAlphaWhenFrameBufferSawNoAlpha(size_t index)525 void ImageDecoder::CorrectAlphaWhenFrameBufferSawNoAlpha(size_t index) {
526 DCHECK(index < frame_buffer_cache_.size());
527 ImageFrame& buffer = frame_buffer_cache_[index];
528
529 // When this frame spans the entire image rect we can SetHasAlpha to false,
530 // since there are logically no transparent pixels outside of the frame rect.
531 if (buffer.OriginalFrameRect().Contains(IntRect(IntPoint(), Size()))) {
532 buffer.SetHasAlpha(false);
533 buffer.SetRequiredPreviousFrameIndex(kNotFound);
534 } else if (buffer.RequiredPreviousFrameIndex() != kNotFound) {
535 // When the frame rect does not span the entire image rect, and it does
536 // *not* have a required previous frame, the pixels outside of the frame
537 // rect will be fully transparent, so we shoudn't SetHasAlpha to false.
538 //
539 // It is a tricky case when the frame does have a required previous frame.
540 // The frame does not have alpha only if everywhere outside its rect
541 // doesn't have alpha. To know whether this is true, we check the start
542 // state of the frame -- if it doesn't have alpha, we're safe.
543 //
544 // We first check that the required previous frame does not have
545 // DisposeOverWritePrevious as its disposal method - this should never
546 // happen, since the required frame should in that case be the required
547 // frame of this frame's required frame.
548 //
549 // If |prev_buffer| is DisposeNotSpecified or DisposeKeep, |buffer| has no
550 // alpha if |prev_buffer| had no alpha. Since InitFrameBuffer() already
551 // copied the alpha state, there's nothing to do here.
552 //
553 // The only remaining case is a DisposeOverwriteBgcolor frame. If
554 // it had no alpha, and its rect is contained in the current frame's
555 // rect, we know the current frame has no alpha.
556 //
557 // For DisposeNotSpecified, DisposeKeep and DisposeOverwriteBgcolor there
558 // is one situation that is not taken into account - when |prev_buffer|
559 // *does* have alpha, but only in the frame rect of |buffer|, we can still
560 // say that this frame has no alpha. However, to determine this, we
561 // potentially need to analyze all image pixels of |prev_buffer|, which is
562 // too computationally expensive.
563 const ImageFrame* prev_buffer =
564 &frame_buffer_cache_[buffer.RequiredPreviousFrameIndex()];
565 DCHECK(prev_buffer->GetDisposalMethod() !=
566 ImageFrame::kDisposeOverwritePrevious);
567
568 if ((prev_buffer->GetDisposalMethod() ==
569 ImageFrame::kDisposeOverwriteBgcolor) &&
570 !prev_buffer->HasAlpha() &&
571 buffer.OriginalFrameRect().Contains(prev_buffer->OriginalFrameRect()))
572 buffer.SetHasAlpha(false);
573 }
574 }
575
InitFrameBuffer(size_t frame_index)576 bool ImageDecoder::InitFrameBuffer(size_t frame_index) {
577 DCHECK(frame_index < frame_buffer_cache_.size());
578
579 ImageFrame* const buffer = &frame_buffer_cache_[frame_index];
580
581 // If the frame is already initialized, return true.
582 if (buffer->GetStatus() != ImageFrame::kFrameEmpty)
583 return true;
584
585 size_t required_previous_frame_index = buffer->RequiredPreviousFrameIndex();
586 if (required_previous_frame_index == kNotFound) {
587 // This frame doesn't rely on any previous data.
588 if (!buffer->AllocatePixelData(Size().Width(), Size().Height(),
589 ColorSpaceForSkImages())) {
590 return false;
591 }
592 buffer->ZeroFillPixelData();
593 } else {
594 ImageFrame* const prev_buffer =
595 &frame_buffer_cache_[required_previous_frame_index];
596 DCHECK(prev_buffer->GetStatus() == ImageFrame::kFrameComplete);
597
598 // We try to reuse |prev_buffer| as starting state to avoid copying.
599 // If CanReusePreviousFrameBuffer returns false, we must copy the data since
600 // |prev_buffer| is necessary to decode this or later frames. In that case,
601 // copy the data instead.
602 if ((!CanReusePreviousFrameBuffer(frame_index) ||
603 !buffer->TakeBitmapDataIfWritable(prev_buffer)) &&
604 !buffer->CopyBitmapData(*prev_buffer))
605 return false;
606
607 if (prev_buffer->GetDisposalMethod() ==
608 ImageFrame::kDisposeOverwriteBgcolor) {
609 // We want to clear the previous frame to transparent, without
610 // affecting pixels in the image outside of the frame.
611 const IntRect& prev_rect = prev_buffer->OriginalFrameRect();
612 DCHECK(!prev_rect.Contains(IntRect(IntPoint(), Size())));
613 buffer->ZeroFillFrameRect(prev_rect);
614 }
615 }
616
617 DCHECK_EQ(high_bit_depth_decoding_option_ == kHighBitDepthToHalfFloat &&
618 ImageIsHighBitDepth(),
619 buffer->GetPixelFormat() == ImageFrame::kRGBA_F16);
620
621 OnInitFrameBuffer(frame_index);
622
623 // Update our status to be partially complete.
624 buffer->SetStatus(ImageFrame::kFramePartial);
625
626 return true;
627 }
628
UpdateAggressivePurging(size_t index)629 void ImageDecoder::UpdateAggressivePurging(size_t index) {
630 if (purge_aggressively_)
631 return;
632
633 // We don't want to cache so much that we cause a memory issue.
634 //
635 // If we used a LRU cache we would fill it and then on next animation loop
636 // we would need to decode all the frames again -- the LRU would give no
637 // benefit and would consume more memory.
638 // So instead, simply purge unused frames if caching all of the frames of
639 // the image would use more memory than the image decoder is allowed
640 // (|max_decoded_bytes|) or would overflow 32 bits..
641 //
642 // As we decode we will learn the total number of frames, and thus total
643 // possible image memory used.
644
645 size_t decoded_bytes_per_pixel = 4;
646
647 if (frame_buffer_cache_.size() && frame_buffer_cache_[0].GetPixelFormat() ==
648 ImageFrame::PixelFormat::kRGBA_F16) {
649 decoded_bytes_per_pixel = 8;
650 }
651 const uint64_t frame_memory_usage =
652 DecodedSize().Area() * decoded_bytes_per_pixel;
653
654 // This condition never fails in the current code. Our existing image decoders
655 // parse for the image size and SetFailed() if that size overflows
656 DCHECK_EQ(frame_memory_usage / decoded_bytes_per_pixel, DecodedSize().Area());
657
658 const uint64_t total_memory_usage = frame_memory_usage * index;
659 if (total_memory_usage / frame_memory_usage != index) { // overflow occurred
660 purge_aggressively_ = true;
661 return;
662 }
663
664 if (total_memory_usage > max_decoded_bytes_) {
665 purge_aggressively_ = true;
666 }
667 }
668
FindRequiredPreviousFrame(size_t frame_index,bool frame_rect_is_opaque)669 size_t ImageDecoder::FindRequiredPreviousFrame(size_t frame_index,
670 bool frame_rect_is_opaque) {
671 DCHECK_LT(frame_index, frame_buffer_cache_.size());
672 if (!frame_index) {
673 // The first frame doesn't rely on any previous data.
674 return kNotFound;
675 }
676
677 const ImageFrame* curr_buffer = &frame_buffer_cache_[frame_index];
678 if ((frame_rect_is_opaque ||
679 curr_buffer->GetAlphaBlendSource() == ImageFrame::kBlendAtopBgcolor) &&
680 curr_buffer->OriginalFrameRect().Contains(IntRect(IntPoint(), Size())))
681 return kNotFound;
682
683 // The starting state for this frame depends on the previous frame's
684 // disposal method.
685 size_t prev_frame = frame_index - 1;
686 const ImageFrame* prev_buffer = &frame_buffer_cache_[prev_frame];
687
688 // Frames that use the DisposeOverwritePrevious method are effectively
689 // no-ops in terms of changing the starting state of a frame compared to
690 // the starting state of the previous frame, so skip over them.
691 while (prev_buffer->GetDisposalMethod() ==
692 ImageFrame::kDisposeOverwritePrevious) {
693 if (prev_frame == 0) {
694 return kNotFound;
695 }
696 prev_frame--;
697 prev_buffer = &frame_buffer_cache_[prev_frame];
698 }
699
700 switch (prev_buffer->GetDisposalMethod()) {
701 case ImageFrame::kDisposeNotSpecified:
702 case ImageFrame::kDisposeKeep:
703 // |prev_frame| will be used as the starting state for this frame.
704 // FIXME: Be even smarter by checking the frame sizes and/or
705 // alpha-containing regions.
706 return prev_frame;
707 case ImageFrame::kDisposeOverwriteBgcolor:
708 // If the previous frame fills the whole image, then the current frame
709 // can be decoded alone. Likewise, if the previous frame could be
710 // decoded without reference to any prior frame, the starting state for
711 // this frame is a blank frame, so it can again be decoded alone.
712 // Otherwise, the previous frame contributes to this frame.
713 return (prev_buffer->OriginalFrameRect().Contains(
714 IntRect(IntPoint(), Size())) ||
715 (prev_buffer->RequiredPreviousFrameIndex() == kNotFound))
716 ? kNotFound
717 : prev_frame;
718 case ImageFrame::kDisposeOverwritePrevious:
719 default:
720 NOTREACHED();
721 return kNotFound;
722 }
723 }
724
ImagePlanes()725 ImagePlanes::ImagePlanes() {
726 color_type_ = kUnknown_SkColorType;
727 for (int i = 0; i < cc::kNumYUVPlanes; ++i) {
728 planes_[i] = nullptr;
729 row_bytes_[i] = 0;
730 }
731 }
732
ImagePlanes(void * planes[cc::kNumYUVPlanes],const size_t row_bytes[cc::kNumYUVPlanes],SkColorType color_type)733 ImagePlanes::ImagePlanes(void* planes[cc::kNumYUVPlanes],
734 const size_t row_bytes[cc::kNumYUVPlanes],
735 SkColorType color_type)
736 : color_type_(color_type) {
737 for (int i = 0; i < cc::kNumYUVPlanes; ++i) {
738 planes_[i] = planes[i];
739 row_bytes_[i] = row_bytes[i];
740 }
741 }
742
Plane(cc::YUVIndex index)743 void* ImagePlanes::Plane(cc::YUVIndex index) {
744 return planes_[static_cast<size_t>(index)];
745 }
746
RowBytes(cc::YUVIndex index) const747 size_t ImagePlanes::RowBytes(cc::YUVIndex index) const {
748 return row_bytes_[static_cast<size_t>(index)];
749 }
750
ColorProfile(const skcms_ICCProfile & profile,std::unique_ptr<uint8_t[]> buffer)751 ColorProfile::ColorProfile(const skcms_ICCProfile& profile,
752 std::unique_ptr<uint8_t[]> buffer)
753 : profile_(profile), buffer_(std::move(buffer)) {}
754
Create(const void * buffer,size_t size)755 std::unique_ptr<ColorProfile> ColorProfile::Create(const void* buffer,
756 size_t size) {
757 // After skcms_Parse, profile will have pointers into the passed buffer,
758 // so we need to copy first, then parse.
759 std::unique_ptr<uint8_t[]> owned_buffer(new uint8_t[size]);
760 memcpy(owned_buffer.get(), buffer, size);
761 skcms_ICCProfile profile;
762 if (skcms_Parse(owned_buffer.get(), size, &profile)) {
763 return std::make_unique<ColorProfile>(profile, std::move(owned_buffer));
764 }
765 return nullptr;
766 }
767
ColorProfileTransform(const skcms_ICCProfile * src_profile,const skcms_ICCProfile * dst_profile)768 ColorProfileTransform::ColorProfileTransform(
769 const skcms_ICCProfile* src_profile,
770 const skcms_ICCProfile* dst_profile) {
771 DCHECK(src_profile);
772 DCHECK(dst_profile);
773 src_profile_ = src_profile;
774 dst_profile_ = *dst_profile;
775 }
776
SrcProfile() const777 const skcms_ICCProfile* ColorProfileTransform::SrcProfile() const {
778 return src_profile_;
779 }
780
DstProfile() const781 const skcms_ICCProfile* ColorProfileTransform::DstProfile() const {
782 return &dst_profile_;
783 }
784
SetEmbeddedColorProfile(std::unique_ptr<ColorProfile> profile)785 void ImageDecoder::SetEmbeddedColorProfile(
786 std::unique_ptr<ColorProfile> profile) {
787 DCHECK(!IgnoresColorSpace());
788
789 embedded_color_profile_ = std::move(profile);
790 source_to_target_color_transform_needs_update_ = true;
791 color_space_for_sk_images_ = nullptr;
792 }
793
ColorTransform()794 ColorProfileTransform* ImageDecoder::ColorTransform() {
795 if (!source_to_target_color_transform_needs_update_)
796 return source_to_target_color_transform_.get();
797 source_to_target_color_transform_needs_update_ = false;
798 source_to_target_color_transform_ = nullptr;
799
800 if (color_behavior_.IsIgnore()) {
801 return nullptr;
802 }
803
804 const skcms_ICCProfile* src_profile = nullptr;
805 skcms_ICCProfile dst_profile;
806 if (color_behavior_.IsTransformToSRGB()) {
807 if (!embedded_color_profile_) {
808 return nullptr;
809 }
810 src_profile = embedded_color_profile_->GetProfile();
811 dst_profile = *skcms_sRGB_profile();
812 } else {
813 DCHECK(color_behavior_.IsTag());
814 src_profile = embedded_color_profile_
815 ? embedded_color_profile_->GetProfile()
816 : skcms_sRGB_profile();
817
818 // This will most likely be equal to the |src_profile|.
819 // In that case, we skip the xform when we check for equality below.
820 ColorSpaceForSkImages()->toProfile(&dst_profile);
821 }
822
823 if (skcms_ApproximatelyEqualProfiles(src_profile, &dst_profile)) {
824 return nullptr;
825 }
826
827 source_to_target_color_transform_ =
828 std::make_unique<ColorProfileTransform>(src_profile, &dst_profile);
829 return source_to_target_color_transform_.get();
830 }
831
ColorSpaceForSkImages()832 sk_sp<SkColorSpace> ImageDecoder::ColorSpaceForSkImages() {
833 if (color_space_for_sk_images_)
834 return color_space_for_sk_images_;
835
836 if (!color_behavior_.IsTag())
837 return nullptr;
838
839 if (embedded_color_profile_) {
840 const skcms_ICCProfile* profile = embedded_color_profile_->GetProfile();
841 color_space_for_sk_images_ = SkColorSpace::Make(*profile);
842
843 // If the embedded color space isn't supported by Skia,
844 // we xform at decode time.
845 if (!color_space_for_sk_images_ && profile->has_toXYZD50) {
846 // Preserve the gamut, but convert to a standard transfer function.
847 skcms_ICCProfile with_srgb = *profile;
848 skcms_SetTransferFunction(&with_srgb, skcms_sRGB_TransferFunction());
849 color_space_for_sk_images_ = SkColorSpace::Make(with_srgb);
850 }
851 }
852
853 // For color spaces without an identifiable gamut, just fall through to sRGB.
854 if (!color_space_for_sk_images_)
855 color_space_for_sk_images_ = SkColorSpace::MakeSRGB();
856
857 return color_space_for_sk_images_;
858 }
859
860 } // namespace blink
861