| Index: chrome/utility/image_decoder_impl.cc
|
| diff --git a/chrome/utility/image_decoder_impl.cc b/chrome/utility/image_decoder_impl.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1c809334e89c8d62ad9d374fa4bb7d6d6e8cc7d9
|
| --- /dev/null
|
| +++ b/chrome/utility/image_decoder_impl.cc
|
| @@ -0,0 +1,137 @@
|
| +// Copyright 2014 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/utility/image_decoder_impl.h"
|
| +
|
| +#include <string.h>
|
| +
|
| +#include "base/base64.h"
|
| +#include "base/memory/ref_counted.h"
|
| +#include "base/time/time.h"
|
| +#include "chrome/common/chrome_utility_messages.h"
|
| +#include "content/child/child_process.h"
|
| +#include "content/public/child/image_decoder_utils.h"
|
| +#include "content/public/common/content_switches.h"
|
| +#include "skia/ext/image_operations.h"
|
| +#include "third_party/skia/include/core/SkBitmap.h"
|
| +#include "ui/gfx/codec/jpeg_codec.h"
|
| +#include "ui/gfx/geometry/size.h"
|
| +
|
| +namespace mojo {
|
| +
|
| +// TODO(amistry): Move somewhere else.
|
| +template <>
|
| +struct TypeConverter<content::ImageDataPtr, SkBitmap> {
|
| + static content::ImageDataPtr Convert(const SkBitmap& bitmap) {
|
| + content::ImageDataPtr result = content::ImageData::New();
|
| + const SkImageInfo& info = bitmap.info();
|
| + result->color_type = info.fColorType;
|
| + result->alpha_type = info.fAlphaType;
|
| + result->width = info.fWidth;
|
| + result->height = info.fHeight;
|
| + SkAutoLockPixels lock(bitmap);
|
| + size_t size = bitmap.getSize();
|
| + result->pixels = mojo::Array<uint8_t>::New(size);
|
| + memcpy(&result->pixels[0], bitmap.getPixels(), size);
|
| + return result.Pass();
|
| + }
|
| +};
|
| +
|
| +} // namespace mojo
|
| +
|
| +namespace content {
|
| +
|
| +ImageDecoderImpl::ImageDecoderImpl() {
|
| +}
|
| +
|
| +ImageDecoderImpl::~ImageDecoderImpl() {
|
| + // TODO(amistry): Single process mode.
|
| + // TODO(amistry): This is the wrong place to do this.
|
| + LOG(INFO) << "Possibly destroying utility process";
|
| + content::ChildProcess::current()->ReleaseProcess();
|
| +}
|
| +
|
| +void ImageDecoderImpl::DecodeImage(
|
| + mojo::Array<uint8_t> encoded_data,
|
| + bool use_robust_jpeg,
|
| + bool shrink_to_fit,
|
| + const mojo::Callback<void(bool, ImageDataPtr)>& callback) {
|
| + LOG(INFO) << "ImageDecoderImpl::DecodeImage: " << encoded_data.size()
|
| + << ", " << use_robust_jpeg << ", " << shrink_to_fit;
|
| + if (use_robust_jpeg) {
|
| + // Our robust jpeg decoding is using IJG libjpeg.
|
| + if (gfx::JPEGCodec::JpegLibraryVariant() == gfx::JPEGCodec::IJG_LIBJPEG &&
|
| + encoded_data.size()) {
|
| + scoped_ptr<SkBitmap> decoded_image(gfx::JPEGCodec::Decode(
|
| + &encoded_data[0], encoded_data.size()));
|
| + if (decoded_image.get() && !decoded_image->empty()) {
|
| + ImageDataPtr image = ImageData::From(*decoded_image);
|
| + LOG(INFO) << "............Done decoding image";
|
| + callback.Run(true, image.Pass());
|
| + return;
|
| + }
|
| + }
|
| + LOG(ERROR) << "Unable to do robust JPEG decode";
|
| + callback.Run(false, ImageDataPtr());
|
| + } else {
|
| + SkBitmap decoded_image = content::DecodeImage(&encoded_data[0],
|
| + gfx::Size(),
|
| + encoded_data.size());
|
| +
|
| + ImageDataPtr image = ImageData::From(decoded_image);
|
| + // TODO(amistry): Do this!
|
| + // TODO(amistry): Resizing is (should be) orthogonal to decoding.
|
| + if (GetSerializedSize_(image) > 32*1024*1024) {
|
| + if (shrink_to_fit) {
|
| + LOG(ERROR) << "Resize currently unsupported";
|
| + } else {
|
| + // Image too big for IPC message, but caller didn't request resize;
|
| + LOG(ERROR) << "Decoded image too large for IPC message";
|
| + }
|
| + callback.Run(false, ImageDataPtr());
|
| + return;
|
| + }
|
| +
|
| + callback.Run(true, image.Pass());
|
| + }
|
| + LOG(INFO) << "............Done decoding image";
|
| +/*
|
| + int64_t struct_size = sizeof(ChromeUtilityHostMsg_DecodeImage_Succeeded);
|
| + int64_t image_size = decoded_image.computeSize64();
|
| + int halves = 0;
|
| + while (struct_size + (image_size >> 2*halves) > max_ipc_message_size_)
|
| + halves++;
|
| + if (halves) {
|
| + if (shrink_to_fit) {
|
| + // If decoded image is too large for IPC message, shrink it by halves.
|
| + // This prevents quality loss, and should never overshrink on displays
|
| + // smaller than 3600x2400.
|
| + // TODO (Issue 416916): Instead of shrinking, return via shared memory
|
| + decoded_image = skia::ImageOperations::Resize(
|
| + decoded_image, skia::ImageOperations::RESIZE_LANCZOS3,
|
| + decoded_image.width() >> halves, decoded_image.height() >> halves);
|
| + } else {
|
| + decoded_image.reset();
|
| + }
|
| + }
|
| + return decoded_image;
|
| +*/
|
| +}
|
| +
|
| +void ImageDecoderImpl::DecodeImageBase64(
|
| + const mojo::String& encoded_data,
|
| + const mojo::Callback<void(bool, ImageDataPtr)>& callback) {
|
| + std::string decoded_data;
|
| + if (!base::Base64Decode(encoded_data.get(), &decoded_data)) {
|
| + LOG(ERROR) << "Unable to base64 decode image";
|
| + callback.Run(false, ImageDataPtr());
|
| + return;
|
| + }
|
| +
|
| + mojo::Array<uint8_t> decoded_array(decoded_data.size());
|
| + // TODO(amistry): This seems wrong.
|
| + memcpy(&decoded_array[0], decoded_data.data(), decoded_data.size());
|
| + DecodeImage(decoded_array.Pass(), false, false, callback);
|
| +}
|
| +
|
| +} // namespace content
|
|
|