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

Side by Side Diff: chrome/browser/chromeos/login/users/avatar/user_image_loader.cc

Issue 1748423005: Crop the user-specified profile image for WebUI (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: just rebase Created 4 years, 9 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 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 <utility> 7 #include <utility>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
(...skipping 26 matching lines...) Expand all
37 image_codec(image_codec), 37 image_codec(image_codec),
38 loaded_cb(loaded_cb) {} 38 loaded_cb(loaded_cb) {}
39 ~ImageInfo() {} 39 ~ImageInfo() {}
40 40
41 const base::FilePath file_path; 41 const base::FilePath file_path;
42 const int pixels_per_side; 42 const int pixels_per_side;
43 const ImageDecoder::ImageCodec image_codec; 43 const ImageDecoder::ImageCodec image_codec;
44 const LoadedCallback loaded_cb; 44 const LoadedCallback loaded_cb;
45 }; 45 };
46 46
47 typedef std::pair<SkBitmap, scoped_ptr<user_manager::UserImage::Bytes>>
48 CropResultPair;
49
47 // Crops |image| to the square format and downsizes the image to 50 // Crops |image| to the square format and downsizes the image to
48 // |target_size| in pixels. 51 // |target_size| in pixels. Returns the cropped image and the regenerated
49 SkBitmap CropImage(const SkBitmap& image, int target_size) { 52 // bytes representation as a pair. The latter can be null on failure.
53 CropResultPair CropImage(const SkBitmap& image, int target_size) {
50 DCHECK_GT(target_size, 0); 54 DCHECK_GT(target_size, 0);
51 55
52 SkBitmap final_image; 56 SkBitmap final_image;
53 // Auto crop the image, taking the largest square in the center. 57 // Auto crop the image, taking the largest square in the center.
54 int pixels_per_side = std::min(image.width(), image.height()); 58 int pixels_per_side = std::min(image.width(), image.height());
55 int x = (image.width() - pixels_per_side) / 2; 59 int x = (image.width() - pixels_per_side) / 2;
56 int y = (image.height() - pixels_per_side) / 2; 60 int y = (image.height() - pixels_per_side) / 2;
57 SkBitmap cropped_image = SkBitmapOperations::CreateTiledBitmap( 61 SkBitmap cropped_image = SkBitmapOperations::CreateTiledBitmap(
58 image, x, y, pixels_per_side, pixels_per_side); 62 image, x, y, pixels_per_side, pixels_per_side);
59 if (pixels_per_side > target_size) { 63 if (pixels_per_side > target_size) {
60 // Also downsize the image to save space and memory. 64 // Also downsize the image to save space and memory.
61 final_image = skia::ImageOperations::Resize( 65 final_image = skia::ImageOperations::Resize(
62 cropped_image, skia::ImageOperations::RESIZE_LANCZOS3, target_size, 66 cropped_image, skia::ImageOperations::RESIZE_LANCZOS3, target_size,
63 target_size); 67 target_size);
64 } else { 68 } else {
65 final_image = cropped_image; 69 final_image = cropped_image;
66 } 70 }
67 return final_image; 71
72 // Encode the cropped image to web-compatible bytes representation
73 scoped_ptr<user_manager::UserImage::Bytes> bytes =
74 user_manager::UserImage::Encode(final_image);
75 return std::make_pair(final_image, std::move(bytes));
68 } 76 }
69 77
70 // Handles the decoded image returned from ImageDecoder through the 78 // Handles the decoded image returned from ImageDecoder through the
71 // ImageRequest interface. 79 // ImageRequest interface.
72 class UserImageRequest : public ImageDecoder::ImageRequest { 80 class UserImageRequest : public ImageDecoder::ImageRequest {
73 public: 81 public:
74 UserImageRequest( 82 UserImageRequest(
75 const ImageInfo& image_info, 83 const ImageInfo& image_info,
76 const std::string& image_data, 84 const std::string& image_data,
77 scoped_refptr<base::SequencedTaskRunner> background_task_runner) 85 scoped_refptr<base::SequencedTaskRunner> background_task_runner)
78 : image_info_(image_info), 86 : image_info_(image_info),
79 image_data_(image_data.begin(), image_data.end()), 87 image_data_(image_data.begin(), image_data.end()),
80 background_task_runner_(background_task_runner), 88 background_task_runner_(background_task_runner),
81 weak_ptr_factory_(this) {} 89 weak_ptr_factory_(this) {}
82 ~UserImageRequest() override {} 90 ~UserImageRequest() override {}
83 91
84 // ImageDecoder::ImageRequest implementation. 92 // ImageDecoder::ImageRequest implementation.
85 void OnImageDecoded(const SkBitmap& decoded_image) override; 93 void OnImageDecoded(const SkBitmap& decoded_image) override;
86 void OnDecodeImageFailed() override; 94 void OnDecodeImageFailed() override;
87 95
88 // Called after the image is transformed (cropped and downsized) as needed. 96 // Called after the image is cropped (and downsized) as needed.
89 void OnImageFinalized(const SkBitmap& image); 97 void OnImageCropped(const CropResultPair& pair);
98
99 // Called after the image is finalized. |image_bytes_regenerated| is true
100 // if |image_bytes| is regenerated from the cropped image.
101 void OnImageFinalized(const SkBitmap& image,
102 const user_manager::UserImage::Bytes& image_bytes,
103 bool image_bytes_regenerated);
90 104
91 private: 105 private:
92 const ImageInfo image_info_; 106 const ImageInfo image_info_;
93 const user_manager::UserImage::Bytes image_data_; 107 const user_manager::UserImage::Bytes image_data_;
94 scoped_refptr<base::SequencedTaskRunner> background_task_runner_; 108 scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
95 109
96 // This should be the last member. 110 // This should be the last member.
97 base::WeakPtrFactory<UserImageRequest> weak_ptr_factory_; 111 base::WeakPtrFactory<UserImageRequest> weak_ptr_factory_;
98 }; 112 };
99 113
100 void UserImageRequest::OnImageDecoded(const SkBitmap& decoded_image) { 114 void UserImageRequest::OnImageDecoded(const SkBitmap& decoded_image) {
101 int target_size = image_info_.pixels_per_side; 115 int target_size = image_info_.pixels_per_side;
102 if (target_size > 0) { 116 if (target_size > 0) {
103 // Transforming an image could be expensive, hence posting to the 117 // Cropping an image could be expensive, hence posting to the background
104 // background thread. 118 // thread.
105 base::PostTaskAndReplyWithResult( 119 base::PostTaskAndReplyWithResult(
106 background_task_runner_.get(), FROM_HERE, 120 background_task_runner_.get(), FROM_HERE,
107 base::Bind(&CropImage, decoded_image, target_size), 121 base::Bind(&CropImage, decoded_image, target_size),
108 base::Bind(&UserImageRequest::OnImageFinalized, 122 base::Bind(&UserImageRequest::OnImageCropped,
109 weak_ptr_factory_.GetWeakPtr())); 123 weak_ptr_factory_.GetWeakPtr()));
110 } else { 124 } else {
111 OnImageFinalized(decoded_image); 125 OnImageFinalized(decoded_image, image_data_,
126 false /* image_bytes_regenerated */);
112 } 127 }
113 } 128 }
114 129
115 void UserImageRequest::OnImageFinalized(const SkBitmap& image) { 130 void UserImageRequest::OnImageCropped(const CropResultPair& pair) {
131 DCHECK_GT(image_info_.pixels_per_side, 0);
132
133 if (!pair.second) { // Failed to encode to bytes representation.
hashimoto 2016/03/04 06:39:50 Checking pair.second looks too subtle. Could you m
satorux1 2016/03/09 08:50:40 Done.
134 OnDecodeImageFailed();
135 return;
136 }
137 OnImageFinalized(pair.first, *pair.second,
138 true /* image_bytes_regenerated */);
139 }
140
141 void UserImageRequest::OnImageFinalized(
142 const SkBitmap& image,
143 const user_manager::UserImage::Bytes& image_bytes,
144 bool image_bytes_regenerated) {
116 SkBitmap final_image = image; 145 SkBitmap final_image = image;
117 // Make the SkBitmap immutable as we won't modify it. This is important 146 // Make the SkBitmap immutable as we won't modify it. This is important
118 // because otherwise it gets duplicated during painting, wasting memory. 147 // because otherwise it gets duplicated during painting, wasting memory.
119 final_image.setImmutable(); 148 final_image.setImmutable();
120 gfx::ImageSkia final_image_skia = 149 gfx::ImageSkia final_image_skia =
121 gfx::ImageSkia::CreateFrom1xBitmap(final_image); 150 gfx::ImageSkia::CreateFrom1xBitmap(final_image);
122 final_image_skia.MakeThreadSafe(); 151 final_image_skia.MakeThreadSafe();
123 user_manager::UserImage user_image(final_image_skia, image_data_); 152 user_manager::UserImage user_image(final_image_skia, image_bytes);
124 user_image.set_file_path(image_info_.file_path); 153 user_image.set_file_path(image_info_.file_path);
125 if (image_info_.image_codec == ImageDecoder::ROBUST_JPEG_CODEC) 154 if (image_info_.image_codec == ImageDecoder::ROBUST_JPEG_CODEC ||
155 image_bytes_regenerated)
126 user_image.MarkAsSafe(); 156 user_image.MarkAsSafe();
127 image_info_.loaded_cb.Run(user_image); 157 image_info_.loaded_cb.Run(user_image);
128 delete this; 158 delete this;
129 } 159 }
130 160
131 void UserImageRequest::OnDecodeImageFailed() { 161 void UserImageRequest::OnDecodeImageFailed() {
132 image_info_.loaded_cb.Run(user_manager::UserImage()); 162 image_info_.loaded_cb.Run(user_manager::UserImage());
133 delete this; 163 delete this;
134 } 164 }
135 165
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 ImageDecoder::ImageCodec image_codec, 205 ImageDecoder::ImageCodec image_codec,
176 int pixels_per_side, 206 int pixels_per_side,
177 const LoadedCallback& loaded_cb) { 207 const LoadedCallback& loaded_cb) {
178 DecodeImage( 208 DecodeImage(
179 ImageInfo(base::FilePath(), pixels_per_side, image_codec, loaded_cb), 209 ImageInfo(base::FilePath(), pixels_per_side, image_codec, loaded_cb),
180 background_task_runner, data.get(), true /* data_is_ready */); 210 background_task_runner, data.get(), true /* data_is_ready */);
181 } 211 }
182 212
183 } // namespace user_image_loader 213 } // namespace user_image_loader
184 } // namespace chromeos 214 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698