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

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

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

Powered by Google App Engine
This is Rietveld 408576698