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 19 namespace ui { 20 21 namespace { 22 23 void OnFrameScalingFinished(const GrabWindowSnapshotAsyncCallback& callback, 24 const SkBitmap& scaled_bitmap) { 25 callback.Run(gfx::Image(gfx::ImageSkia::CreateFrom1xBitmap(scaled_bitmap))); 26 } 27 28 SkBitmap 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 37 scoped_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 62 void 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 83 void 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