| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 #import "ios/web/public/image_fetcher/webp_decoder.h" | 5 #import "ios/web/public/image_fetcher/webp_decoder.h" |
| 6 | 6 |
| 7 #import <Foundation/Foundation.h> | 7 #import <Foundation/Foundation.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #import <UIKit/UIKit.h> | 9 #import <UIKit/UIKit.h> |
| 10 | 10 |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
| 13 | 13 |
| 14 #if !defined(__has_feature) || !__has_feature(objc_arc) | 14 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 15 #error "This file requires ARC support." | 15 #error "This file requires ARC support." |
| 16 #endif | 16 #endif |
| 17 | 17 |
| 18 namespace { | 18 namespace { |
| 19 | 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_ = nil; |
| 30 } |
| 31 |
| 32 void SetImageFeatures( |
| 33 size_t total_size, |
| 34 webp_transcode::WebpDecoder::DecodedImageFormat format) override { |
| 35 decoded_image_ = [[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 NSMutableData* decoded_image_; |
| 46 |
| 47 DISALLOW_COPY_AND_ASSIGN(WebpDecoderDelegate); |
| 48 }; |
| 49 |
| 50 // Content-type header for WebP images. |
| 51 const char kWEBPFirstMagicPattern[] = "RIFF"; |
| 52 const char kWEBPSecondMagicPattern[] = "WEBP"; |
| 53 |
| 20 const uint8_t kNumIfdEntries = 15; | 54 const uint8_t kNumIfdEntries = 15; |
| 21 const unsigned int kExtraDataSize = 16; | 55 const unsigned int kExtraDataSize = 16; |
| 22 // 10b for signature/header + n * 12b entries + 4b for IFD terminator: | 56 // 10b for signature/header + n * 12b entries + 4b for IFD terminator: |
| 23 const unsigned int kExtraDataOffset = 10 + 12 * kNumIfdEntries + 4; | 57 const unsigned int kExtraDataOffset = 10 + 12 * kNumIfdEntries + 4; |
| 24 const unsigned int kHeaderSize = kExtraDataOffset + kExtraDataSize; | 58 const unsigned int kHeaderSize = kExtraDataOffset + kExtraDataSize; |
| 25 const int kRecompressionThreshold = 64 * 64; // Threshold in pixels. | 59 const int kRecompressionThreshold = 64 * 64; // Threshold in pixels. |
| 26 const CGFloat kJpegQuality = 0.85; | 60 const CGFloat kJpegQuality = 0.85; |
| 27 | 61 |
| 28 // Adapted from libwebp example dwebp.c. | 62 // Adapted from libwebp example dwebp.c. |
| 29 void PutLE16(uint8_t* const dst, uint32_t value) { | 63 void PutLE16(uint8_t* const dst, uint32_t value) { |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 PutLE32(tiff_header + 178, 0); | 118 PutLE32(tiff_header + 178, 0); |
| 85 | 119 |
| 86 memcpy(dst, tiff_header, kHeaderSize); | 120 memcpy(dst, tiff_header, kHeaderSize); |
| 87 } | 121 } |
| 88 | 122 |
| 89 } // namespace | 123 } // namespace |
| 90 | 124 |
| 91 namespace webp_transcode { | 125 namespace webp_transcode { |
| 92 | 126 |
| 93 // static | 127 // static |
| 128 NSData* WebpDecoder::DecodeWebpImage(NSData* webp_image) { |
| 129 scoped_refptr<WebpDecoderDelegate> delegate(new WebpDecoderDelegate); |
| 130 |
| 131 scoped_refptr<webp_transcode::WebpDecoder> decoder( |
| 132 new webp_transcode::WebpDecoder(delegate.get())); |
| 133 |
| 134 decoder->OnDataReceived(webp_image); |
| 135 DLOG_IF(ERROR, !delegate->data()) << "WebP image decoding failed."; |
| 136 return delegate->data(); |
| 137 } |
| 138 |
| 139 // static |
| 140 bool WebpDecoder::IsWebpImage(const std::string& image_data) { |
| 141 if (image_data.length() < 12) |
| 142 return false; |
| 143 return image_data.compare(0, 4, kWEBPFirstMagicPattern) == 0 && |
| 144 image_data.compare(8, 4, kWEBPSecondMagicPattern) == 0; |
| 145 } |
| 146 |
| 147 // static |
| 94 size_t WebpDecoder::GetHeaderSize() { | 148 size_t WebpDecoder::GetHeaderSize() { |
| 95 return kHeaderSize; | 149 return kHeaderSize; |
| 96 } | 150 } |
| 97 | 151 |
| 98 WebpDecoder::WebpDecoder(WebpDecoder::Delegate* delegate) | 152 WebpDecoder::WebpDecoder(WebpDecoder::Delegate* delegate) |
| 99 : delegate_(delegate), state_(READING_FEATURES), has_alpha_(0) { | 153 : delegate_(delegate), state_(READING_FEATURES), has_alpha_(0) { |
| 100 DCHECK(delegate_.get()); | 154 DCHECK(delegate_.get()); |
| 101 const bool rv = WebPInitDecoderConfig(&config_); | 155 const bool rv = WebPInitDecoderConfig(&config_); |
| 102 DCHECK(rv); | 156 DCHECK(rv); |
| 103 } | 157 } |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 } | 300 } |
| 247 UMA_HISTOGRAM_ENUMERATION("WebP.DecodedImageFormat", format, | 301 UMA_HISTOGRAM_ENUMERATION("WebP.DecodedImageFormat", format, |
| 248 DECODED_FORMAT_COUNT); | 302 DECODED_FORMAT_COUNT); |
| 249 delegate_->SetImageFeatures([result_data length], format); | 303 delegate_->SetImageFeatures([result_data length], format); |
| 250 delegate_->OnDataDecoded(result_data); | 304 delegate_->OnDataDecoded(result_data); |
| 251 output_buffer_.reset(); | 305 output_buffer_.reset(); |
| 252 return true; | 306 return true; |
| 253 } | 307 } |
| 254 | 308 |
| 255 } // namespace webp_transcode | 309 } // namespace webp_transcode |
| OLD | NEW |