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

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

Issue 931993002: Make image_decoder a Leaky LazyInstance (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add ImageDecoder->RemoveDelegate Created 5 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 "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
(...skipping 13 matching lines...) Expand all
24 int pixels_per_side, 24 int pixels_per_side,
25 const LoadedCallback& loaded_cb) 25 const LoadedCallback& loaded_cb)
26 : file_path(file_path), 26 : file_path(file_path),
27 pixels_per_side(pixels_per_side), 27 pixels_per_side(pixels_per_side),
28 loaded_cb(loaded_cb) { 28 loaded_cb(loaded_cb) {
29 } 29 }
30 30
31 UserImageLoader::ImageInfo::~ImageInfo() { 31 UserImageLoader::ImageInfo::~ImageInfo() {
32 } 32 }
33 33
34 UserImageLoader::ImageData::ImageData(const ImageInfo& image_info,
35 const std::string& data)
36 : image_info(image_info), data(data.begin(), data.end()) {
37 }
38
39 UserImageLoader::ImageData::~ImageData() {
40 }
41
34 UserImageLoader::UserImageLoader( 42 UserImageLoader::UserImageLoader(
35 ImageDecoder::ImageCodec image_codec, 43 ImageDecoder::ImageCodec image_codec,
36 scoped_refptr<base::SequencedTaskRunner> background_task_runner) 44 scoped_refptr<base::SequencedTaskRunner> background_task_runner)
37 : foreground_task_runner_(base::MessageLoopProxy::current()), 45 : foreground_task_runner_(base::MessageLoopProxy::current()),
38 background_task_runner_(background_task_runner), 46 background_task_runner_(background_task_runner),
39 image_codec_(image_codec) { 47 image_codec_(image_codec) {
40 } 48 }
41 49
42 UserImageLoader::~UserImageLoader() { 50 UserImageLoader::~UserImageLoader() {
43 } 51 }
(...skipping 28 matching lines...) Expand all
72 80
73 // In case ReadFileToString() fails, |data| is empty and DecodeImage() calls 81 // In case ReadFileToString() fails, |data| is empty and DecodeImage() calls
74 // back to OnDecodeImageFailed(). 82 // back to OnDecodeImageFailed().
75 DecodeImage(data.Pass(), image_info); 83 DecodeImage(data.Pass(), image_info);
76 } 84 }
77 85
78 void UserImageLoader::DecodeImage(const scoped_ptr<std::string> data, 86 void UserImageLoader::DecodeImage(const scoped_ptr<std::string> data,
79 const ImageInfo& image_info) { 87 const ImageInfo& image_info) {
80 DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); 88 DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
81 89
82 scoped_refptr<ImageDecoder> image_decoder = 90 ImageData image_data(image_info, *data);
83 new ImageDecoder(this, *data, image_codec_); 91 image_data_queue_.push(image_data);
84 image_info_map_.insert(std::make_pair(image_decoder.get(), image_info)); 92 ImageDecoder::GetInstance()->Start(this, *data, image_codec_,
85 image_decoder->Start(background_task_runner_); 93 background_task_runner_, false);
86 } 94 }
87 95
88 void UserImageLoader::OnImageDecoded(const ImageDecoder* decoder, 96 void UserImageLoader::OnImageDecoded(const SkBitmap& decoded_image) {
89 const SkBitmap& decoded_image) {
90 DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); 97 DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
91 98
92 ImageInfoMap::iterator it = image_info_map_.find(decoder); 99 const ImageData& image_data = image_data_queue_.front();
93 if (it == image_info_map_.end()) { 100 const ImageInfo& image_info = image_data.image_info;
94 NOTREACHED(); 101 const std::string file_path = image_info.file_path;
95 return; 102 const int target_size = image_info.pixels_per_side;
96 } 103 const LoadedCallback loaded_cb = image_info.loaded_cb;
97 const std::string file_path = it->second.file_path; 104 std::vector<unsigned char> original_data = image_data.data;
98 const int target_size = it->second.pixels_per_side; 105 image_data_queue_.pop();
dcheng 2015/03/19 14:25:46 After thinking about this, I feel uncomfortable wi
Theresa 2015/03/19 21:54:56 I created a UserImageLoader::ImageRequest subclass
dcheng 2015/03/20 00:14:45 I think it's OK for those single-shot instances to
Theresa 2015/03/20 19:09:01 Done.
99 const LoadedCallback loaded_cb = it->second.loaded_cb;
100 image_info_map_.erase(it);
101 106
102 SkBitmap final_image = decoded_image; 107 SkBitmap final_image = decoded_image;
103 108
104 if (target_size > 0) { 109 if (target_size > 0) {
105 // Auto crop the image, taking the largest square in the center. 110 // Auto crop the image, taking the largest square in the center.
106 int pixels_per_side = 111 int pixels_per_side =
107 std::min(decoded_image.width(), decoded_image.height()); 112 std::min(decoded_image.width(), decoded_image.height());
108 int x = (decoded_image.width() - pixels_per_side) / 2; 113 int x = (decoded_image.width() - pixels_per_side) / 2;
109 int y = (decoded_image.height() - pixels_per_side) / 2; 114 int y = (decoded_image.height() - pixels_per_side) / 2;
110 SkBitmap cropped_image = SkBitmapOperations::CreateTiledBitmap( 115 SkBitmap cropped_image = SkBitmapOperations::CreateTiledBitmap(
111 decoded_image, x, y, pixels_per_side, pixels_per_side); 116 decoded_image, x, y, pixels_per_side, pixels_per_side);
112 if (pixels_per_side > target_size) { 117 if (pixels_per_side > target_size) {
113 // Also downsize the image to save space and memory. 118 // Also downsize the image to save space and memory.
114 final_image = 119 final_image =
115 skia::ImageOperations::Resize(cropped_image, 120 skia::ImageOperations::Resize(cropped_image,
116 skia::ImageOperations::RESIZE_LANCZOS3, 121 skia::ImageOperations::RESIZE_LANCZOS3,
117 target_size, 122 target_size,
118 target_size); 123 target_size);
119 } else { 124 } else {
120 final_image = cropped_image; 125 final_image = cropped_image;
121 } 126 }
122 } 127 }
123 // Make the SkBitmap immutable as we won't modify it. This is important 128 // Make the SkBitmap immutable as we won't modify it. This is important
124 // because otherwise it gets duplicated during painting, wasting memory. 129 // because otherwise it gets duplicated during painting, wasting memory.
125 final_image.setImmutable(); 130 final_image.setImmutable();
126 gfx::ImageSkia final_image_skia = 131 gfx::ImageSkia final_image_skia =
127 gfx::ImageSkia::CreateFrom1xBitmap(final_image); 132 gfx::ImageSkia::CreateFrom1xBitmap(final_image);
128 final_image_skia.MakeThreadSafe(); 133 final_image_skia.MakeThreadSafe();
129 user_manager::UserImage user_image(final_image_skia, 134 user_manager::UserImage user_image(final_image_skia, original_data);
130 decoder->get_image_data());
131 user_image.set_file_path(file_path); 135 user_image.set_file_path(file_path);
132 if (image_codec_ == ImageDecoder::ROBUST_JPEG_CODEC) 136 if (image_codec_ == ImageDecoder::ROBUST_JPEG_CODEC)
133 user_image.MarkAsSafe(); 137 user_image.MarkAsSafe();
134 foreground_task_runner_->PostTask(FROM_HERE, 138 foreground_task_runner_->PostTask(FROM_HERE,
135 base::Bind(loaded_cb, user_image)); 139 base::Bind(loaded_cb, user_image));
136 } 140 }
137 141
138 void UserImageLoader::OnDecodeImageFailed(const ImageDecoder* decoder) { 142 void UserImageLoader::OnDecodeImageFailed() {
139 DCHECK(background_task_runner_->RunsTasksOnCurrentThread()); 143 DCHECK(background_task_runner_->RunsTasksOnCurrentThread());
140 144
141 ImageInfoMap::iterator it = image_info_map_.find(decoder); 145 ImageInfo image_info = image_data_queue_.front().image_info;
142 if (it == image_info_map_.end()) { 146 const LoadedCallback loaded_cb = image_info.loaded_cb;
143 NOTREACHED(); 147 image_data_queue_.pop();
144 return;
145 }
146 const LoadedCallback loaded_cb = it->second.loaded_cb;
147 image_info_map_.erase(it);
148 148
149 foreground_task_runner_->PostTask( 149 foreground_task_runner_->PostTask(
150 FROM_HERE, base::Bind(loaded_cb, user_manager::UserImage())); 150 FROM_HERE, base::Bind(loaded_cb, user_manager::UserImage()));
151 } 151 }
152 152
153 } // namespace chromeos 153 } // namespace chromeos
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698