mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Add a rowBytes parameter to decodeImageFromPixels (#5573)
See https://github.com/flutter/flutter/issues/9184
This commit is contained in:
parent
349d9d9085
commit
74ea64e912
@ -1381,10 +1381,13 @@ enum PixelFormat {
|
||||
}
|
||||
|
||||
class _ImageInfo {
|
||||
_ImageInfo(this.width, this.height, this.format);
|
||||
_ImageInfo(this.width, this.height, this.format, this.rowBytes) {
|
||||
rowBytes ??= width * 4;
|
||||
}
|
||||
int width;
|
||||
int height;
|
||||
int format;
|
||||
int rowBytes;
|
||||
}
|
||||
|
||||
/// Opaque handle to raw decoded image data (pixels).
|
||||
@ -1529,14 +1532,19 @@ Future<Null> _decodeImageFromListAsync(Uint8List list,
|
||||
/// Convert an array of pixel values into an [Image] object.
|
||||
///
|
||||
/// [pixels] is the pixel data in the encoding described by [format].
|
||||
///
|
||||
/// [rowBytes] is the number of bytes consumed by each row of pixels in the
|
||||
/// data buffer. If unspecified, it defaults to [width] multipled by the
|
||||
/// number of bytes per pixel in the provided [format].
|
||||
void decodeImageFromPixels(
|
||||
Uint8List pixels,
|
||||
int width,
|
||||
int height,
|
||||
PixelFormat format,
|
||||
ImageDecoderCallback callback
|
||||
ImageDecoderCallback callback,
|
||||
{int rowBytes}
|
||||
) {
|
||||
final _ImageInfo imageInfo = new _ImageInfo(width, height, format.index);
|
||||
final _ImageInfo imageInfo = new _ImageInfo(width, height, format.index, rowBytes);
|
||||
final Future<Codec> codecFuture = _futurize(
|
||||
(_Callback<Codec> callback) => _instantiateImageCodec(pixels, callback, imageInfo)
|
||||
);
|
||||
|
||||
@ -38,6 +38,11 @@ enum PixelFormat {
|
||||
kBGRA8888,
|
||||
};
|
||||
|
||||
struct ImageInfo {
|
||||
SkImageInfo sk_info;
|
||||
size_t row_bytes;
|
||||
};
|
||||
|
||||
static void InvokeCodecCallback(fxl::RefPtr<Codec> codec,
|
||||
std::unique_ptr<DartPersistentValue> callback,
|
||||
size_t trace_id) {
|
||||
@ -113,7 +118,7 @@ fxl::RefPtr<Codec> InitCodec(fml::WeakPtr<GrContext> context,
|
||||
fxl::RefPtr<Codec> InitCodecUncompressed(
|
||||
fml::WeakPtr<GrContext> context,
|
||||
sk_sp<SkData> buffer,
|
||||
SkImageInfo image_info,
|
||||
ImageInfo image_info,
|
||||
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
|
||||
size_t trace_id) {
|
||||
TRACE_FLOW_STEP("flutter", kInitCodecTraceTag, trace_id);
|
||||
@ -126,12 +131,12 @@ fxl::RefPtr<Codec> InitCodecUncompressed(
|
||||
|
||||
sk_sp<SkImage> skImage;
|
||||
if (context) {
|
||||
SkPixmap pixmap(image_info, buffer->data(), image_info.minRowBytes());
|
||||
SkPixmap pixmap(image_info.sk_info, buffer->data(), image_info.row_bytes);
|
||||
skImage = SkImage::MakeCrossContextFromPixmap(context.get(), pixmap, false,
|
||||
nullptr, true);
|
||||
} else {
|
||||
skImage = SkImage::MakeRasterData(image_info, std::move(buffer),
|
||||
image_info.minRowBytes());
|
||||
skImage = SkImage::MakeRasterData(image_info.sk_info, std::move(buffer),
|
||||
image_info.row_bytes);
|
||||
}
|
||||
|
||||
auto image = CanvasImage::Create();
|
||||
@ -146,7 +151,7 @@ void InitCodecAndInvokeCodecCallback(
|
||||
fxl::RefPtr<flow::SkiaUnrefQueue> unref_queue,
|
||||
std::unique_ptr<DartPersistentValue> callback,
|
||||
sk_sp<SkData> buffer,
|
||||
std::unique_ptr<SkImageInfo> image_info,
|
||||
std::unique_ptr<ImageInfo> image_info,
|
||||
size_t trace_id) {
|
||||
fxl::RefPtr<Codec> codec;
|
||||
if (image_info) {
|
||||
@ -165,7 +170,7 @@ void InitCodecAndInvokeCodecCallback(
|
||||
|
||||
bool ConvertImageInfo(Dart_Handle image_info_handle,
|
||||
Dart_NativeArguments args,
|
||||
SkImageInfo* image_info) {
|
||||
ImageInfo* image_info) {
|
||||
Dart_Handle width_handle = Dart_GetField(image_info_handle, ToDart("width"));
|
||||
if (!Dart_IsInteger(width_handle)) {
|
||||
Dart_SetReturnValue(args, ToDart("ImageInfo.width must be an integer"));
|
||||
@ -183,6 +188,12 @@ bool ConvertImageInfo(Dart_Handle image_info_handle,
|
||||
Dart_SetReturnValue(args, ToDart("ImageInfo.format must be an integer"));
|
||||
return false;
|
||||
}
|
||||
Dart_Handle row_bytes_handle =
|
||||
Dart_GetField(image_info_handle, ToDart("rowBytes"));
|
||||
if (!Dart_IsInteger(row_bytes_handle)) {
|
||||
Dart_SetReturnValue(args, ToDart("ImageInfo.rowBytes must be an integer"));
|
||||
return false;
|
||||
}
|
||||
|
||||
PixelFormat pixel_format = static_cast<PixelFormat>(
|
||||
tonic::DartConverter<int>::FromDart(format_handle));
|
||||
@ -200,10 +211,26 @@ bool ConvertImageInfo(Dart_Handle image_info_handle,
|
||||
return false;
|
||||
}
|
||||
|
||||
*image_info =
|
||||
SkImageInfo::Make(tonic::DartConverter<int>::FromDart(width_handle),
|
||||
tonic::DartConverter<int>::FromDart(height_handle),
|
||||
color_type, kPremul_SkAlphaType);
|
||||
int width = tonic::DartConverter<int>::FromDart(width_handle);
|
||||
if (width <= 0) {
|
||||
Dart_SetReturnValue(args, ToDart("width must be greater than zero"));
|
||||
return false;
|
||||
}
|
||||
int height = tonic::DartConverter<int>::FromDart(height_handle);
|
||||
if (height <= 0) {
|
||||
Dart_SetReturnValue(args, ToDart("height must be greater than zero"));
|
||||
return false;
|
||||
}
|
||||
image_info->sk_info =
|
||||
SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType);
|
||||
image_info->row_bytes =
|
||||
tonic::DartConverter<size_t>::FromDart(row_bytes_handle);
|
||||
|
||||
if (image_info->row_bytes < image_info->sk_info.minRowBytes()) {
|
||||
Dart_SetReturnValue(
|
||||
args, ToDart("rowBytes does not match the width of the image"));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -221,9 +248,9 @@ void InstantiateImageCodec(Dart_NativeArguments args) {
|
||||
}
|
||||
|
||||
Dart_Handle image_info_handle = Dart_GetNativeArgument(args, 2);
|
||||
std::unique_ptr<SkImageInfo> image_info;
|
||||
std::unique_ptr<ImageInfo> image_info;
|
||||
if (!Dart_IsNull(image_info_handle)) {
|
||||
image_info = std::make_unique<SkImageInfo>();
|
||||
image_info = std::make_unique<ImageInfo>();
|
||||
if (!ConvertImageInfo(image_info_handle, args, image_info.get())) {
|
||||
TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
|
||||
return;
|
||||
@ -240,7 +267,7 @@ void InstantiateImageCodec(Dart_NativeArguments args) {
|
||||
}
|
||||
|
||||
if (image_info) {
|
||||
int expected_size = image_info->minRowBytes() * image_info->height();
|
||||
int expected_size = image_info->row_bytes * image_info->sk_info.height();
|
||||
if (list.num_elements() < expected_size) {
|
||||
TRACE_FLOW_END("flutter", kInitCodecTraceTag, trace_id);
|
||||
list.Release();
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user