MultProc.c 9.1 KB
/***************
 * 
 *  多媒体处理器
 *  Multimedia Processor
 * 
 * ******************/
#include "stdio.h"

#include "./MultProc.h"

#include "JZsdkLib.h"

// 将RGB888格式转换为YUV420P格(I420)
T_JZsdkReturnCode Stream_rgb888_to_yuv420p(U8_t *rgb_data, int width, int height, U8_t *yuv_data)
{  
    // YUV420P格式的大小:Y平面后面跟着U和V平面,它们的高度和宽度都是原图像的一半  
    int y_size = width * height;  
    int u_size = (width / 2) * (height / 2) ; // U和V平面交错存储  
  
    // YUV420P的各个平面  
    U8_t *y_plane = yuv_data;  
    U8_t *u_plane = yuv_data + y_size;  
    U8_t *v_plane = u_plane + u_size;  
  
    // RGB888到YUV420P的转换  
    for (int j = 0; j < height; j++) {  
        for (int i = 0; i < width; i++) {  
            // 计算Y分量的索引  
            int y_idx = j * width + i;  
            // 计算UV分量的索引(每个第二个像素存储一次)  
            int uv_idx = (j / 2) * (width / 2) + (i / 2);  
  
            // 提取RGB分量  
            U8_t r = rgb_data[y_idx * 3];  
            U8_t g = rgb_data[y_idx * 3 + 1];  
            U8_t b = rgb_data[y_idx * 3 + 2];  
  
            // 将RGB转换为YUV  
            int y = ((66 * r + 129 * g + 25 * b + 128) >> 8);  
            int u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;  
            int v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;  
  
            // 存储Y分量  
            y_plane[y_idx] = (U8_t)y;  
  
            // 仅当为每第二个像素时存储U和V分量  
            if ((i & 1) == 0 && (j & 1) == 0) 
            {  
                u_plane[uv_idx] = (U8_t)u;  
                v_plane[uv_idx] = (U8_t)v;  
            }  
        }  
    } 

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}  

