如何将Flutter CameraImage转换为具有适当颜色和旋转的png或jpg?

lsmd5eda  于 2023-03-24  发布在  Flutter
关注(0)|答案(1)|浏览(250)

我正在使用camera flutter lib和控制器的startImageStream方法,每X毫秒我得到一个CameraImage输入,并希望将其保存为jpg/png文件
我正在使用一些代码在网上找到,但它有2个问题
1.它是灰度的,没有任何颜色
1.逆时针旋转90度
我现在使用的代码是

import 'package:camera/camera.dart';
import 'package:image/image.dart' as imglib;

Future<List<int>> convertImageToPng(CameraImage image) async {
  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 = imglib.PngEncoder();

  // Convert to png
  List<int> png = pngEncoder.encodeImage(img!);
  return png;
}

// 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 (compression: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;
}

方法convertImageToPng
我需要一个跨平台的ios+android的方法来转换CameraImage到jpg/png与适当的颜色和不旋转。

_controller?.startImageStream(
      (image) {
        final asPng = await convertImageToPng(image);
        // todo then I save this on disk or uploa
      },
    );

任何帮助都将不胜感激。

j5fpnvbx

j5fpnvbx1#

要捕获和保存图像,您可以使用以下方法。

import 'package:camera/camera.dart';
import 'package:image/image.dart' as imglib;

然后用你的方法:

_controller?.startImageStream((CameraImage image){
  Uint8List imageBytes = image.planes[0].bytes;
  //convert bytedata to image
  imglib.Image bitmap = imglib.decodeImage(imageBytes.toList());

  //then save on your directories use path_provider package to get all directories you are able to save in a device
  File("pathToSave").writeAsBytesSync(imglib.encodeJpg(bitmap));

  // or as png
  File("pathToSave").writeAsBytesSync(imglib.encodePng(bitmap));
});

或者作为替代方案:

// get picture as cross platform file as an alternative more easy (without passin by _controller.startImageStream)
XFile xfile = await _controller?.takePicture();

// get bytedata of it
Uint8List imageBytes = await xfile.readAsBytes();

//convert bytedata to image
imglib.Image bitmap = imglib.decodeImage(imageBytes.toList());

//then save on your directories use path_provider package to get all directories you are able to save in a device
File("pathToSave").writeAsBytesSync(imglib.encodeJpg(bitmap));

// or as png
File("pathToSave").writeAsBytesSync(imglib.encodePng(bitmap));

要向右旋转,你可以使用这个,传递bytedata的As UintList:

void saveImageFromUint8List(Uint8List data, int width, int height, String pathToSave) async {
  
    try {
      // Here you can use read_exif package
      final Map<String, IfdTag> exifData = await readExifFromBytes(data.toList());
      imglib.Image  source = imglib.decodeImage(data);
      if (source != null) {
        if (exifData.length > 0) {
          final IfdTag? imgOrientation = exifData['Image Orientation'];
          if (imgOrientation != null) {
            int rotation = 0;
            switch (imgOrientation.values.firstAsInt()) {
              case 6: // Make constants for it read about EXIF metadata
                rotation = 90;
                break;
              case 3: // Make constants for it read about EXIF metadata
                rotation = 180;
                break;
              case 8: // Make constants for it read about EXIF metadata
                rotation = -90;
                break;
            }
            if (rotation != 0) source = imglib.copyRotate(source, rotation); //or specify this parameter for newest version of  , angle: rotation);
          }
        }
        if (source.width != width || source.height != height) {
          File("pathToSave").writeAsBytesSync(imglib.encodeJpg(source));
        }
      }
    } catch (e) {
      // log(e.toString());
    }

  }

要通过传递原始图像来获得旋转图像,您可以用途:

Future<imglib.Image> getRotatedByTheRightSide(imglib.Image image) async {
    imglib.Image result = image;
    try {
     
      if (image != null) {
        // Here you can use read_exif package
        final Map<String, IfdTag> exifData = await readExifFromBytes(image.getBytes());
        
        if (exifData.length > 0) {
          final IfdTag? imgOrientation = exifData['Image Orientation'];
          if (imgOrientation != null) {
            int rotation = 0;
            switch (imgOrientation.values.firstAsInt()) {
              case 6: // Make constants for it read about EXIF metadata
                rotation = 90;
                break;
              case 3: // Make constants for it read about EXIF metadata
                rotation = 180;
                break;
              case 8: // Make constants for it read about EXIF metadata
                rotation = -90;
                break;
            }
            if (rotation != 0) result = imglib.copyRotate(image, angle: rotation);
          }
        }
      }
    
    } catch (e) {
      // log(e.toString());
    }
    
    return result;
  }

相关问题