YUV分割原理是对Y、U、V三个分量分别处理。以下使用I420做例子列举出左右、上下、切块三种方式,原理都一样。
不画图直接上代码。
左右切割:
void CutLR(const char* src1, int w, int h)
{
int w1 = w / 2, w2 = w - w1;
int h1 = h, h2 = h;
char* cut_L = new char[w1 * h1 * 3 / 2]; // Left planer
char* cut_R = new char[w2 * h2 * 3 / 2]; // Right planer
char* src_y = (char*)src1;
char* src_u = src_y + w * h;
char* src_v = src_u + w / 2 * h / 2;
char* y1 = cut_L;
char* u1 = cut_L + w1 * h1;
char* v1 = u1 + w1 / 2 * h1 / 2;
char* y2 = cut_R;
char* u2 = cut_R + w2 * h2;
char* v2 = u2 + w2 / 2 * h2 / 2;
for (int i = 0; i < h; i++)
{
// Left y
memcpy(y1 + i*w1, src_y + i * w, w1);
// Right y
memcpy(y2 + i*w2, src_y + i*w + w1, w2);
}
for (int i = 0; i < h / 2; i++)
{
// Left uv
memcpy(u1 + i*w1 / 2, src_u + i*w / 2, w1 / 2);
memcpy(v1 + i*w1 / 2, src_v + i*w / 2, w1 / 2);
// Right uv
memcpy(u2 + i*w1 / 2, src_u + i*w / 2 + w1/2, w1 / 2);
memcpy(v2 + i*w1 / 2, src_v + i*w / 2 + w1/2, w1 / 2);
}
}
上下切割:
void CutUD(const char* src1, int w, int h)
{
int w1 = w, w2 = w;
int h1 = h / 2, h2 = h - h1;
char* cut_U = new char[w1 * h1 * 3 / 2]; // Up planer
char* cut_D = new char[w2 * h2 * 3 / 2]; // Down planer
char* src_y = (char*)src1;
char* src_u = src_y + w * h;
char* src_v = src_u + w / 2 * h / 2;
char* y1 = cut_U;
char* u1 = cut_U + w1 * h1;
char* v1 = u1 + w1 / 2 * h1 / 2;
char* y2 = cut_D;
char* u2 = cut_D + w2 * h2;
char* v2 = u2 + w2 / 2 * h2 / 2;
// Up y
for (int i = 0; i < h1; i++)
{
memcpy(y1 + i*w1, src_y + i*w, w1);
}
// Up uv
for (int i = 0; i < h1 / 2; i++)
{
memcpy(u1 + i*w1 / 2, src_u + i * w / 2, w1 / 2);
memcpy(v1 + i*w1 / 2, src_v + i * w / 2, w1 / 2);
}
// Down y
for (int i = 0; i < h2; i++)
{
memcpy(y2 + i*w2, src_y + (i + h1)*w, w2);
}
// Down uv
for (int i = 0; i < h2 / 2; i++)
{
memcpy(u2 + i*w1 / 2, src_u + (i+h1/2) * w / 2, w1 / 2);
memcpy(v2 + i*w1 / 2, src_v + (i+h1/2) * w / 2, w1 / 2);
}
}
切割块:
/*
* src1: source i420
* w: source width
* h: source height
* x,y: cut postion
* dw: destination width
* dh: destination height
*/
void CutBlock(const char* src1, int w, int h, int x, int y, int dw, int dh)
{
if (x + dw > w || y + dh > h) return;
char* dst = new char[dw*dh * 3 / 2]; // dst YUV
char* dst_y = dst;
char* dst_u = dst + dw * dh;
char* dst_v = dst_u + dw / 2 * dh / 2;
char* src_y = (char*)src1;
char* src_u = src_y + w * h;
char* src_v = src_u + w / 2 * h / 2;
for (int i = 0; i < dh; i++)
{
memcpy(dst_y + i * dw, src_y + (i + y) * w + x, dw);
}
for (int i = 0; i < dh / 2; i++)
{
memcpy(dst_u + i * dw / 2, src_u + (i + y / 2) * w / 2 + x/2, dw / 2);
memcpy(dst_v + i * dw / 2, src_v + (i + y / 2) * w / 2 + x/2, dw / 2);
}
}