Home | History | Annotate | Download | only in snapshot
      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.get(),
     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.get(),
     98       FROM_HERE,
     99       base::Bind(EncodeBitmap, *result->TakeBitmap()),
    100       callback);
    101 }
    102 
    103 }  // namespace ui
    104