Image.fromBytes constructor

Image.fromBytes({
  1. required int width,
  2. required int height,
  3. required ByteBuffer bytes,
  4. int bytesOffset = 0,
  5. Format format = Format.uint8,
  6. int? numChannels,
  7. int? rowStride,
  8. bool withPalette = false,
  9. Format paletteFormat = Format.uint8,
  10. Palette? palette,
  11. ExifData? exif,
  12. IccProfile? iccp,
  13. ChannelOrder? order,
  14. Map<String, String>? textData,
  15. int loopCount = 0,
  16. FrameType frameType = FrameType.sequence,
  17. Color? backgroundColor,
  18. int frameDuration = 0,
  19. int frameIndex = 0,
})

Create an image from raw data in bytes.

format defines the order of color channels in bytes. An HTML canvas element stores colors in Format.rgba format; a Flutter Image object stores colors in Format.rgba format.

rowStride is the row stride, in bytes, of the source data bytes. This may be different than the rowStride of the Image, as some data sources align rows to different byte alignments and include padding.

order can be used if the source bytes has a different channel order than RGBA. ChannelOrder.bgra will rearrange the color channels from BGRA to what Image wants, RGBA.

If numChannels and order are not provided, a default of 3 for numChannels and ChannelOrder.rgba for order will be assumed.

For example, given an Html Canvas, you could create an image: var bytes = canvas.getContext('2d').getImageData(0, 0, canvas.width, canvas.height).data; var image = Image.fromBytes(width: canvas.width, height: canvas.height, bytes: canvasBytes, numChannels: 4);

Implementation

Image.fromBytes(
    {required int width,
    required int height,
    required ByteBuffer bytes,
    int bytesOffset = 0,
    Format format = Format.uint8,
    int? numChannels,
    int? rowStride,
    bool withPalette = false,
    Format paletteFormat = Format.uint8,
    Palette? palette,
    ExifData? exif,
    IccProfile? iccp,
    ChannelOrder? order,
    this.textData,
    this.loopCount = 0,
    this.frameType = FrameType.sequence,
    this.backgroundColor,
    this.frameDuration = 0,
    this.frameIndex = 0}) {
  frames.add(this);

  numChannels ??= order != null ? channelOrderLength[order] : 3;

  if (numChannels! < 0 || numChannels > 4) {
    throw ImageException('An Image can only have 1-4 channels.');
  }

  order ??= numChannels == 3
      ? ChannelOrder.rgb
      : numChannels == 4
          ? ChannelOrder.rgba
          : numChannels == 1
              ? ChannelOrder.red
              : ChannelOrder.grayAlpha;

  if (numChannels == 1) {
    // There is only one channel order
    order = ChannelOrder.red;
  } else if (numChannels == 2) {
    // There is only one channel order
    order = ChannelOrder.grayAlpha;
  } else if (numChannels == 3) {
    if (order != ChannelOrder.rgb && order != ChannelOrder.bgr) {
      // The user asked for a channel order that conflicts with the number
      // of channels.
      order = ChannelOrder.rgb;
    }
  } else if (numChannels == 4) {
    if (order != ChannelOrder.bgra &&
        order != ChannelOrder.rgba &&
        order != ChannelOrder.abgr &&
        order != ChannelOrder.argb) {
      // The user asked for a channel order that conflicts with the number
      // of channels.
      order = ChannelOrder.rgba;
    }
  }

  _initialize(width, height,
      format: format,
      numChannels: numChannels,
      withPalette: withPalette,
      paletteFormat: paletteFormat,
      palette: palette,
      exif: exif,
      iccp: iccp);

  if (data == null) {
    return;
  }

  final toBytes = data!.toUint8List();
  final fromBytes = Uint8List.view(bytes, bytesOffset);

  rowStride ??= getRowStride(width, numChannels, format);
  final dataStride = data!.rowStride;
  final stride = min(rowStride, dataStride);

  var dOff = 0;
  var bOff = 0;
  for (int y = 0; y < height; ++y, bOff += rowStride, dOff += dataStride) {
    final bRow = fromBytes.getRange(bOff, bOff + stride);
    toBytes.setRange(dOff, dOff + dataStride, bRow);
  }

  if (numChannels == 3 && order == ChannelOrder.bgr) {
    for (final p in this) {
      final r = p.r;
      p
        ..r = p.b
        ..b = r;
    }
  } else if (numChannels == 4 && order == ChannelOrder.abgr) {
    for (final p in this) {
      final r = p.r;
      final g = p.g;
      final b = p.b;
      final a = p.a;
      p
        ..r = a
        ..g = b
        ..b = g
        ..a = r;
    }
  } else if (numChannels == 4 && order == ChannelOrder.argb) {
    for (final p in this) {
      final r = p.r;
      final g = p.g;
      final b = p.b;
      final a = p.a;
      p
        ..r = a
        ..g = r
        ..b = g
        ..a = b;
    }
  } else if (numChannels == 4 && order == ChannelOrder.bgra) {
    for (final p in this) {
      final r = p.r;
      final g = p.g;
      final b = p.b;
      final a = p.a;
      p
        ..r = b
        ..g = g
        ..b = r
        ..a = a;
    }
  }
}