#pragma once #include "yolo_runtime_types.h" #include #include #include 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(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(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(x) * 3; red = pixel[0]; green = pixel[1]; blue = pixel[2]; return; } case YOLO_PIXEL_FORMAT_BGR888: { const unsigned char* pixel = row + static_cast(x) * 3; blue = pixel[0]; green = pixel[1]; red = pixel[2]; return; } case YOLO_PIXEL_FORMAT_RGBA8888: { const unsigned char* pixel = row + static_cast(x) * 4; red = pixel[0]; green = pixel[1]; blue = pixel[2]; return; } case YOLO_PIXEL_FORMAT_BGRA8888: { const unsigned char* pixel = row + static_cast(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(stride) * image.height + static_cast(y / 2) * stride + static_cast(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