kannaRotate method

KannaRotateResults kannaRotate({
  1. required Uint8List pixels,
  2. PixelChannel pixelChannel = PixelChannel.c3,
  3. required int width,
  4. required int height,
  5. KannaRotateDeviceOrientationType deviceOrientationType = KannaRotateDeviceOrientationType.portraitUp,
  6. int sensorOrientation = 90,
})

Rotate the pixel to match the orientation of the device.

pixels is Image pixel data. pixelChannel is the number of channels of the image. For example, PixelChannel.c3 for RGB or PixelChannel.c4 for RGBA. width and height specify the width and height of the Image. deviceOrientationType is the orientation of the device. sensorOrientation is the orientation of the sensor.

Returns KannaRotateResults with the rotated pixels data.

Implementation

KannaRotateResults kannaRotate({
  required Uint8List pixels,
  PixelChannel pixelChannel = PixelChannel.c3,
  required int width,
  required int height,
  KannaRotateDeviceOrientationType deviceOrientationType =
      KannaRotateDeviceOrientationType.portraitUp,
  int sensorOrientation = 90,
}) {
  assert(width > 0, 'width is too small');
  assert(height > 0, 'height is too small');
  assert(pixels.isNotEmpty, 'pixels is empty');
  assert(sensorOrientation >= 0, 'sensorOrientation is too small');
  assert(sensorOrientation <= 360, 'sensorOrientation is too big');
  assert(sensorOrientation % 90 == 0, 'Only 0, 90, 180 or 270');

  if (width <= 0 ||
      height <= 0 ||
      pixels.isEmpty ||
      sensorOrientation < 0 ||
      sensorOrientation > 360 ||
      sensorOrientation % 90 != 0) {
    return const KannaRotateResults();
  }

  var rotateType = KannaRotateType.deg0;

  ///
  /// I don't know why you only need iOS but it works.
  /// Maybe related issue https://github.com/flutter/flutter/issues/94045
  ///
  switch (deviceOrientationType) {
    case KannaRotateDeviceOrientationType.portraitUp:
      rotateType = KannaRotateType.fromDegree(
        Platform.isIOS
            ? (-90 + sensorOrientation) % 360
            : (0 + sensorOrientation) % 360,
      );
      break;
    case KannaRotateDeviceOrientationType.landscapeRight:
      rotateType = KannaRotateType.fromDegree(
        Platform.isIOS
            ? (-90 + sensorOrientation) % 360
            : (90 + sensorOrientation) % 360,
      );
      break;
    case KannaRotateDeviceOrientationType.portraitDown:
      rotateType = KannaRotateType.fromDegree(
        Platform.isIOS
            ? (-90 + sensorOrientation) % 360
            : (180 + sensorOrientation) % 360,
      );
      break;
    case KannaRotateDeviceOrientationType.landscapeLeft:
      rotateType = KannaRotateType.fromDegree(
        Platform.isIOS
            ? (-90 + sensorOrientation) % 360
            : (270 + sensorOrientation) % 360,
      );
      break;
  }

  if (rotateType == KannaRotateType.deg0) {
    return KannaRotateResults(
      pixels: pixels,
      width: width,
      height: height,
      pixelChannel: pixelChannel,
    );
  }

  final src = calloc.allocate<Uint8>(pixels.length);
  for (var i = 0; i < pixels.length; i++) {
    src[i] = pixels[i];
  }
  final srcw = width;
  final srch = height;

  final dst = calloc.allocate<Uint8>(pixels.length);
  var dstw = width;
  var dsth = height;

  switch (rotateType) {
    case KannaRotateType.deg0:
    case KannaRotateType.deg180:
      break;
    case KannaRotateType.deg90:
    case KannaRotateType.deg270:
      dstw = height;
      dsth = width;
      break;
  }

  final type = rotateType.type;

  _kannaRotateFunction(
    src,
    pixelChannel.channelNum,
    srcw,
    srch,
    dst,
    dstw,
    dsth,
    type,
  );

  final results = _copyUint8PointerToUint8List(dst, pixels.length);
  calloc
    ..free(src)
    ..free(dst);

  return KannaRotateResults(
    pixels: results,
    width: dstw,
    height: dsth,
    pixelChannel: pixelChannel,
  );
}