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 data type of pixel channel values. Format.uint8 is the most typical format for images, where each pixel value is an unsigned byte with values in the range 0, 255.

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. bytesOffset can be specified to start reading the bytes data starting from that value.

numChannels can be used to specify the number of pixel channels in the bytes data, defaulting to 3.

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.

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 = Uint8List.sublistView(fromBytes, 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;
    }
  }
}