StreamProc.c
7.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
#include "stdio.h"
#include "./StreamProc.h"
#include "JZsdkLib.h"
// 将RGB888格式转换为YUV420P格式
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图片画框
* 暂时不加入宽度功能
*
* *************************/
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;
}