| Index: chrome/browser/chromeos/login/users/avatar/user_image_loader.cc
|
| diff --git a/chrome/browser/chromeos/login/users/avatar/user_image_loader.cc b/chrome/browser/chromeos/login/users/avatar/user_image_loader.cc
|
| index dc0e9117a3288df849e0a1ee5c5adbfd4ee0e7e7..d8fa49df6c6f86008c5a8c132ce6dbd458ab5791 100644
|
| --- a/chrome/browser/chromeos/login/users/avatar/user_image_loader.cc
|
| +++ b/chrome/browser/chromeos/login/users/avatar/user_image_loader.cc
|
| @@ -45,8 +45,12 @@ struct ImageInfo {
|
| };
|
|
|
| // Crops |image| to the square format and downsizes the image to
|
| -// |target_size| in pixels.
|
| -SkBitmap CropImage(const SkBitmap& image, int target_size) {
|
| +// |target_size| in pixels. On success, returns true and stores the cropped
|
| +// image in |bitmap| and the bytes representation in |byytes|.
|
| +bool CropImage(const SkBitmap& image,
|
| + int target_size,
|
| + SkBitmap* bitmap,
|
| + user_manager::UserImage::Bytes* bytes) {
|
| DCHECK_GT(target_size, 0);
|
|
|
| SkBitmap final_image;
|
| @@ -64,7 +68,16 @@ SkBitmap CropImage(const SkBitmap& image, int target_size) {
|
| } else {
|
| final_image = cropped_image;
|
| }
|
| - return final_image;
|
| +
|
| + // Encode the cropped image to web-compatible bytes representation
|
| + scoped_ptr<user_manager::UserImage::Bytes> encoded =
|
| + user_manager::UserImage::Encode(final_image);
|
| + if (!encoded)
|
| + return false;
|
| +
|
| + bitmap->swap(final_image);
|
| + bytes->swap(*encoded);
|
| + return true;
|
| }
|
|
|
| // Handles the decoded image returned from ImageDecoder through the
|
| @@ -85,8 +98,16 @@ class UserImageRequest : public ImageDecoder::ImageRequest {
|
| void OnImageDecoded(const SkBitmap& decoded_image) override;
|
| void OnDecodeImageFailed() override;
|
|
|
| - // Called after the image is transformed (cropped and downsized) as needed.
|
| - void OnImageFinalized(const SkBitmap& image);
|
| + // Called after the image is cropped (and downsized) as needed.
|
| + void OnImageCropped(SkBitmap* bitmap,
|
| + user_manager::UserImage::Bytes* bytes,
|
| + bool succeeded);
|
| +
|
| + // Called after the image is finalized. |image_bytes_regenerated| is true
|
| + // if |image_bytes| is regenerated from the cropped image.
|
| + void OnImageFinalized(const SkBitmap& image,
|
| + const user_manager::UserImage::Bytes& image_bytes,
|
| + bool image_bytes_regenerated);
|
|
|
| private:
|
| const ImageInfo image_info_;
|
| @@ -100,19 +121,38 @@ class UserImageRequest : public ImageDecoder::ImageRequest {
|
| void UserImageRequest::OnImageDecoded(const SkBitmap& decoded_image) {
|
| int target_size = image_info_.pixels_per_side;
|
| if (target_size > 0) {
|
| - // Transforming an image could be expensive, hence posting to the
|
| - // background thread.
|
| + // Cropping an image could be expensive, hence posting to the background
|
| + // thread.
|
| + SkBitmap* bitmap = new SkBitmap;
|
| + user_manager::UserImage::Bytes* bytes = new user_manager::UserImage::Bytes;
|
| base::PostTaskAndReplyWithResult(
|
| background_task_runner_.get(), FROM_HERE,
|
| - base::Bind(&CropImage, decoded_image, target_size),
|
| - base::Bind(&UserImageRequest::OnImageFinalized,
|
| - weak_ptr_factory_.GetWeakPtr()));
|
| + base::Bind(&CropImage, decoded_image, target_size, bitmap, bytes),
|
| + base::Bind(&UserImageRequest::OnImageCropped,
|
| + weak_ptr_factory_.GetWeakPtr(), base::Owned(bitmap),
|
| + base::Owned(bytes)));
|
| } else {
|
| - OnImageFinalized(decoded_image);
|
| + OnImageFinalized(decoded_image, image_data_,
|
| + false /* image_bytes_regenerated */);
|
| + }
|
| +}
|
| +
|
| +void UserImageRequest::OnImageCropped(SkBitmap* bitmap,
|
| + user_manager::UserImage::Bytes* bytes,
|
| + bool succeeded) {
|
| + DCHECK_GT(image_info_.pixels_per_side, 0);
|
| +
|
| + if (!succeeded) {
|
| + OnDecodeImageFailed();
|
| + return;
|
| }
|
| + OnImageFinalized(*bitmap, *bytes, true /* image_bytes_regenerated */);
|
| }
|
|
|
| -void UserImageRequest::OnImageFinalized(const SkBitmap& image) {
|
| +void UserImageRequest::OnImageFinalized(
|
| + const SkBitmap& image,
|
| + const user_manager::UserImage::Bytes& image_bytes,
|
| + bool image_bytes_regenerated) {
|
| SkBitmap final_image = image;
|
| // Make the SkBitmap immutable as we won't modify it. This is important
|
| // because otherwise it gets duplicated during painting, wasting memory.
|
| @@ -120,9 +160,10 @@ void UserImageRequest::OnImageFinalized(const SkBitmap& image) {
|
| gfx::ImageSkia final_image_skia =
|
| gfx::ImageSkia::CreateFrom1xBitmap(final_image);
|
| final_image_skia.MakeThreadSafe();
|
| - user_manager::UserImage user_image(final_image_skia, image_data_);
|
| + user_manager::UserImage user_image(final_image_skia, image_bytes);
|
| user_image.set_file_path(image_info_.file_path);
|
| - if (image_info_.image_codec == ImageDecoder::ROBUST_JPEG_CODEC)
|
| + if (image_info_.image_codec == ImageDecoder::ROBUST_JPEG_CODEC ||
|
| + image_bytes_regenerated)
|
| user_image.MarkAsSafe();
|
| image_info_.loaded_cb.Run(user_image);
|
| delete this;
|
|
|