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