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 3// found in the LICENSE file. 4 5#include "ui/snapshot/snapshot_async.h" 6 7#include "base/location.h" 8#include "base/memory/ref_counted.h" 9#include "base/numerics/safe_conversions.h" 10#include "base/task_runner_util.h" 11#include "skia/ext/image_operations.h" 12#include "third_party/skia/include/core/SkBitmap.h" 13#include "third_party/skia/include/core/SkPixelRef.h" 14#include "ui/gfx/codec/png_codec.h" 15#include "ui/gfx/image/image.h" 16#include "ui/gfx/image/image_skia.h" 17#include "ui/gfx/skbitmap_operations.h" 18 19namespace ui { 20 21namespace { 22 23void OnFrameScalingFinished(const GrabWindowSnapshotAsyncCallback& callback, 24 const SkBitmap& scaled_bitmap) { 25 callback.Run(gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(scaled_bitmap))); 26} 27 28SkBitmap ScaleBitmap(const SkBitmap& input_bitmap, 29 const gfx::Size& target_size) { 30 return skia::ImageOperations::Resize(input_bitmap, 31 skia::ImageOperations::RESIZE_GOOD, 32 target_size.width(), 33 target_size.height(), 34 static_cast<SkBitmap::Allocator*>(NULL)); 35} 36 37scoped_refptr<base::RefCountedBytes> EncodeBitmap(const SkBitmap& bitmap) { 38 scoped_refptr<base::RefCountedBytes> png_data(new base::RefCountedBytes); 39 SkAutoLockPixels lock(bitmap); 40 unsigned char* pixels = reinterpret_cast<unsigned char*>(bitmap.getPixels()); 41#if SK_A32_SHIFT == 24 && SK_R32_SHIFT == 16 && SK_G32_SHIFT == 8 42 gfx::PNGCodec::ColorFormat kColorFormat = gfx::PNGCodec::FORMAT_BGRA; 43#elif SK_A32_SHIFT == 24 && SK_B32_SHIFT == 16 && SK_G32_SHIFT == 8 44 gfx::PNGCodec::ColorFormat kColorFormat = gfx::PNGCodec::FORMAT_RGBA; 45#else 46#error Unknown color format 47#endif 48 if (!gfx::PNGCodec::Encode(pixels, 49 kColorFormat, 50 gfx::Size(bitmap.width(), bitmap.height()), 51 base::checked_cast<int>(bitmap.rowBytes()), 52 true, 53 std::vector<gfx::PNGCodec::Comment>(), 54 &png_data->data())) { 55 return scoped_refptr<base::RefCountedBytes>(); 56 } 57 return png_data; 58} 59 60} // namespace 61 62void SnapshotAsync::ScaleCopyOutputResult( 63 const GrabWindowSnapshotAsyncCallback& callback, 64 const gfx::Size& target_size, 65 scoped_refptr<base::TaskRunner> background_task_runner, 66 scoped_ptr<cc::CopyOutputResult> result) { 67 if (result->IsEmpty()) { 68 callback.Run(gfx::Image()); 69 return; 70 } 71 72 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it 73 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't 74 // be used here because it's not in content/public. Move the scaling code 75 // somewhere so that it can be reused here. 76 base::PostTaskAndReplyWithResult( 77 background_task_runner, 78 FROM_HERE, 79 base::Bind(ScaleBitmap, *result->TakeBitmap(), target_size), 80 base::Bind(&OnFrameScalingFinished, callback)); 81} 82 83void SnapshotAsync::EncodeCopyOutputResult( 84 const GrabWindowSnapshotAsyncPNGCallback& callback, 85 scoped_refptr<base::TaskRunner> background_task_runner, 86 scoped_ptr<cc::CopyOutputResult> result) { 87 if (result->IsEmpty()) { 88 callback.Run(scoped_refptr<base::RefCountedBytes>()); 89 return; 90 } 91 92 // TODO(sergeyu): Potentially images can be scaled on GPU before reading it 93 // from GPU. Image scaling is implemented in content::GlHelper, but it's can't 94 // be used here because it's not in content/public. Move the scaling code 95 // somewhere so that it can be reused here. 96 base::PostTaskAndReplyWithResult( 97 background_task_runner, 98 FROM_HERE, 99 base::Bind(EncodeBitmap, *result->TakeBitmap()), 100 callback); 101} 102 103} // namespace ui 104