// pkg\\sky_engine\\lib\\ui\\painting.dart
ui.decodeImageFromPixels方法会调用ImmutableBuffer.fromUint8List(pixels)方法:

// pkg\\sky_engine\\lib\\ui\\painting.dart
class ImmutableBuffer extends NativeFieldWrapperClass1 {
	/// Creates a copy of the data from a [Uint8List] suitable for internal use
  /// in the engine.
  static Future<ImmutableBuffer> fromUint8List(Uint8List list) {
    final ImmutableBuffer instance = ImmutableBuffer._(list.length);
    return _futurize((_Callback<void> callback) {
      instance._init(list, callback);
    }).then((_) => instance);
  }
  void _init(Uint8List list, _Callback<void> callback) native 'ImmutableBuffer_init';
}

// flutter/engine/flutter/lib/ui/painting/immutable_buffer.cc
void ImmutableBuffer::RegisterNatives( tonic::DartLibraryNatives* natives) {
  natives->Register({{"ImmutableBuffer_init", ImmutableBuffer::init, 3, true},
                     FOR_EACH_BINDING(DART_REGISTER_NATIVE)});
}
 
void ImmutableBuffer::init(Dart_NativeArguments args) {
  Dart_Handle callback_handle = Dart_GetNativeArgument(args, 2);
  if (!Dart_IsClosure(callback_handle)) {
    Dart_SetReturnValue(args,  tonic::ToDart("Callback must be a function"));
    return;
  }
 
  Dart_Handle buffer_handle = Dart_GetNativeArgument(args, 0);
   tonic::Uint8List data =  tonic::Uint8List(Dart_GetNativeArgument(args, 1));
 
  auto sk_data = MakeSkDataWithCopy(data.data(), data.num_elements());
  data.Release();
  auto buffer = fml::MakeRefCounted<ImmutableBuffer>(sk_data);
  buffer->AssociateWithDartWrapper(buffer_handle);
   tonic::DartInvoke(callback_handle, {Dart_TypeVoid()});
}

// flutter/engine/flutter/lib/ui/painting/immutable_buffer.cc
sk_sp<SkData> ImmutableBuffer::MakeSkDataWithCopy(const void* data,
                                                  size_t length) {
  return SkData::MakeWithCopy(data, length);
}

// flutter/engine/third_party/skia/src/core/SkData.cpp
sk_sp<SkData> SkData::MakeWithCopy(const void* src, size_t length) {
    SkASSERT(src);
    return PrivateNewWithCopy(src, length);
}

sk_sp<SkData> SkData::PrivateNewWithCopy(const void* srcOrNull, size_t length) {
    if (0 == length) {
        return SkData::MakeEmpty();
    }
 
    const size_t actualLength = length + sizeof(SkData);
    SkASSERT_RELEASE(length < actualLength);  // Check for overflow.
 
    void* storage = ::operator new (actualLength);
    sk_sp<SkData> data(new (storage) SkData(length));
    if (srcOrNull) {
        memcpy(data->writable_data(), srcOrNull, length);
    }
    return data;
}