absl::Status ConvertFromRgba()

in tensorflow_lite_support/cc/task/vision/utils/libyuv_frame_buffer_utils.cc [561:661]


absl::Status ConvertFromRgba(const FrameBuffer& buffer,
                             FrameBuffer* output_buffer) {
  switch (output_buffer->format()) {
    case FrameBuffer::Format::kGRAY: {
      // libyuv does not support convert kRGBA (ABGR) foramat. In this method,
      // the implementation converts kRGBA format to ARGB and use ARGB buffer
      // for conversion.
      // TODO(b/141181395): Use libyuv::ABGRToJ400 when it is ready.

      // Convert kRGBA to ARGB
      int argb_buffer_size = GetFrameBufferByteSize(buffer.dimension(),
                                                    FrameBuffer::Format::kRGBA);
      auto argb_buffer = absl::make_unique<uint8[]>(argb_buffer_size);
      const int argb_row_bytes = buffer.dimension().width * kRgbaPixelBytes;
      RETURN_IF_ERROR(
          ConvertRgbaToArgb(buffer, argb_buffer.get(), argb_row_bytes));

      // Convert ARGB to kGRAY
      int ret = libyuv::ARGBToJ400(
          argb_buffer.get(), argb_row_bytes,
          const_cast<uint8*>(output_buffer->plane(0).buffer),
          output_buffer->plane(0).stride.row_stride_bytes,
          buffer.dimension().width, buffer.dimension().height);
      if (ret != 0) {
        return CreateStatusWithPayload(
            StatusCode::kUnknown, "Libyuv ARGBToJ400 operation failed.",
            TfLiteSupportStatus::kImageProcessingBackendError);
      }
      break;
    }
    case FrameBuffer::Format::kNV12: {
      ASSIGN_OR_RETURN(FrameBuffer::YuvData output_data,
                       FrameBuffer::GetYuvDataFromFrameBuffer(*output_buffer));
      int ret = libyuv::ABGRToNV12(
          buffer.plane(0).buffer, buffer.plane(0).stride.row_stride_bytes,
          const_cast<uint8*>(output_data.y_buffer), output_data.y_row_stride,
          const_cast<uint8*>(output_data.u_buffer), output_data.uv_row_stride,
          buffer.dimension().width, buffer.dimension().height);
      if (ret != 0) {
        return CreateStatusWithPayload(
            StatusCode::kUnknown, "Libyuv ABGRToNV12 operation failed.",
            TfLiteSupportStatus::kImageProcessingBackendError);
      }
      break;
    }
    case FrameBuffer::Format::kNV21: {
      ASSIGN_OR_RETURN(FrameBuffer::YuvData output_data,
                       FrameBuffer::GetYuvDataFromFrameBuffer(*output_buffer));
      int ret = libyuv::ABGRToNV21(
          buffer.plane(0).buffer, buffer.plane(0).stride.row_stride_bytes,
          const_cast<uint8*>(output_data.y_buffer), output_data.y_row_stride,
          const_cast<uint8*>(output_data.v_buffer), output_data.uv_row_stride,
          buffer.dimension().width, buffer.dimension().height);
      if (ret != 0) {
        return CreateStatusWithPayload(
            StatusCode::kUnknown, "Libyuv ABGRToNV21 operation failed.",
            TfLiteSupportStatus::kImageProcessingBackendError);
      }
      break;
    }
    case FrameBuffer::Format::kYV12:
    case FrameBuffer::Format::kYV21: {
      ASSIGN_OR_RETURN(FrameBuffer::YuvData output_data,
                       FrameBuffer::GetYuvDataFromFrameBuffer(*output_buffer));
      int ret = libyuv::ABGRToI420(
          buffer.plane(0).buffer, buffer.plane(0).stride.row_stride_bytes,
          const_cast<uint8*>(output_data.y_buffer), output_data.y_row_stride,
          const_cast<uint8*>(output_data.u_buffer), output_data.uv_row_stride,
          const_cast<uint8*>(output_data.v_buffer), output_data.uv_row_stride,
          buffer.dimension().width, buffer.dimension().height);
      if (ret != 0) {
        return CreateStatusWithPayload(
            StatusCode::kUnknown, "Libyuv ABGRToI420 operation failed.",
            TfLiteSupportStatus::kImageProcessingBackendError);
      }
      break;
    }
    case FrameBuffer::Format::kRGB: {
      // ARGB is BGRA in memory and RGB24 is BGR in memory. The removal of the
      // alpha channel will not impact the RGB ordering.
      int ret = libyuv::ARGBToRGB24(
          buffer.plane(0).buffer, buffer.plane(0).stride.row_stride_bytes,
          const_cast<uint8*>(output_buffer->plane(0).buffer),
          output_buffer->plane(0).stride.row_stride_bytes,
          buffer.dimension().width, buffer.dimension().height);
      if (ret != 0) {
        return CreateStatusWithPayload(
            StatusCode::kUnknown, "Libyuv ABGRToRGB24 operation failed.",
            TfLiteSupportStatus::kImageProcessingBackendError);
      }
      break;
    }
    default:
      return CreateStatusWithPayload(
          StatusCode::kInternal,
          absl::StrFormat("Convert Rgba to format %i is not supported.",
                          output_buffer->format()),
          TfLiteSupportStatus::kImageProcessingError);
  }
  return absl::OkStatus();
}