1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/chromeos/login/user_image_loader.h"
6
7#include "base/file_path.h"
8#include "base/file_util.h"
9#include "base/message_loop.h"
10#include "chrome/browser/chromeos/login/image_decoder.h"
11#include "chrome/browser/chromeos/login/helper.h"
12#include "content/browser/browser_thread.h"
13#include "skia/ext/image_operations.h"
14#include "third_party/skia/include/core/SkBitmap.h"
15#include "ui/gfx/codec/png_codec.h"
16#include "ui/gfx/skbitmap_operations.h"
17
18namespace chromeos {
19
20UserImageLoader::UserImageLoader(Delegate* delegate)
21    : target_message_loop_(NULL),
22      delegate_(delegate) {
23}
24
25UserImageLoader::~UserImageLoader() {
26}
27
28void UserImageLoader::Start(const std::string& username,
29                            const std::string& filename,
30                            bool should_save_image) {
31  target_message_loop_ = MessageLoop::current();
32
33  ImageInfo image_info(username, should_save_image);
34  BrowserThread::PostTask(BrowserThread::FILE,
35                          FROM_HERE,
36                          NewRunnableMethod(this,
37                                            &UserImageLoader::LoadImage,
38                                            filename,
39                                            image_info));
40}
41
42void UserImageLoader::LoadImage(const std::string& filepath,
43                                const ImageInfo& image_info) {
44  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
45  std::string image_data;
46  file_util::ReadFileToString(FilePath(filepath), &image_data);
47
48  scoped_refptr<ImageDecoder> image_decoder =
49      new ImageDecoder(this, image_data);
50  image_info_map_.insert(std::make_pair(image_decoder.get(), image_info));
51  image_decoder->Start();
52}
53
54void UserImageLoader::OnImageDecoded(const ImageDecoder* decoder,
55                                     const SkBitmap& decoded_image) {
56  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
57  ImageInfoMap::iterator info_it = image_info_map_.find(decoder);
58  if (info_it == image_info_map_.end()) {
59    NOTREACHED();
60    return;
61  }
62  ImageInfo image_info = info_it->second;
63  SkBitmap final_image = decoded_image;
64  if (image_info.should_save_image) {
65    // Auto crop the image, taking the largest square in the center.
66    // Also make the image smaller to save space and memory.
67    int size = std::min(decoded_image.width(), decoded_image.height());
68    int x = (decoded_image.width() - size) / 2;
69    int y = (decoded_image.height() - size) / 2;
70    SkBitmap cropped_image =
71        SkBitmapOperations::CreateTiledBitmap(decoded_image, x, y, size, size);
72    final_image =
73        skia::ImageOperations::Resize(cropped_image,
74                                      skia::ImageOperations::RESIZE_LANCZOS3,
75                                      login::kUserImageSize,
76                                      login::kUserImageSize);
77  }
78  target_message_loop_->PostTask(FROM_HERE,
79      NewRunnableMethod(this,
80                        &UserImageLoader::NotifyDelegate,
81                        final_image,
82                        image_info));
83  image_info_map_.erase(info_it);
84}
85
86void UserImageLoader::OnDecodeImageFailed(const ImageDecoder* decoder) {
87  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
88  image_info_map_.erase(decoder);
89}
90
91void UserImageLoader::NotifyDelegate(const SkBitmap& image,
92                                     const ImageInfo& image_info) {
93  if (delegate_) {
94    delegate_->OnImageLoaded(image_info.username,
95                             image,
96                             image_info.should_save_image);
97  }
98}
99
100}  // namespace chromeos
101