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();
}