Browse Source

Lock pixels before calling `SkBitmap::getPixels` and copy bitmap row-wise in case (stride != width)

Ales Pergl 7 years ago
parent
commit
9f8f95f4c9
1 changed files with 19 additions and 17 deletions
  1. 19 17
      atom/browser/api/frame_subscriber.cc

+ 19 - 17
atom/browser/api/frame_subscriber.cc

@@ -14,18 +14,6 @@
 
 namespace atom {
 
-namespace {
-
-void CopyPixelsToBuffer(const SkBitmap& bitmap,
-                        const v8::Local<v8::Object>& buffer) {
-  size_t rgb_arr_size = bitmap.width() * bitmap.height() *
-      bitmap.bytesPerPixel();
-
-  memcpy(node::Buffer::Data(buffer), bitmap.getPixels(), rgb_arr_size);
-}
-
-}  // namespace
-
 namespace api {
 
 FrameSubscriber::FrameSubscriber(v8::Isolate* isolate,
@@ -90,18 +78,32 @@ void FrameSubscriber::OnFrameDelivered(const FrameCaptureCallback& callback,
   v8::Locker locker(isolate_);
   v8::HandleScope handle_scope(isolate_);
 
-  size_t rgb_arr_size = bitmap.width() * bitmap.height() *
-    bitmap.bytesPerPixel();
-  v8::MaybeLocal<v8::Object> buffer = node::Buffer::New(isolate_, rgb_arr_size);
+  size_t rgb_row_size = bitmap.width() * bitmap.bytesPerPixel();
+
+  v8::MaybeLocal<v8::Object> buffer =
+      node::Buffer::New(isolate_, rgb_row_size * bitmap.height());
+
   if (buffer.IsEmpty())
     return;
 
-  CopyPixelsToBuffer(bitmap, buffer.ToLocalChecked());
+  auto local_buffer = buffer.ToLocalChecked();
+
+  {
+    SkAutoLockPixels lock(bitmap);
+    auto source = static_cast<const unsigned char*>(bitmap.getPixels());
+    auto target = node::Buffer::Data(local_buffer);
+
+    for (int y = 0; y < bitmap.height(); ++y) {
+      memcpy(target, source, rgb_row_size);
+      source += bitmap.rowBytes();
+      target += rgb_row_size;
+    }
+  }
 
   v8::Local<v8::Value> damage =
       mate::Converter<gfx::Rect>::ToV8(isolate_, damage_rect);
 
-  callback_.Run(buffer.ToLocalChecked(), damage);
+  callback_.Run(local_buffer, damage);
 }
 
 }  // namespace api