Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "chrome/browser/chromeos/login/users/avatar/user_image_loader.h" | 5 #include "chrome/browser/chromeos/login/users/avatar/user_image_loader.h" |
| 6 | 6 |
| 7 #include <memory> | 7 #include <memory> |
| 8 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 40 ~ImageInfo() {} | 40 ~ImageInfo() {} |
| 41 | 41 |
| 42 const base::FilePath file_path; | 42 const base::FilePath file_path; |
| 43 const int pixels_per_side; | 43 const int pixels_per_side; |
| 44 const ImageDecoder::ImageCodec image_codec; | 44 const ImageDecoder::ImageCodec image_codec; |
| 45 const LoadedCallback loaded_cb; | 45 const LoadedCallback loaded_cb; |
| 46 }; | 46 }; |
| 47 | 47 |
| 48 // Crops |image| to the square format and downsizes the image to | 48 // Crops |image| to the square format and downsizes the image to |
| 49 // |target_size| in pixels. On success, returns the bytes representation and | 49 // |target_size| in pixels. On success, returns the bytes representation and |
| 50 // stores the cropped image in |bitmap|. On failure, returns nullptr. | 50 // stores the cropped image in |bitmap|, and the format of the bytes |
| 51 scoped_refptr<base::RefCountedBytes> CropImage(const SkBitmap& image, | 51 // representation in |image_format|. On failure, returns nullptr. |
| 52 int target_size, | 52 scoped_refptr<base::RefCountedBytes> CropImage( |
| 53 SkBitmap* bitmap) { | 53 const SkBitmap& image, |
| 54 int target_size, | |
| 55 SkBitmap* bitmap, | |
| 56 user_manager::UserImage::ImageFormat* image_format) { | |
| 54 DCHECK_GT(target_size, 0); | 57 DCHECK_GT(target_size, 0); |
| 58 DCHECK(image_format); | |
| 55 | 59 |
| 56 SkBitmap final_image; | 60 SkBitmap final_image; |
| 57 // Auto crop the image, taking the largest square in the center. | 61 // Auto crop the image, taking the largest square in the center. |
| 58 int pixels_per_side = std::min(image.width(), image.height()); | 62 int pixels_per_side = std::min(image.width(), image.height()); |
| 59 int x = (image.width() - pixels_per_side) / 2; | 63 int x = (image.width() - pixels_per_side) / 2; |
| 60 int y = (image.height() - pixels_per_side) / 2; | 64 int y = (image.height() - pixels_per_side) / 2; |
| 61 SkBitmap cropped_image = SkBitmapOperations::CreateTiledBitmap( | 65 SkBitmap cropped_image = SkBitmapOperations::CreateTiledBitmap( |
| 62 image, x, y, pixels_per_side, pixels_per_side); | 66 image, x, y, pixels_per_side, pixels_per_side); |
| 63 if (pixels_per_side > target_size) { | 67 if (pixels_per_side > target_size) { |
| 64 // Also downsize the image to save space and memory. | 68 // Also downsize the image to save space and memory. |
| 65 final_image = skia::ImageOperations::Resize( | 69 final_image = skia::ImageOperations::Resize( |
| 66 cropped_image, skia::ImageOperations::RESIZE_LANCZOS3, target_size, | 70 cropped_image, skia::ImageOperations::RESIZE_LANCZOS3, target_size, |
| 67 target_size); | 71 target_size); |
| 68 } else { | 72 } else { |
| 69 final_image = cropped_image; | 73 final_image = cropped_image; |
| 70 } | 74 } |
| 71 | 75 |
| 72 // Encode the cropped image to web-compatible bytes representation | 76 // Encode the cropped image to web-compatible bytes representation |
| 77 *image_format = user_manager::UserImage::ChooseImageFormat(final_image); | |
| 73 scoped_refptr<base::RefCountedBytes> encoded = | 78 scoped_refptr<base::RefCountedBytes> encoded = |
| 74 user_manager::UserImage::Encode(final_image); | 79 user_manager::UserImage::Encode(final_image, *image_format); |
| 75 if (encoded) | 80 if (encoded) |
|
achuithb
2016/11/30 00:26:48
Does it make sense to reset image_format to FORMAT
satorux1
2016/12/01 07:43:36
No, I think. The function returns nullptr on error
| |
| 76 bitmap->swap(final_image); | 81 bitmap->swap(final_image); |
| 77 return encoded; | 82 return encoded; |
| 78 } | 83 } |
| 79 | 84 |
| 85 // Returns the image format for the bytes representation of the user image | |
| 86 // from the image codec used for loading the image. | |
| 87 user_manager::UserImage::ImageFormat ChooseImageFormatFromCodec( | |
| 88 ImageDecoder::ImageCodec image_codec) { | |
| 89 switch (image_codec) { | |
| 90 case ImageDecoder::ROBUST_JPEG_CODEC: | |
| 91 return user_manager::UserImage::FORMAT_JPEG; | |
| 92 case ImageDecoder::ROBUST_PNG_CODEC: | |
| 93 return user_manager::UserImage::FORMAT_PNG; | |
| 94 case ImageDecoder::DEFAULT_CODEC: | |
| 95 // The default codec can accept many kinds of image formats, hence the | |
| 96 // image format of the bytes representation is unknown. | |
| 97 return user_manager::UserImage::FORMAT_UNKNOWN; | |
| 98 } | |
| 99 NOTREACHED(); | |
| 100 return user_manager::UserImage::FORMAT_UNKNOWN; | |
| 101 } | |
| 102 | |
| 80 // Handles the decoded image returned from ImageDecoder through the | 103 // Handles the decoded image returned from ImageDecoder through the |
| 81 // ImageRequest interface. | 104 // ImageRequest interface. |
| 82 class UserImageRequest : public ImageDecoder::ImageRequest { | 105 class UserImageRequest : public ImageDecoder::ImageRequest { |
| 83 public: | 106 public: |
| 84 UserImageRequest( | 107 UserImageRequest( |
| 85 const ImageInfo& image_info, | 108 const ImageInfo& image_info, |
| 86 const std::string& image_data, | 109 const std::string& image_data, |
| 87 scoped_refptr<base::SequencedTaskRunner> background_task_runner) | 110 scoped_refptr<base::SequencedTaskRunner> background_task_runner) |
| 88 : image_info_(image_info), | 111 : image_info_(image_info), |
| 89 // TODO(crbug.com/593251): Remove the data copy here. | 112 // TODO(crbug.com/593251): Remove the data copy here. |
| 90 image_data_(new base::RefCountedBytes( | 113 image_data_(new base::RefCountedBytes( |
| 91 reinterpret_cast<const unsigned char*>(image_data.data()), | 114 reinterpret_cast<const unsigned char*>(image_data.data()), |
| 92 image_data.size())), | 115 image_data.size())), |
| 93 background_task_runner_(background_task_runner), | 116 background_task_runner_(background_task_runner), |
| 94 weak_ptr_factory_(this) {} | 117 weak_ptr_factory_(this) {} |
| 95 ~UserImageRequest() override {} | 118 ~UserImageRequest() override {} |
| 96 | 119 |
| 97 // ImageDecoder::ImageRequest implementation. | 120 // ImageDecoder::ImageRequest implementation. |
| 98 void OnImageDecoded(const SkBitmap& decoded_image) override; | 121 void OnImageDecoded(const SkBitmap& decoded_image) override; |
| 99 void OnDecodeImageFailed() override; | 122 void OnDecodeImageFailed() override; |
| 100 | 123 |
| 101 // Called after the image is cropped (and downsized) as needed. | 124 // Called after the image is cropped (and downsized) as needed. |
| 102 void OnImageCropped(SkBitmap* bitmap, | 125 void OnImageCropped(SkBitmap* bitmap, |
| 126 user_manager::UserImage::ImageFormat* image_format, | |
| 103 scoped_refptr<base::RefCountedBytes> bytes); | 127 scoped_refptr<base::RefCountedBytes> bytes); |
| 104 | 128 |
| 105 // Called after the image is finalized. |image_bytes_regenerated| is true | 129 // Called after the image is finalized. |image_bytes_regenerated| is true |
| 106 // if |image_bytes| is regenerated from the cropped image. | 130 // if |image_bytes| is regenerated from the cropped image. |
| 107 void OnImageFinalized(const SkBitmap& image, | 131 void OnImageFinalized(const SkBitmap& image, |
| 132 user_manager::UserImage::ImageFormat image_format, | |
| 108 scoped_refptr<base::RefCountedBytes> image_bytes, | 133 scoped_refptr<base::RefCountedBytes> image_bytes, |
| 109 bool image_bytes_regenerated); | 134 bool image_bytes_regenerated); |
| 110 | 135 |
| 111 private: | 136 private: |
| 112 const ImageInfo image_info_; | 137 const ImageInfo image_info_; |
| 113 scoped_refptr<base::RefCountedBytes> image_data_; | 138 scoped_refptr<base::RefCountedBytes> image_data_; |
| 114 scoped_refptr<base::SequencedTaskRunner> background_task_runner_; | 139 scoped_refptr<base::SequencedTaskRunner> background_task_runner_; |
| 115 | 140 |
| 116 // This should be the last member. | 141 // This should be the last member. |
| 117 base::WeakPtrFactory<UserImageRequest> weak_ptr_factory_; | 142 base::WeakPtrFactory<UserImageRequest> weak_ptr_factory_; |
| 118 }; | 143 }; |
| 119 | 144 |
| 120 void UserImageRequest::OnImageDecoded(const SkBitmap& decoded_image) { | 145 void UserImageRequest::OnImageDecoded(const SkBitmap& decoded_image) { |
| 121 int target_size = image_info_.pixels_per_side; | 146 int target_size = image_info_.pixels_per_side; |
| 122 if (target_size > 0) { | 147 if (target_size > 0) { |
| 123 // Cropping an image could be expensive, hence posting to the background | 148 // Cropping an image could be expensive, hence posting to the background |
| 124 // thread. | 149 // thread. |
| 125 SkBitmap* bitmap = new SkBitmap; | 150 SkBitmap* bitmap = new SkBitmap; |
| 151 user_manager::UserImage::ImageFormat* image_format = | |
|
achuithb
2016/11/30 00:26:48
auto* is appropriate here
satorux1
2016/12/01 07:43:36
Done.
| |
| 152 new user_manager::UserImage::ImageFormat( | |
| 153 user_manager::UserImage::FORMAT_UNKNOWN); | |
| 126 base::PostTaskAndReplyWithResult( | 154 base::PostTaskAndReplyWithResult( |
| 127 background_task_runner_.get(), FROM_HERE, | 155 background_task_runner_.get(), FROM_HERE, |
| 128 base::Bind(&CropImage, decoded_image, target_size, bitmap), | 156 base::Bind(&CropImage, decoded_image, target_size, bitmap, |
| 157 image_format), | |
| 129 base::Bind(&UserImageRequest::OnImageCropped, | 158 base::Bind(&UserImageRequest::OnImageCropped, |
| 130 weak_ptr_factory_.GetWeakPtr(), base::Owned(bitmap))); | 159 weak_ptr_factory_.GetWeakPtr(), base::Owned(bitmap), |
| 160 base::Owned(image_format))); | |
| 131 } else { | 161 } else { |
| 132 OnImageFinalized(decoded_image, image_data_, | 162 const user_manager::UserImage::ImageFormat image_format = |
| 163 ChooseImageFormatFromCodec(image_info_.image_codec); | |
| 164 OnImageFinalized(decoded_image, image_format, image_data_, | |
| 133 false /* image_bytes_regenerated */); | 165 false /* image_bytes_regenerated */); |
| 134 } | 166 } |
| 135 } | 167 } |
| 136 | 168 |
| 137 void UserImageRequest::OnImageCropped( | 169 void UserImageRequest::OnImageCropped( |
| 138 SkBitmap* bitmap, | 170 SkBitmap* bitmap, |
| 171 user_manager::UserImage::ImageFormat* image_format, | |
| 139 scoped_refptr<base::RefCountedBytes> bytes) { | 172 scoped_refptr<base::RefCountedBytes> bytes) { |
| 140 DCHECK_GT(image_info_.pixels_per_side, 0); | 173 DCHECK_GT(image_info_.pixels_per_side, 0); |
| 141 | 174 |
| 142 if (!bytes) { | 175 if (!bytes) { |
| 143 OnDecodeImageFailed(); | 176 OnDecodeImageFailed(); |
| 144 return; | 177 return; |
| 145 } | 178 } |
| 146 OnImageFinalized(*bitmap, bytes, true /* image_bytes_regenerated */); | 179 OnImageFinalized(*bitmap, *image_format, bytes, |
| 180 true /* image_bytes_regenerated */); | |
| 147 } | 181 } |
| 148 | 182 |
| 149 void UserImageRequest::OnImageFinalized( | 183 void UserImageRequest::OnImageFinalized( |
| 150 const SkBitmap& image, | 184 const SkBitmap& image, |
| 185 user_manager::UserImage::ImageFormat image_format, | |
| 151 scoped_refptr<base::RefCountedBytes> image_bytes, | 186 scoped_refptr<base::RefCountedBytes> image_bytes, |
| 152 bool image_bytes_regenerated) { | 187 bool image_bytes_regenerated) { |
| 153 SkBitmap final_image = image; | 188 SkBitmap final_image = image; |
| 154 // Make the SkBitmap immutable as we won't modify it. This is important | 189 // Make the SkBitmap immutable as we won't modify it. This is important |
| 155 // because otherwise it gets duplicated during painting, wasting memory. | 190 // because otherwise it gets duplicated during painting, wasting memory. |
| 156 final_image.setImmutable(); | 191 final_image.setImmutable(); |
| 157 gfx::ImageSkia final_image_skia = | 192 gfx::ImageSkia final_image_skia = |
| 158 gfx::ImageSkia::CreateFrom1xBitmap(final_image); | 193 gfx::ImageSkia::CreateFrom1xBitmap(final_image); |
| 159 final_image_skia.MakeThreadSafe(); | 194 final_image_skia.MakeThreadSafe(); |
| 160 std::unique_ptr<user_manager::UserImage> user_image( | 195 std::unique_ptr<user_manager::UserImage> user_image( |
| 161 new user_manager::UserImage(final_image_skia, image_bytes)); | 196 new user_manager::UserImage(final_image_skia, image_bytes, image_format)); |
| 162 user_image->set_file_path(image_info_.file_path); | 197 user_image->set_file_path(image_info_.file_path); |
| 163 if (image_info_.image_codec == ImageDecoder::ROBUST_JPEG_CODEC || | 198 if (image_info_.image_codec == ImageDecoder::ROBUST_JPEG_CODEC || |
| 199 image_info_.image_codec == ImageDecoder::ROBUST_PNG_CODEC || | |
|
achuithb
2016/11/30 00:26:48
This is a change in behavior right?
satorux1
2016/12/01 07:43:36
Yes. Added some comment to clarify the intention h
| |
| 164 image_bytes_regenerated) | 200 image_bytes_regenerated) |
| 165 user_image->MarkAsSafe(); | 201 user_image->MarkAsSafe(); |
| 166 image_info_.loaded_cb.Run(std::move(user_image)); | 202 image_info_.loaded_cb.Run(std::move(user_image)); |
| 167 delete this; | 203 delete this; |
| 168 } | 204 } |
| 169 | 205 |
| 170 void UserImageRequest::OnDecodeImageFailed() { | 206 void UserImageRequest::OnDecodeImageFailed() { |
| 171 image_info_.loaded_cb.Run(base::WrapUnique(new user_manager::UserImage)); | 207 image_info_.loaded_cb.Run(base::WrapUnique(new user_manager::UserImage)); |
| 172 delete this; | 208 delete this; |
| 173 } | 209 } |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 216 ImageDecoder::ImageCodec image_codec, | 252 ImageDecoder::ImageCodec image_codec, |
| 217 int pixels_per_side, | 253 int pixels_per_side, |
| 218 const LoadedCallback& loaded_cb) { | 254 const LoadedCallback& loaded_cb) { |
| 219 DecodeImage( | 255 DecodeImage( |
| 220 ImageInfo(base::FilePath(), pixels_per_side, image_codec, loaded_cb), | 256 ImageInfo(base::FilePath(), pixels_per_side, image_codec, loaded_cb), |
| 221 background_task_runner, data.get(), true /* data_is_ready */); | 257 background_task_runner, data.get(), true /* data_is_ready */); |
| 222 } | 258 } |
| 223 | 259 |
| 224 } // namespace user_image_loader | 260 } // namespace user_image_loader |
| 225 } // namespace chromeos | 261 } // namespace chromeos |
| OLD | NEW |