Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(249)

Side by Side Diff: ios/chrome/browser/suggestions/ios_image_decoder_impl.mm

Issue 2689213010: Add a static method to WebPDecoder to decode WebP (Closed)
Patch Set: Address comment Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ios/chrome/browser/suggestions/ios_image_decoder_impl.h" 5 #include "ios/chrome/browser/suggestions/ios_image_decoder_impl.h"
6 6
7 #import <UIKit/UIKit.h> 7 #import <UIKit/UIKit.h>
8 8
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/mac/scoped_nsobject.h" 10 #import "base/mac/bind_objc_block.h"
11 #include "base/macros.h" 11 #include "base/macros.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/memory/weak_ptr.h" 13 #include "base/memory/weak_ptr.h"
14 #import "ios/web/public/image_fetcher/webp_decoder.h" 14 #import "ios/web/public/image_fetcher/webp_decoder.h"
15 #include "ios/web/public/web_thread.h" 15 #include "ios/web/public/web_thread.h"
16 #include "ui/gfx/image/image.h" 16 #include "ui/gfx/image/image.h"
17 17
18 #if !defined(__has_feature) || !__has_feature(objc_arc) 18 #if !defined(__has_feature) || !__has_feature(objc_arc)
19 #error "This file requires ARC support." 19 #error "This file requires ARC support."
20 #endif 20 #endif
21 21
22 namespace {
23
24 class WebpDecoderDelegate : public webp_transcode::WebpDecoder::Delegate {
25 public:
26 WebpDecoderDelegate() = default;
27
28 NSData* data() const { return decoded_image_; }
29
30 // WebpDecoder::Delegate methods
31 void OnFinishedDecoding(bool success) override {
32 if (!success)
33 decoded_image_ = nil;
34 }
35
36 void SetImageFeatures(
37 size_t total_size,
38 webp_transcode::WebpDecoder::DecodedImageFormat format) override {
39 decoded_image_ = [[NSMutableData alloc] initWithCapacity:total_size];
40 }
41
42 void OnDataDecoded(NSData* data) override {
43 DCHECK(decoded_image_);
44 [decoded_image_ appendData:data];
45 }
46
47 private:
48 ~WebpDecoderDelegate() override {}
49 NSMutableData* decoded_image_;
50
51 DISALLOW_COPY_AND_ASSIGN(WebpDecoderDelegate);
52 };
53
54 // Returns an NSData object containing the decoded image data of the given
55 // webp_image. Returns nil in case of failure.
56 base::scoped_nsobject<NSData> DecodeWebpImage(
57 const base::scoped_nsobject<NSData>& webp_image) {
58 scoped_refptr<WebpDecoderDelegate> delegate(new WebpDecoderDelegate);
59 scoped_refptr<webp_transcode::WebpDecoder> decoder(
60 new webp_transcode::WebpDecoder(delegate.get()));
61 decoder->OnDataReceived(webp_image);
62 DLOG_IF(ERROR, !delegate->data()) << "WebP image decoding failed.";
63 return base::scoped_nsobject<NSData>(delegate->data());
64 }
65
66 // Returns true if the given image_data is a WebP image.
67 //
68 // Every WebP file contains a 12 byte file header in the beginning of the file.
69 // A WebP file header starts with the four ASCII characters "RIFF". The next
70 // four bytes contain the image size and the last four header bytes contain the
71 // four ASCII characters "WEBP".
72 //
73 // WebP file header:
74 // 1 1
75 // Byte Nr. 0 1 2 3 4 5 6 7 8 9 0 1
76 // Byte value [ R I F F ? ? ? ? W E B P ]
77 //
78 // For more information see:
79 // https://developers.google.com/speed/webp/docs/riff_container#webp_file_header
80 bool IsWebpImage(const std::string& image_data) {
81 if (image_data.length() < 12)
82 return false;
83 return image_data.compare(0, 4, "RIFF") == 0 &&
84 image_data.compare(8, 4, "WEBP") == 0;
85 }
86
87 } // namespace
88
89 namespace suggestions { 22 namespace suggestions {
90 23
91 class IOSImageDecoderImpl : public image_fetcher::ImageDecoder { 24 class IOSImageDecoderImpl : public image_fetcher::ImageDecoder {
92 public: 25 public:
93 explicit IOSImageDecoderImpl(scoped_refptr<base::TaskRunner> task_runner); 26 explicit IOSImageDecoderImpl(scoped_refptr<base::TaskRunner> task_runner);
94 ~IOSImageDecoderImpl() override; 27 ~IOSImageDecoderImpl() override;
95 28
96 void DecodeImage( 29 void DecodeImage(
97 const std::string& image_data, 30 const std::string& image_data,
98 const image_fetcher::ImageDecodedCallback& callback) override; 31 const image_fetcher::ImageDecodedCallback& callback) override;
99 32
100 private: 33 private:
101 void CreateUIImageAndRunCallback( 34 void CreateUIImageAndRunCallback(
102 const image_fetcher::ImageDecodedCallback& callback, 35 const image_fetcher::ImageDecodedCallback& callback,
103 const base::scoped_nsobject<NSData>& image_data); 36 NSData* image_data);
104 37
105 // The task runner used to decode images if necessary. 38 // The task runner used to decode images if necessary.
106 const scoped_refptr<base::TaskRunner> task_runner_; 39 const scoped_refptr<base::TaskRunner> task_runner_;
107 40
108 // The WeakPtrFactory is used to cancel callbacks if ImageFetcher is 41 // The WeakPtrFactory is used to cancel callbacks if ImageFetcher is
109 // destroyed during WebP decoding. 42 // destroyed during WebP decoding.
110 base::WeakPtrFactory<IOSImageDecoderImpl> weak_factory_; 43 base::WeakPtrFactory<IOSImageDecoderImpl> weak_factory_;
111 44
112 DISALLOW_COPY_AND_ASSIGN(IOSImageDecoderImpl); 45 DISALLOW_COPY_AND_ASSIGN(IOSImageDecoderImpl);
113 }; 46 };
114 47
115 IOSImageDecoderImpl::IOSImageDecoderImpl( 48 IOSImageDecoderImpl::IOSImageDecoderImpl(
116 scoped_refptr<base::TaskRunner> task_runner) 49 scoped_refptr<base::TaskRunner> task_runner)
117 : task_runner_(std::move(task_runner)), weak_factory_(this) { 50 : task_runner_(std::move(task_runner)), weak_factory_(this) {
118 DCHECK(task_runner_.get()); 51 DCHECK(task_runner_.get());
119 } 52 }
120 53
121 IOSImageDecoderImpl::~IOSImageDecoderImpl() {} 54 IOSImageDecoderImpl::~IOSImageDecoderImpl() {}
122 55
123 void IOSImageDecoderImpl::DecodeImage( 56 void IOSImageDecoderImpl::DecodeImage(
124 const std::string& image_data, 57 const std::string& image_data,
125 const image_fetcher::ImageDecodedCallback& callback) { 58 const image_fetcher::ImageDecodedCallback& callback) {
126 // Convert the |image_data| std::string to an NSData buffer. 59 // Convert the |image_data| std::string to an NSData buffer.
127 base::scoped_nsobject<NSData> data([NSData 60 // The data is copied as it may have to outlive the caller in
128 dataWithBytesNoCopy:const_cast<char*>(image_data.c_str()) 61 // PostTaskAndReplyWithResult.
129 length:image_data.length() 62 NSData* data =
130 freeWhenDone:NO]); 63 [NSData dataWithBytes:image_data.data() length:image_data.size()];
131 64
132 // The WebP image format is not supported by iOS natively. Therefore WebP 65 // The WebP image format is not supported by iOS natively. Therefore WebP
133 // images need to be decoded explicitly, 66 // images need to be decoded explicitly,
134 if (IsWebpImage(image_data)) { 67 if (webp_transcode::WebpDecoder::IsWebpImage(image_data)) {
135 base::PostTaskAndReplyWithResult( 68 base::PostTaskAndReplyWithResult(
136 task_runner_.get(), FROM_HERE, base::Bind(&DecodeWebpImage, data), 69 task_runner_.get(), FROM_HERE, base::BindBlockArc(^NSData*() {
70 return webp_transcode::WebpDecoder::DecodeWebpImage(data);
71 }),
137 base::Bind(&IOSImageDecoderImpl::CreateUIImageAndRunCallback, 72 base::Bind(&IOSImageDecoderImpl::CreateUIImageAndRunCallback,
138 weak_factory_.GetWeakPtr(), callback)); 73 weak_factory_.GetWeakPtr(), callback));
139 } else { 74 } else {
140 CreateUIImageAndRunCallback(callback, data); 75 CreateUIImageAndRunCallback(callback, data);
141 } 76 }
142 } 77 }
143 78
144 void IOSImageDecoderImpl::CreateUIImageAndRunCallback( 79 void IOSImageDecoderImpl::CreateUIImageAndRunCallback(
145 const image_fetcher::ImageDecodedCallback& callback, 80 const image_fetcher::ImageDecodedCallback& callback,
146 const base::scoped_nsobject<NSData>& image_data) { 81 NSData* image_data) {
147 // Decode the image data using UIImage. 82 // Decode the image data using UIImage.
148 if (image_data) { 83 if (image_data) {
149 // "Most likely" always returns 1x images. 84 // "Most likely" always returns 1x images.
150 UIImage* ui_image = [UIImage imageWithData:image_data scale:1]; 85 UIImage* ui_image = [UIImage imageWithData:image_data scale:1];
151 if (ui_image) { 86 if (ui_image) {
152 // This constructor does not retain the image, but expects to take the 87 // This constructor does not retain the image, but expects to take the
153 // ownership, therefore, |ui_image| is retained here, but not released 88 // ownership, therefore, |ui_image| is retained here, but not released
154 // afterwards. 89 // afterwards.
155 gfx::Image gfx_image(ui_image, base::scoped_policy::RETAIN); 90 gfx::Image gfx_image(ui_image, base::scoped_policy::RETAIN);
156 callback.Run(gfx_image); 91 callback.Run(gfx_image);
157 return; 92 return;
158 } 93 }
159 } 94 }
160 gfx::Image empty_image; 95 gfx::Image empty_image;
161 callback.Run(empty_image); 96 callback.Run(empty_image);
162 } 97 }
163 98
164 std::unique_ptr<image_fetcher::ImageDecoder> CreateIOSImageDecoder( 99 std::unique_ptr<image_fetcher::ImageDecoder> CreateIOSImageDecoder(
165 scoped_refptr<base::TaskRunner> task_runner) { 100 scoped_refptr<base::TaskRunner> task_runner) {
166 return base::MakeUnique<IOSImageDecoderImpl>(std::move(task_runner)); 101 return base::MakeUnique<IOSImageDecoderImpl>(std::move(task_runner));
167 } 102 }
168 103
169 } // namespace suggestions 104 } // namespace suggestions
OLDNEW
« no previous file with comments | « components/image_fetcher/ios/ios_image_data_fetcher_wrapper_unittest.mm ('k') | ios/web/public/image_fetcher/webp_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698