root/chrome/browser/chromeos/login/user_image_loader.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. loaded_cb
  2. image_codec_
  3. Start
  4. Start
  5. ReadAndDecodeImage
  6. DecodeImage
  7. OnImageDecoded
  8. OnDecodeImageFailed

// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/login/user_image_loader.h"

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/sequenced_task_runner.h"
#include "chrome/browser/chromeos/login/helper.h"
#include "chrome/browser/chromeos/login/user_image.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/skbitmap_operations.h"

namespace chromeos {

UserImageLoader::ImageInfo::ImageInfo(int size,
                                      const LoadedCallback& loaded_cb)
    : size(size),
      loaded_cb(loaded_cb) {
}

UserImageLoader::ImageInfo::~ImageInfo() {
}

UserImageLoader::UserImageLoader(
    ImageDecoder::ImageCodec image_codec,
    scoped_refptr<base::SequencedTaskRunner> background_task_runner)
    : foreground_task_runner_(base::MessageLoopProxy::current()),
      background_task_runner_(background_task_runner),
      image_codec_(image_codec) {
}

UserImageLoader::~UserImageLoader() {
}

void UserImageLoader::Start(const std::string& filepath,
                            int size,
                            const LoadedCallback& loaded_cb) {
  background_task_runner_->PostTask(
      FROM_HERE,
      base::Bind(&UserImageLoader::ReadAndDecodeImage,
                 this,
                 filepath,
                 ImageInfo(size, loaded_cb)));
}

void UserImageLoader::Start(scoped_ptr<std::string> data,
                            int size,
                            const LoadedCallback& loaded_cb) {
  background_task_runner_->PostTask(FROM_HERE,
                                    base::Bind(&UserImageLoader::DecodeImage,
                                        this,
                                        base::Passed(&data),
                                        ImageInfo(size, loaded_cb)));
}

void UserImageLoader::ReadAndDecodeImage(const std::string& filepath,
                                         const ImageInfo& image_info) {
  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());

  scoped_ptr<std::string> data(new std::string);
  const bool success =
      base::ReadFileToString(base::FilePath(filepath), data.get());
  DCHECK(success);

  DecodeImage(data.Pass(), image_info);
}

void UserImageLoader::DecodeImage(const scoped_ptr<std::string> data,
                                  const ImageInfo& image_info) {
  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());

  scoped_refptr<ImageDecoder> image_decoder =
      new ImageDecoder(this, *data, image_codec_);
  image_info_map_.insert(std::make_pair(image_decoder.get(), image_info));
  image_decoder->Start(background_task_runner_);
}

void UserImageLoader::OnImageDecoded(const ImageDecoder* decoder,
                                     const SkBitmap& decoded_image) {
  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());

  ImageInfoMap::iterator it = image_info_map_.find(decoder);
  if (it == image_info_map_.end()) {
    NOTREACHED();
    return;
  }
  const int target_size = it->second.size;
  const LoadedCallback loaded_cb = it->second.loaded_cb;
  image_info_map_.erase(it);

  SkBitmap final_image = decoded_image;

  if (target_size > 0) {
    // Auto crop the image, taking the largest square in the center.
    int size = std::min(decoded_image.width(), decoded_image.height());
    int x = (decoded_image.width() - size) / 2;
    int y = (decoded_image.height() - size) / 2;
    SkBitmap cropped_image =
        SkBitmapOperations::CreateTiledBitmap(decoded_image, x, y, size, size);
    if (size > target_size) {
      // Also downsize the image to save space and memory.
      final_image =
          skia::ImageOperations::Resize(cropped_image,
                                        skia::ImageOperations::RESIZE_LANCZOS3,
                                        target_size,
                                        target_size);
    } else {
      final_image = cropped_image;
    }
  }
  // Make the SkBitmap immutable as we won't modify it. This is important
  // because otherwise it gets duplicated during painting, wasting memory.
  final_image.setImmutable();
  gfx::ImageSkia final_image_skia =
      gfx::ImageSkia::CreateFrom1xBitmap(final_image);
  final_image_skia.MakeThreadSafe();
  UserImage user_image(final_image_skia, decoder->get_image_data());
  if (image_codec_ == ImageDecoder::ROBUST_JPEG_CODEC)
    user_image.MarkAsSafe();
  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::Bind(loaded_cb, user_image));
}

void UserImageLoader::OnDecodeImageFailed(const ImageDecoder* decoder) {
  DCHECK(background_task_runner_->RunsTasksOnCurrentThread());

  ImageInfoMap::iterator it = image_info_map_.find(decoder);
  if (it == image_info_map_.end()) {
    NOTREACHED();
    return;
  }
  const LoadedCallback loaded_cb = it->second.loaded_cb;
  image_info_map_.erase(it);

  foreground_task_runner_->PostTask(FROM_HERE,
                                    base::Bind(loaded_cb, UserImage()));
}

}  // namespace chromeos

/* [<][>][^][v][top][bottom][index][help] */