如何使用 dart 将 Uint8list 转换为 List<int>?

Posted

技术标签:

【中文标题】如何使用 dart 将 Uint8list 转换为 List<int>?【英文标题】:How to convert Uint8list to List<int> with dart? 【发布时间】:2020-03-16 03:41:39 【问题描述】:

我用 Flutter 开发了一个移动应用程序。我做对象检测使用“controller.startImageStream”这个方法返回CameraImage,我使用对象检测。我想保存这个图像文件。我试图将此文件转换为 List 和 jpg 文件进行保存。但 uint8list 无法转换为 List。这种结构是真的吗?如果您知道我的问题的不同解决方案,请分享给我。

这是我的视频流方法;

startVideoStreaming() 
    if (cameras == null || cameras.length < 1) 
      print('No camera is found');
     else 
      controller = new CameraController(
        cameras[0],
          ResolutionPreset.medium,
        );

        if(!_busy)
          controller.initialize().then((_) 

          print("model yükleme bitmiş stream dinleme başlıyor ");

          controller.startImageStream((CameraImage img)
                  print("img format: $img.format planes: $img.planes");
                  List<int> imageBytes = [];
                  img.planes.map((plane) 
                    imageBytes.addAll(plane.bytes.toList());
                  );
                  
                  // call save image file method
                    saveImageFile(imageBytes).then((res) => 
                      print("save image file successfull filepath: $res")
                    ).catchError((err) => 
                      print("error on save image file error: $err")
                    );
                  
                  if(!isDetecting)
                    isDetecting = true;
                    print("Tflite'a stream gönderildi");
                    Tflite.detectObjectOnFrame(
                        bytesList: img.planes.map((plane) 
                          return plane.bytes;
                        ).toList(),
                        model: "SSDMobileNet",
                        imageHeight: img.height,
                        imageWidth: img.width,
                        imageMean: 127.5,
                        imageStd: 127.5,
                        numResultsPerClass: 1,
                        threshold: 0.4,
                      ).then((recognitions) 
                        int endTime = new DateTime.now().millisecondsSinceEpoch;
                        setState(() 
                          _recognitions=recognitions;
                        );
                        print("Recognitions: $recognitions");
                        isDetecting = false;
                      );
                  
                );
          );
        
    
  

这是我的图片保存方法;

Future<String> saveImageFile(imageBytes) async 
    final Directory extDir = await getApplicationDocumentsDirectory();
    final String dirPath = '$extDir.path/Pictures/flutter_test';
    await Directory(dirPath).create(recursive: true);
    final String filePath = '$dirPath/$timestamp().jpg';

    if (controller.value.isTakingPicture) 
      // A capture is already pending, do nothing.
      return null;
    

    try 
      File file = new File(filePath);
      file.writeAsBytes(imageBytes);
      print("finish image saved $imageBytes");
     on CameraException catch (e) 
      _showCameraException(e);
      return null;
    
    return filePath;
  

【问题讨论】:

Uint8list 实现了List&lt;int&gt; - 换句话说:它是一个List&lt;int&gt; 如果我直接发送发送 CameraImage 类型,file.writeAsBytes() 方法返回此代码:发生异常。 _TypeError(类型“CameraImage”不是类型“List”的子类型) 如果我使用img.planes.map((plane) return plane.bytes; ).toList(); 这是retunr List 你知道这个文件类型像图片一样保存吗? 这并不容易。见:***.com/questions/54312915/… 【参考方案1】:

去做

var temp = new Uint8List(500);
var list  = new List.from(temp);

【讨论】:

【参考方案2】:

您可以使用以下代码sn -p将CameraImage YUV420或BGRA8888转换为图像

来自 gist 的代码:https://gist.github.com/Alby-o/fe87e35bc21d534c8220aed7df028e03

// imgLib -> Image package from https://pub.dartlang.org/packages/image
import 'package:image/image.dart' as imglib;
import 'package:camera/camera.dart';

