99 lines
3.8 KiB
C++
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
|