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

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: address comments 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
« no previous file with comments | « no previous file | chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 27 matching lines...) Expand all
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 // Crops |image| to the square format and downsizes the image to 47 // Crops |image| to the square format and downsizes the image to
48 // |target_size| in pixels. 48 // |target_size| in pixels. On success, returns true and stores the cropped
49 SkBitmap CropImage(const SkBitmap& image, int target_size) { 49 // image in |bitmap| and the bytes representation in |byytes|.
50 bool CropImage(const SkBitmap& image,
51 int target_size,
52 SkBitmap* bitmap,
53 user_manager::UserImage::Bytes* bytes) {
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> encoded =
74 user_manager::UserImage::Encode(final_image);
75 if (!encoded)
76 return false;
77
78 bitmap->swap(final_image);
79 bytes->swap(*encoded);
80 return true;
68 } 81 }
69 82
70 // Handles the decoded image returned from ImageDecoder through the 83 // Handles the decoded image returned from ImageDecoder through the
71 // ImageRequest interface. 84 // ImageRequest interface.
72 class UserImageRequest : public ImageDecoder::ImageRequest { 85 class UserImageRequest : public ImageDecoder::ImageRequest {
73 public: 86 public:
74 UserImageRequest( 87 UserImageRequest(
75 const ImageInfo& image_info, 88 const ImageInfo& image_info,
76 const std::string& image_data, 89 const std::string& image_data,
77 scoped_refptr<base::SequencedTaskRunner> background_task_runner) 90 scoped_refptr<base::SequencedTaskRunner> background_task_runner)
78 : image_info_(image_info), 91 : image_info_(image_info),
79 image_data_(image_data.begin(), image_data.end()), 92 image_data_(image_data.begin(), image_data.end()),
80 background_task_runner_(background_task_runner), 93 background_task_runner_(background_task_runner),
81 weak_ptr_factory_(this) {} 94 weak_ptr_factory_(this) {}
82 ~UserImageRequest() override {} 95 ~UserImageRequest() override {}
83 96
84 // ImageDecoder::ImageRequest implementation. 97 // ImageDecoder::ImageRequest implementation.
85 void OnImageDecoded(const SkBitmap& decoded_image) override; 98 void OnImageDecoded(const SkBitmap& decoded_image) override;
86 void OnDecodeImageFailed() override; 99 void OnDecodeImageFailed() override;
87 100
88 // Called after the image is transformed (cropped and downsized) as needed. 101 // Called after the image is cropped (and downsized) as needed.
89 void OnImageFinalized(const SkBitmap& image); 102 void OnImageCropped(SkBitmap* bitmap,
103 user_manager::UserImage::Bytes* bytes,
104 bool succeeded);
105
106 // Called after the image is finalized. |image_bytes_regenerated| is true
107 // if |image_bytes| is regenerated from the cropped image.
108 void OnImageFinalized(const SkBitmap& image,
109 const user_manager::UserImage::Bytes& image_bytes,
110 bool image_bytes_regenerated);
90 111
91 private: 112 private:
92 const ImageInfo image_info_; 113 const ImageInfo image_info_;
93 const user_manager::UserImage::Bytes image_data_; 114 const user_manager::UserImage::Bytes image_data_;
94 scoped_refptr<base::SequencedTaskRunner> background_task_runner_; 115 scoped_refptr<base::SequencedTaskRunner> background_task_runner_;
95 116
96 // This should be the last member. 117 // This should be the last member.
97 base::WeakPtrFactory<UserImageRequest> weak_ptr_factory_; 118 base::WeakPtrFactory<UserImageRequest> weak_ptr_factory_;
98 }; 119 };
99 120
100 void UserImageRequest::OnImageDecoded(const SkBitmap& decoded_image) { 121 void UserImageRequest::OnImageDecoded(const SkBitmap& decoded_image) {
101 int target_size = image_info_.pixels_per_side; 122 int target_size = image_info_.pixels_per_side;
102 if (target_size > 0) { 123 if (target_size > 0) {
103 // Transforming an image could be expensive, hence posting to the 124 // Cropping an image could be expensive, hence posting to the background
104 // background thread. 125 // thread.
126 SkBitmap* bitmap = new SkBitmap;
127 user_manager::UserImage::Bytes* bytes = new user_manager::UserImage::Bytes;
105 base::PostTaskAndReplyWithResult( 128 base::PostTaskAndReplyWithResult(
106 background_task_runner_.get(), FROM_HERE, 129 background_task_runner_.get(), FROM_HERE,
107 base::Bind(&CropImage, decoded_image, target_size), 130 base::Bind(&CropImage, decoded_image, target_size, bitmap, bytes),
108 base::Bind(&UserImageRequest::OnImageFinalized, 131 base::Bind(&UserImageRequest::OnImageCropped,
109 weak_ptr_factory_.GetWeakPtr())); 132 weak_ptr_factory_.GetWeakPtr(), base::Owned(bitmap),
133 base::Owned(bytes)));
110 } else { 134 } else {
111 OnImageFinalized(decoded_image); 135 OnImageFinalized(decoded_image, image_data_,
136 false /* image_bytes_regenerated */);
112 } 137 }
113 } 138 }
114 139
115 void UserImageRequest::OnImageFinalized(const SkBitmap& image) { 140 void UserImageRequest::OnImageCropped(SkBitmap* bitmap,
141 user_manager::UserImage::Bytes* bytes,
142 bool succeeded) {
143 DCHECK_GT(image_info_.pixels_per_side, 0);
144
145 if (!succeeded) {
146 OnDecodeImageFailed();
147 return;
148 }
149 OnImageFinalized(*bitmap, *bytes, true /* image_bytes_regenerated */);
150 }
151
152 void UserImageRequest::OnImageFinalized(
153 const SkBitmap& image,
154 const user_manager::UserImage::Bytes& image_bytes,
155 bool image_bytes_regenerated) {
116 SkBitmap final_image = image; 156 SkBitmap final_image = image;
117 // Make the SkBitmap immutable as we won't modify it. This is important 157 // Make the SkBitmap immutable as we won't modify it. This is important
118 // because otherwise it gets duplicated during painting, wasting memory. 158 // because otherwise it gets duplicated during painting, wasting memory.
119 final_image.setImmutable(); 159 final_image.setImmutable();
120 gfx::ImageSkia final_image_skia = 160 gfx::ImageSkia final_image_skia =
121 gfx::ImageSkia::CreateFrom1xBitmap(final_image); 161 gfx::ImageSkia::CreateFrom1xBitmap(final_image);
122 final_image_skia.MakeThreadSafe(); 162 final_image_skia.MakeThreadSafe();
123 user_manager::UserImage user_image(final_image_skia, image_data_); 163 user_manager::UserImage user_image(final_image_skia, image_bytes);
124 user_image.set_file_path(image_info_.file_path); 164 user_image.set_file_path(image_info_.file_path);
125 if (image_info_.image_codec == ImageDecoder::ROBUST_JPEG_CODEC) 165 if (image_info_.image_codec == ImageDecoder::ROBUST_JPEG_CODEC ||
166 image_bytes_regenerated)
126 user_image.MarkAsSafe(); 167 user_image.MarkAsSafe();
127 image_info_.loaded_cb.Run(user_image); 168 image_info_.loaded_cb.Run(user_image);
128 delete this; 169 delete this;
129 } 170 }
130 171
131 void UserImageRequest::OnDecodeImageFailed() { 172 void UserImageRequest::OnDecodeImageFailed() {
132 image_info_.loaded_cb.Run(user_manager::UserImage()); 173 image_info_.loaded_cb.Run(user_manager::UserImage());
133 delete this; 174 delete this;
134 } 175 }
135 176
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 ImageDecoder::ImageCodec image_codec, 216 ImageDecoder::ImageCodec image_codec,
176 int pixels_per_side, 217 int pixels_per_side,
177 const LoadedCallback& loaded_cb) { 218 const LoadedCallback& loaded_cb) {
178 DecodeImage( 219 DecodeImage(
179 ImageInfo(base::FilePath(), pixels_per_side, image_codec, loaded_cb), 220 ImageInfo(base::FilePath(), pixels_per_side, image_codec, loaded_cb),
180 background_task_runner, data.get(), true /* data_is_ready */); 221 background_task_runner, data.get(), true /* data_is_ready */);
181 } 222 }
182 223
183 } // namespace user_image_loader 224 } // namespace user_image_loader
184 } // namespace chromeos 225 } // namespace chromeos
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/chromeos/login/users/avatar/user_image_manager_impl.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698