Future<List<int>> convertImagetoPng(CameraImage image) async 
  try 
    imglib.Image img;
    if (image.format.group == ImageFormatGroup.yuv420) 
      img = _convertYUV420(image);
     else if (image.format.group == ImageFormatGroup.bgra8888) 
      img = _convertBGRA8888(image);
    

    imglib.PngEncoder pngEncoder = new imglib.PngEncoder();

    // Convert to png
    List<int> png = pngEncoder.encodeImage(img);
    return png;
   catch (e) 
    print(">>>>>>>>>>>> ERROR:" + e.toString());
  
  return null;


// CameraImage BGRA8888 -> PNG
// Color
imglib.Image _convertBGRA8888(CameraImage image) 
  return imglib.Image.fromBytes(
    image.width,
    image.height,
    image.planes[0].bytes,
    format: imglib.Format.bgra,
  );


// CameraImage YUV420_888 -> PNG -> Image (compresion:0, filter: none)
// Black
imglib.Image _convertYUV420(CameraImage image) 
  var img = imglib.Image(image.width, image.height); // Create Image buffer

  Plane plane = image.planes[0];
  const int shift = (0xFF << 24);

  // Fill image buffer with plane[0] from YUV420_888
  for (int x = 0; x < image.width; x++) 
    for (int planeOffset = 0;
        planeOffset < image.height * image.width;
        planeOffset += image.width) 
      final pixelColor = plane.bytes[planeOffset + x];
      // color: 0x FF  FF  FF  FF
      //           A   B   G   R
      // Calculate pixel color
      var newVal = shift | (pixelColor << 16) | (pixelColor << 8) | pixelColor;

      img.data[planeOffset + x] = newVal;
    
  

  return img;

【讨论】:

您好,有彩色打印的方法吗? 你的意思是int color吗? 对于方法 _convertYUV420 图像是黑色的。有没有办法让它们也有颜色? @stan ,你能检查一下这个github.com/flutter/flutter/issues/26348#issuecomment-624244895【参考方案3】:

Flutter 现在有了将List&lt;int&gt; 转换为Uint8List 的方法。您可以使用以下内容:

Uint8List.fromList(List<int> elements);

见https://api.flutter.dev/flutter/dart-typed_data/Uint8List/Uint8List.fromList.html

【讨论】:

相信作者问反了。【参考方案4】:

@hunhunghan 有没有办法让_convertYUV420(CameraImage image) 方法也有颜色?因为这些图像是黑色的,而来自_convertBGRA8888(CameraImage image) 的图像是彩色的。

【讨论】:

【参考方案5】:

你可以这样做

Uint8List 是 Dart 核心库之一 dart:typed_data 的一部分。要使用它,请添加以下导入:

import 'dart:typed_data';

void main() 
  final testData = List.filled(1000000, 1);
  final uint8List = Uint8List.fromList(testData);

  final sw1 = Stopwatch()..start();
  final result1 = Stream.value(
    List<int>.from(uint8List),
  );
  sw1.stop();
  print('case1: $sw1.elapsedMicroseconds µs');

  final sw2 = Stopwatch()..start();
  final result2 = Stream.value(
    uint8List.map((e) => [e]),
  );
  sw2.stop();
  print('case2: $sw2.elapsedMicroseconds µs');

  final sw3 = Stopwatch()..start();
  final result3 = Stream.fromIterable(
    uint8List.map((e) => [e]),
  );
  sw3.stop();
  print('case3: $sw3.elapsedMicroseconds µs');

【讨论】:

以上是关于如何使用 dart 将 Uint8list 转换为 List<int>?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Dart 中使用 json_annotation 将 Uint8List 序列化为 json?

如何将 List<Uint8list> 转换为 GIF?

将图像转换为 Uint8List 颤振

Flutter 将十六进制转换为 Uint8list

如何从网络图像中获取 Flutter Uint8List?

【Dart/Flutter】一些常用的基本数据格式转换