左下角裁剪
思路
用 左下角 1/2 hSrc * 1/2 wSrc 像素内容 替换 左上角内容
实现
//获得pCropFrame ... int wDst = pPicFrame->width * 2 / 4; int hDst = pPicFrame->height * 2 / 4; int wSrc = pPicFrame->width; int hSrc = pPicFrame->height; //AVFrame* pCropFrame = WXMediaUtilsAllocVideoFrame(AV_PIX_FMT_RGB32, wDst, hDst);//新的 //右上角 int lineSizeY = pPicFrame->linesize[0]; int lineSizeU = pPicFrame->linesize[1]; int lineSizeV = pPicFrame->linesize[2]; //crop Y for (size_t line = 0; line < hDst; line++) { //起始[0]+起始行hSrc/2*line +行中心开始lineSize/2 memcpy(pPicFrame->data[0] + line *lineSizeY, pPicFrame->data[0] + (hSrc / 2 + line) * lineSizeY, lineSizeY / 2); } //crop U for (size_t line = 0; line < hDst / 2; line++) { //起始[0]+起始行hDst/2*line +行中心开始lineSize/2 memcpy(pPicFrame->data[1] + line * lineSizeU, pPicFrame->data[1] + (hDst / 2 + line) * lineSizeU, lineSizeU / 2); } //crop V for (size_t line = 0; line < hDst / 2; line++) { memcpy(pPicFrame->data[2] + line * lineSizeV, pPicFrame->data[2] + (hDst / 2 + line) * lineSizeV, lineSizeV / 2); } pPicFrame->width = wDst; pPicFrame->height = hDst; ... //显示pCropFrame
右下角裁剪
思路
用 右下角 1/2 hSrc * 1/2 wSrc 像素内容 替换 左上角内容
实现
//获得pCropFrame ... int wDst = pCropFrame->width * 2 / 4; int hDst = pCropFrame->height * 2 / 4; int wSrc = pCropFrame->width; int hSrc = pCropFrame->height; //左上角 //pCropFrame->width = wDst; //pCropFrame->height = hDst; //右上角 int lineSizeY = pCropFrame->linesize[0]; int lineSizeU = pCropFrame->linesize[1]; int lineSizeV = pCropFrame->linesize[2]; //crop Y for (size_t line = 0; line < hDst; line++) { //起始[0]+起始行hSrc/2*line +行中心开始lineSize/2 memcpy(pCropFrame->data[0] + line *lineSizeY, pCropFrame->data[0] + (hSrc / 2 + line) * lineSizeY + lineSizeY / 2, lineSizeY / 2); } //crop U for (size_t line = 0; line < hDst/2; line++) { //起始[0]+起始行hDst/2*line +行中心开始lineSize/2 memcpy(pCropFrame->data[1] + line * lineSizeU, pCropFrame->data[1] + (hDst / 2 + line) * lineSizeU + lineSizeU / 2 , lineSizeU / 2); } //crop V for (size_t line = 0; line < hDst/2; line++) { memcpy(pCropFrame->data[2] + line * lineSizeV, pCropFrame->data[2] + (hDst / 2 + line) * lineSizeV + lineSizeV / 2, lineSizeV / 2); } pCropFrame->width = wDst; pCropFrame->height = hDst; ... //显示pCropFrame
中心裁剪
思路
用 中心 1/2 hSrc * 1/2 wSrc 像素内容 替换 左上角内容
实现
//获得pCropFrame ... int wDst = pPicFrame->width * 2 / 4; int hDst = pPicFrame->height * 2 / 4; int wSrc = pPicFrame->width; int hSrc = pPicFrame->height; //AVFrame* pCropFrame = WXMediaUtilsAllocVideoFrame(AV_PIX_FMT_RGB32, wDst, hDst);//新的 //右上角 int lineSizeY = pPicFrame->linesize[0]; int lineSizeU = pPicFrame->linesize[1]; int lineSizeV = pPicFrame->linesize[2]; //crop Y for (size_t line = 0; line < hDst; line++) { memcpy(pPicFrame->data[0] + line * lineSizeY, pPicFrame->data[0] + (hSrc / 4 + line) * lineSizeY + lineSizeY * 4 / 16, lineSizeY / 2); } //crop U for (size_t line = 0; line < hDst / 2; line++) { memcpy(pPicFrame->data[1] + line * lineSizeU, pPicFrame->data[1] + (hDst / 4 + line) * lineSizeU + lineSizeU * 4 / 16, lineSizeU / 2); } //crop V for (size_t line = 0; line < hDst / 2; line++) { memcpy(pPicFrame->data[2] + line * lineSizeV, pPicFrame->data[2] + (hDst / 4 + line) * lineSizeV + lineSizeV * 4 / 16, lineSizeV / 2); } pPicFrame->width = wDst; pPicFrame->height = hDst; ... //显示pCropFrame
任意区域裁剪
思路
确认裁剪区域起始坐标和尺寸
实现
AVFrame* pPicFrame = WXMediaUtilsFromPicture(m_pwszPicPath); //目标裁剪矩形 及其坐标 typedef struct Rect{ int x; int y; int width; int height; }Rect; Rect dstRect; //设定裁剪中心和尺寸 dstRect.x = pPicFrame->width * 4 / 16; dstRect.y = pPicFrame->height * 4 / 16; dstRect.width = pPicFrame->width * 4 / 16; dstRect.height = pPicFrame->height * 4 / 16; // wchar_t text[260] = {0}; wsprintf(text,L"rect (%d,%d) w:%d,h:%d", dstRect.x, dstRect.y, dstRect.width, dstRect.height); MessageBox(text, L"提示", 0); int maxHeight = pPicFrame->height; int maxWidth = pPicFrame->width; if (dstRect.x<0 || dstRect.x >maxWidth) { return; } if (dstRect.y<0 || dstRect.y >maxHeight) { return; } int wDst = dstRect.width; int hDst = dstRect.height; int wSrc = pPicFrame->width; int hSrc = pPicFrame->height; ... //创建pCropFrame 新尺寸 //AVFrame* pCropFrame = AllocFrame(AV_PIX_FMT_YUV420P, wDst, hDst);//新的 ... //右上角 int srcLineSizeY = pPicFrame->linesize[0]; int srcLineSizeU = pPicFrame->linesize[1]; int srcLineSizeV = pPicFrame->linesize[2]; int fromHeight = dstRect.y - dstRect.height / 2; int fromWidth = dstRect.x - dstRect.width / 2; if (fromHeight < 0) { fromHeight = dstRect.y; } if (fromHeight+dstRect.height > hSrc) { } if (fromWidth < 0) { fromWidth = dstRect.x; } if (fromHeight + dstRect.height > hSrc) { } //crop Y for (size_t line = 0; line < dstRect.height; line++) { void *dst = pCropFrame->data[0] + line * pCropFrame->linesize[0]; int offset = (fromHeight + line) * srcLineSizeY + fromWidth; void *from = pPicFrame->data[0] + offset; int size = srcLineSizeY * dstRect.width / pPicFrame->width; memcpy(dst,from, size); } //crop U for (size_t line = 0; line < dstRect.height / 2; line++) { memcpy(pCropFrame->data[1] + line * pCropFrame->linesize[1], pPicFrame->data[1] + (fromHeight / 2 + line) * srcLineSizeU + fromWidth/2, srcLineSizeY * dstRect.width / pPicFrame->width); } //crop V for (size_t line = 0; line < dstRect.height / 2; line++) { memcpy(pCropFrame->data[2] + line * pCropFrame->linesize[2], pPicFrame->data[2] + (fromHeight / 2 + line) * srcLineSizeV + fromWidth/2, srcLineSizeY * dstRect.width / pPicFrame->width); } pCropFrame->width = wDst; pCropFrame->height = hDst; AVFrame* pResizeFrame = pCropFrame; ... //display pResizeFrame ...
缩放
思路
思路比较简单
基于原画面数据的缩放
放大就是裁剪需要放大部分+Resize画面尺寸为原画面大小,连续放大就是每次将上次放大的Frame再作为下次放大的srcFrame 进行操作;
缩小就是将原画面放到新画面中心 四周填黑,宽高扩大。
实现
放大
... //s_pPicFrame为src AVFrame ... int wDst = s_pPicFrame->width * 2 / 4; int hDst = s_pPicFrame->height * 2 / 4; int wSrc = s_pPicFrame->width; int hSrc = s_pPicFrame->height; AVFrame* pCropFrame = AllocFrame(AV_PIX_FMT_YUV420P, wDst, hDst);//新的 //右上角 int lineSizeY = s_pPicFrame->linesize[0]; int lineSizeU = s_pPicFrame->linesize[1]; int lineSizeV = s_pPicFrame->linesize[2]; //crop Y for (size_t line = 0; line < hDst; line++) { memcpy(pCropFrame->data[0] + line * pCropFrame->linesize[0], s_pPicFrame->data[0] + (hSrc / 4 + line) * lineSizeY + lineSizeY * 4 / 16, lineSizeY / 2); } //crop U for (size_t line = 0; line < hDst / 2; line++) { memcpy(pCropFrame->data[1] + line * pCropFrame->linesize[1], s_pPicFrame->data[1] + (hDst / 4 + line) * lineSizeU + lineSizeU * 4 / 16, lineSizeU / 2); } //crop V for (size_t line = 0; line < hDst / 2; line++) { memcpy(pCropFrame->data[2] + line * pCropFrame->linesize[2], s_pPicFrame->data[2] + (hDst / 4 + line) * lineSizeV + lineSizeV * 4 / 16, lineSizeV / 2); } pCropFrame->width = wDst; pCropFrame->height = hDst; ... //通过libyuv scale pCropFrame ... ... //然后显示出来 ...
缩小 四周填黑
... //pPicFrame 为src AVFrame ... int wDst = pPicFrame->width * 2; int hDst = pPicFrame->height * 2; int wSrc = pPicFrame->width; int hSrc = pPicFrame->height; //扩大宽高 AVFrame* pCropFrame = AllocFrame(AV_PIX_FMT_YUV420P, wDst, hDst);//新的 int lineSizeY = pPicFrame->linesize[0]; int lineSizeU = pPicFrame->linesize[1]; int lineSizeV = pPicFrame->linesize[2]; //扩大宽高 pCropFrame->width = wDst; pCropFrame->height = hDst; pCropFrame->linesize[0] = pPicFrame->linesize[0] * 2; pCropFrame->linesize[1] = pPicFrame->linesize[1] * 2; pCropFrame->linesize[2] = pPicFrame->linesize[2] * 2; //默认填黑 memset(pCropFrame->data[0], 0, pCropFrame->linesize[0] * hDst ); memset(pCropFrame->data[1], 128, pCropFrame->linesize[1] * hDst / 2); memset(pCropFrame->data[2], 128, pCropFrame->linesize[2] * hDst / 2); //Process Y for (size_t line = 0; line < hSrc; line++) { memcpy(pCropFrame->data[0] + (hSrc / 2 + line) * pCropFrame->linesize[0] + pCropFrame->linesize[0] * 4 / 16, pPicFrame->data[0] + line*pPicFrame->linesize[0], wDst / 2); } //Process U for (size_t line = 0; line < hSrc / 2; line++) { memcpy(pCropFrame->data[1] + (hSrc / 4 + line) * pCropFrame->linesize[1] + pCropFrame->linesize[1] * 4 / 16, pPicFrame->data[1] + line*pPicFrame->linesize[1], wDst / 4); } //Process V for (size_t line = 0; line < hSrc / 2; line++) { memcpy(pCropFrame->data[2] + (hSrc / 4 + line) * pCropFrame->linesize[2] + pCropFrame->linesize[2] * 4 / 16, pPicFrame->data[2] + line*pPicFrame->linesize[2], wDst / 4); } pCropFrame->width = wDst; pCropFrame->height = hDst; ... //显示 ...