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

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

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

Powered by Google App Engine
This is Rietveld 408576698