CommonLibraries/src/yolo_cpu_image_utils.h

99 lines
3.8 KiB
C++

#pragma once
#include "yolo_runtime_types.h"
#include <algorithm>
#include <climits>
#include <cstddef>
namespace yolo_cpu_image {
inline int packed_row_bytes(const yolo_image_view_v1_t& image) {
if (image.width <= 0) return 0;
switch (image.pixel_format) {
case YOLO_PIXEL_FORMAT_GRAY8:
case YOLO_PIXEL_FORMAT_NV12:
case YOLO_PIXEL_FORMAT_NV21:
return image.width;
case YOLO_PIXEL_FORMAT_RGB888:
case YOLO_PIXEL_FORMAT_BGR888:
return image.width <= INT_MAX / 3 ? image.width * 3 : 0;
case YOLO_PIXEL_FORMAT_RGBA8888:
case YOLO_PIXEL_FORMAT_BGRA8888:
return image.width <= INT_MAX / 4 ? image.width * 4 : 0;
default:
return 0;
}
}
inline bool is_yuv420sp(yolo_pixel_format_t format) {
return format == YOLO_PIXEL_FORMAT_NV12 || format == YOLO_PIXEL_FORMAT_NV21;
}
inline bool valid(const yolo_image_view_v1_t* image) {
if (!image || image->struct_size < sizeof(yolo_image_view_v1_t) ||
image->version != YOLO_IMAGE_VIEW_ABI_VERSION || !image->data ||
image->width <= 0 || image->height <= 0) return false;
const int packed = packed_row_bytes(*image);
if (packed <= 0) return false;
const int stride = image->row_stride_bytes > 0 ? image->row_stride_bytes : packed;
if (stride < packed) return false;
if (is_yuv420sp(image->pixel_format) && ((image->width & 1) != 0 || (image->height & 1) != 0)) return false;
return true;
}
inline float clamp_byte(int value) {
return static_cast<float>(std::clamp(value, 0, 255));
}
inline void pixel_rgb(const yolo_image_view_v1_t& image, int x, int y, float& red, float& green, float& blue) {
const int packed = packed_row_bytes(image);
const int stride = image.row_stride_bytes > 0 ? image.row_stride_bytes : packed;
const unsigned char* row = image.data + static_cast<size_t>(y) * stride;
switch (image.pixel_format) {
case YOLO_PIXEL_FORMAT_GRAY8:
red = green = blue = row[x];
return;
case YOLO_PIXEL_FORMAT_RGB888: {
const unsigned char* pixel = row + static_cast<size_t>(x) * 3;
red = pixel[0]; green = pixel[1]; blue = pixel[2];
return;
}
case YOLO_PIXEL_FORMAT_BGR888: {
const unsigned char* pixel = row + static_cast<size_t>(x) * 3;
blue = pixel[0]; green = pixel[1]; red = pixel[2];
return;
}
case YOLO_PIXEL_FORMAT_RGBA8888: {
const unsigned char* pixel = row + static_cast<size_t>(x) * 4;
red = pixel[0]; green = pixel[1]; blue = pixel[2];
return;
}
case YOLO_PIXEL_FORMAT_BGRA8888: {
const unsigned char* pixel = row + static_cast<size_t>(x) * 4;
blue = pixel[0]; green = pixel[1]; red = pixel[2];
return;
}
case YOLO_PIXEL_FORMAT_NV12:
case YOLO_PIXEL_FORMAT_NV21: {
const int y_value = row[x];
const unsigned char* chroma = image.data + static_cast<size_t>(stride) * image.height +
static_cast<size_t>(y / 2) * stride + static_cast<size_t>(x / 2) * 2;
const int u_value = image.pixel_format == YOLO_PIXEL_FORMAT_NV12 ? chroma[0] : chroma[1];
const int v_value = image.pixel_format == YOLO_PIXEL_FORMAT_NV12 ? chroma[1] : chroma[0];
const int c = std::max(0, y_value - 16);
const int d = u_value - 128;
const int e = v_value - 128;
red = clamp_byte((298 * c + 409 * e + 128) >> 8);
green = clamp_byte((298 * c - 100 * d - 208 * e + 128) >> 8);
blue = clamp_byte((298 * c + 516 * d + 128) >> 8);
return;
}
default:
red = green = blue = 0.0f;
return;
}
}
} // namespace yolo_cpu_image