//rgb888 转yuv420sp MPP_FMT_YUV420SP        = (MPP_FRAME_FMT_YUV + 0),  /* YYYY... UV... (NV12)     */
T_JZsdkReturnCode Stream_rgb888_to_yuv420sp(U8_t *rgb_data, int width, int height, U8_t *yuv_data)
{
    // YUV420SP(NV12)格式的大小:Y平面后面跟着一个交织的UV平面
    int y_size = width * height;
    int uv_size = (width / 2) * (height / 2) * 2; // UV平面交织存储,所以大小是U或V平面的两倍
 
    // YUV420SP的各个平面
    U8_t *y_plane = yuv_data;
    U8_t *uv_plane = yuv_data + y_size;
 

 
    // RGB888到YUV420SP的转换
    for (int j = 0; j < height; j++) {
        for (int i = 0; i < width; i++) {
            // 计算Y分量的索引
            int y_idx = j * width + i;

            // 计算UV分量的索引(每个第二个像素存储一次)  
            int uv_idx = (j / 2) * (width / 2) + (i / 2); 
 
            // 提取RGB分量
            U8_t r = rgb_data[y_idx * 3];
            U8_t g = rgb_data[y_idx * 3 + 1];
            U8_t b = rgb_data[y_idx * 3 + 2];
 
            // 将RGB转换为YUV
            int y = ((66 * r + 129 * g + 25 * b + 128) >> 8);
            int u = ((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
            int v = ((112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
 
            // 存储Y分量
            y_plane[y_idx] = (U8_t)y;
 
            // 仅当为每第二个像素时存储U和V分量 
            if ((i & 1) == 0 && (j & 1) == 0) 
            {
                // 存储U分量
                uv_plane[uv_idx * 2] = (U8_t)u;
                // 存储V分量
                uv_plane[uv_idx * 2 + 1] = (U8_t)v;
            }

        }
    }
 
    // 注意:如果图像的宽度或高度不是偶数,上面的代码可能无法正确处理最后一行或一列。
    // 在实际应用中,通常需要确保图像的尺寸是2的倍数,或者添加适当的边界处理代码。
 
    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}


/*************************
 * 
 * /rgb888图片画框
 *  暂时不加入宽度功能
 * 
 * *************************/
T_JZsdkReturnCode Stream_rgb888_WriteRectangle(U8_t *rgb_data, int width, int height, int Point1_X, int Point1_Y, int Point2_X, int Point2_Y, int R_Color,int G_Color, int B_Color, int DrawWidth)
{
    //涂色

    //找到矩形的左上角
    int LeftTop_X = JZ_MATH_MIN(Point1_X, Point2_X);
    int LeftTop_Y = JZ_MATH_MIN(Point1_Y, Point2_Y);
    //找到矩形的左下角
    int LeftDown_X = JZ_MATH_MAX(Point1_X, Point2_X);
    int LeftDown_Y = JZ_MATH_MAX(Point1_Y, Point2_Y);

    //找到矩形的右上角
    int RightTop_X = JZ_MATH_MIN(Point1_X, Point2_X);
    int RightTop_Y = JZ_MATH_MIN(Point1_Y, Point2_Y);
    //找到矩形的右下角
    int RightDown_X = JZ_MATH_MAX(Point1_X, Point2_X);
    int RightDown_Y = JZ_MATH_MAX(Point1_Y, Point2_Y);

    // 确保坐标在有效范围内  
    if (LeftTop_X < 0) LeftTop_X = 0;  
    if (LeftTop_Y < 0) LeftTop_Y = 0;  
    if (RightDown_X >= width) RightDown_X = width - 1;  
    if (RightDown_Y >= height) RightDown_Y = height - 1;  
  
    // 计算起始位置(以字节为单位,每个像素3字节)  
    //int start_base = LeftTop_Y * width * 3 + LeftTop_X * 3;  
  
    // // 填充矩形区域  
    // for (int y = LeftTop_Y; y <= RightDown_Y; y++) {  
    //     for (int x = LeftTop_X; x <= RightDown_X; x++) {  
    //         int offset = (y * width + x) * 3;  
    //         rgb_data[offset] = R_Color; // R  
    //         rgb_data[offset + 1] = G_Color; // G  
    //         rgb_data[offset + 2] = B_Color; // B  
    //     }  
    // }  

    // 确保DrawWidth在有效范围内  
    if (DrawWidth < 1) DrawWidth = 1;  
    if (DrawWidth > (RightDown_X - LeftTop_X + 1) / 2) DrawWidth = (RightDown_X - LeftTop_X + 1) / 2; // 防止宽度过大导致超出矩形  
    if (DrawWidth > (RightDown_Y - LeftTop_Y + 1) / 2) DrawWidth = (RightDown_Y - LeftTop_Y + 1) / 2;  
  
    // 绘制矩形边框  
    // 上边  
    for (int x = LeftTop_X; x <= RightDown_X; x++) {  
        for (int dw = 0; dw < DrawWidth; dw++) {  
            int offset = ((LeftTop_Y - dw) * width + x) * 3;  
            if (offset >= 0 && offset < width * height * 3) { // 检查边界  
                rgb_data[offset] = R_Color;  
                rgb_data[offset + 1] = G_Color;  
                rgb_data[offset + 2] = B_Color;  
            }  
        }  
    }  
    // 下边  
    for (int x = LeftTop_X; x <= RightDown_X; x++) {  
        for (int dw = 0; dw < DrawWidth; dw++) {  
            int offset = ((RightDown_Y + dw) * width + x) * 3;  
            if (offset >= 0 && offset < width * height * 3) { // 检查边界  
                rgb_data[offset] = R_Color;  
                rgb_data[offset + 1] = G_Color;  
                rgb_data[offset + 2] = B_Color;  
            }  
        }  
    }  
    // 左边  
    for (int y = LeftTop_Y; y <= RightDown_Y; y++) {  
        for (int dw = 0; dw < DrawWidth; dw++) {  
            int offset = (y * width + (LeftTop_X - dw)) * 3;  
            if (offset >= 0 && offset < width * height * 3) { // 检查边界  
                rgb_data[offset] = R_Color;  
                rgb_data[offset + 1] = G_Color;  
                rgb_data[offset + 2] = B_Color;  
            }  
        }  
    }  
    // 右边  
    for (int y = LeftTop_Y; y <= RightDown_Y; y++) {  
        for (int dw = 0; dw < DrawWidth; dw++) {  
            int offset = (y * width + (RightDown_X + dw)) * 3;  
            if (offset >= 0 && offset < width * height * 3) { // 检查边界  
                rgb_data[offset] = R_Color;  
                rgb_data[offset + 1] = G_Color;
                rgb_data[offset + 2] = B_Color;  
            }  
        }  
    }  

    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}

/*************************
 * 
 *  rgb888 画十字
 * 
 * *************************/
T_JZsdkReturnCode Stream_rgb888_WriteCross(U8_t *rgb_data, int width, int height, int PointX, int PointY, int R_Color,int G_Color, int B_Color, int DrawWidth, int DrawHeight)
{
     // 确保DrawWidth和DrawHeight为奇数,且不小于1  
    if (DrawWidth % 2 == 0) DrawWidth--;  
    if (DrawHeight % 2 == 0) DrawHeight--;  
      
    // 排查是否有足够的位置画十字  
    if (PointX < DrawWidth / 2 || PointX >= (width - DrawWidth / 2) || PointY < DrawHeight / 2 || PointY >= (height - DrawHeight / 2))  
    {  
        return JZ_ERROR_SYSTEM_MODULE_CODE_FAILURE;  
    }  
      
    // 中心点  
    int base = (PointY * width + PointX) * 3;  
  
    // 绘制垂直线  
    for (int dy = -DrawWidth / 2; dy <= DrawWidth / 2; dy++)  
    {  
        // 确保不会超出图像范围  
        int y = PointY + dy;  
        if (y >= 0 && y < height)  
        {  
            int offset = y * width * 3;  
            rgb_data[offset + PointX * 3] = R_Color;  
            rgb_data[offset + PointX * 3 + 1] = G_Color;  
            rgb_data[offset + PointX * 3 + 2] = B_Color;  
        }  
    }  
  
    // 绘制水平线  
    for (int dx = -DrawHeight / 2; dx <= DrawHeight / 2; dx++)  
    {  
        // 确保不会超出图像范围  
        int x = PointX + dx;  
        if (x >= 0 && x < width)  
        {  
            int offset = base + dx * 3;  
            rgb_data[offset] = R_Color;  
            rgb_data[offset + 1] = G_Color;  
            rgb_data[offset + 2] = B_Color;  
        }  
    }  
      
    return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}