YUV图像旋转
来源:互联网 发布:mysql字段值累加 编辑:程序博客网 时间:2024/05/19 21:03
近期参与了Android程序开发,涉及到音视频。由于Android的窗口模式不同于传统的窗口,有时候需要对图像进行90度旋转。对图像旋转主要是对YUV图片的旋转,以下代码是将一个格式为YUV420的图片进行逆时针旋转。
void yuv_rotate_90(uchar *des,uchar *src,int width,int height) { int n = 0; int hw = width>>1; int hh = height>>1; int size = width * height; int hsize = size>>2; int pos = 0; //copy y for(int j = 0; j < width;j++) { pos = size; for(int i = height - 1; i >= 0; i--) {pos-=width; des[n++] = src[pos + j]; } } //copy uv uchar *ptemp = src + size; int m = n + hsize; for(int j = 0;j < hw;j++) { pos= hsize; for(int i = hh - 1;i >= 0;i--) { pos-=hw; des[n++] = ptemp[ pos + j ]; des[m++] = ptemp[ pos + j+ hsize ]; } }}
很多音视频相关的项目里面用到了ffmpeg,对ffmpeg里面的视频帧进行旋转主要是在视频解码后,图片显示前完成,于是将以上代码改到ffmpeg的应用环境。ffmpeg里面解码完成后的视频帧结构是AVFrame,以下代码是所述代码。
逆时针90度
void frame_rotate_90( AVFrame *src,AVFrame*des) { int n = 0; int hw = src->width>>1; int hh = src->height>>1; int size = src->width * src->height; int hsize = size>>2; int pos = 0; //copy y for(int j = 0; j < src->width;j++) { pos = size; for(int i = src->height - 1; i >= 0; i--) { pos-=src->width; des->data[0][n++] = src->data[0][pos + j]; } } //copy uv n = 0; for(int j = 0;j < hw;j++) { pos= hsize; for(int i = hh - 1;i >= 0;i--) { pos-=hw; des->data[1][n] = src->data[1][ pos + j]; des->data[2][n] = src->data[2][ pos + j]; n++; } } des->linesize[0] = src->height; des->linesize[1] = src->height>>1; des->linesize[2] = src->height>>1; des->height = src->width; des->width = src->height;}
逆时针180度旋转
void frame_rotate_180(AVFrame *src,AVFrame*des){int n = 0,i= 0,j = 0; int hw = src->width>>1; int hh = src->height>>1; int pos= src->width * src->height; for (i = 0; i < src->height; i++){ pos-= src->width; for (int j = 0; j < src->width; j++) { des->data[0][n++] = src->data[0][pos + j]; } }n = 0;pos = src->width * src->height>>2;for (i = 0; i < hh;i++) { pos-= hw; for (int j = 0; j < hw;j++) {des->data[1][n] = src->data[1][ pos + j];des->data[2][n] = src->data[2][ pos + j];n++; } }des->linesize[0] = src->width;des->linesize[1] = src->width>>1;des->linesize[2] = src->width>>1;des->width = src->width;des->height = src->height;des->format = src->format;des->pts = src->pts;des->pkt_pts = src->pkt_pts;des->pkt_dts = src->pkt_dts;des->key_frame = src->key_frame;}
逆时针270度旋转:
void frame_rotate_270(AVFrame *src,AVFrame*des){int n = 0,i= 0,j = 0; int hw = src->width>>1; int hh = src->height>>1; int pos = 0;for(i = src->width-1;i >= 0;i--){pos = 0;for(j= 0;j < src->height;j++){ des->data[0][n++]= src->data[0][pos+i];pos += src->width;}}n = 0;for (i = hw-1; i >= 0;i--) { pos= 0; for (j = 0; j < hh;j++) { des->data[1][n]= src->data[1][pos+i]; des->data[2][n]= src->data[2][pos+i];pos += hw; n++; } }des->linesize[0] = src->height;des->linesize[1] = src->height>>1;des->linesize[2] = src->height>>1;des->width = src->height;des->height = src->width;des->format = src->format;des->pts = src->pts;des->pkt_pts = src->pkt_pts;des->pkt_dts = src->pkt_dts;des->key_frame = src->key_frame;}
注意:
1,在ffmpeg环境下,调用frame_rotate系列函数之前需要对 AVFrame*des 进行初始化,否则内存是否发进行拷贝的。初始化代码如下:AVFrame *des = av_frame_alloc();unsigned char *rotate_buffer=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->height, pCodecCtx->width,1));av_image_fill_arrays(des->data, des->linesize,rotate_buffer,AV_PIX_FMT_YUV420P,pCodecCtx->height, pCodecCtx->width,1);
2,经过旋转后,视频帧的宽和高已经发生了变化,所以进行显示时,应该以旋转后的宽高进行显示,不再是AVCodecContext里面的宽和高,SDL里面的Window和Texture都要进行调整,否则图片会花,或者崩溃。
参考:
1,http://blog.csdn.net/kl222/article/details/24470305 感觉算法有点问题,图片经过旋转后UV部分存在问题。
2,http://blog.csdn.net/codefoxtiger/article/details/23549553 算法对,但是性能需要优化,旋转一次,会调用太多乘法,对Android环境不太适用。
1 0
- YUV图像旋转
- YUV图像
- YUV图像
- YUV格式转换、旋转
- YUV图像数据分析
- YUV图像合成原理
- D3D显示YUV图像
- YUV图像合成原理
- 如何显示YUV图像
- YUV图像数据分析
- V4L2抓取YUV图像
- SDL2显示YUV图像
- 图像旋转
- 旋转图像
- 图像旋转
- 图像旋转
- 图像旋转
- 图像旋转
- Android自动化之adb命令
- 【NOIP2016提高A组8.12】奇袭
- Kotlin语法(七)-属性和字段
- js鼠标滚轮事件
- 利用ViewDragHelper实现上拉加载更多与下拉刷新
- YUV图像旋转
- 替换字符串中连续出现的指定字符串
- t077宝物筛选
- Basic基础——数学,线代,概率基础
- LightOJ 1104 Birthday Paradox(生日悖论,思维)
- 1857. 最大值
- getchar用法
- Android中Services之异步IntentService
- Data Pre-processing(数据预处理)