1. 裁剪NV21NV12

需要注意YUV三者的共用关系,Y的裁剪比较直接;但是对于UV而言,UV的大小各只有Y的大小的1/4(U的宽高和V的宽高都是Y的宽高的一半),因此在横纵向都要进行跳行,在横向由于UV是交叉排序,width / 2 的V和 width / 2 的U加起来刚好就是Y的大小,可以直接按偏移量裁剪。

void cropYuv420sp(char *yuv420sp, char *cropYuv420sp, int width, int height, int left, int top,int right, int bottom) {int halfWidth = width / 2;int cropImageWidth = right - left;int cropImageHeight = bottom - top;//复制Yint originalYLineStart = top * width;int targetYIndex = 0;//复制UVint originalUVLineStart = width * height + top * halfWidth;int targetUVIndex = cropImageWidth * cropImageHeight;for (int i = top; i < bottom; i++) {memcpy(cropYuv420sp + targetYIndex, yuv420sp + originalYLineStart + left, cropImageWidth);originalYLineStart += width;targetYIndex += cropImageWidth;if ((i & 1) == 0) {memcpy(cropYuv420sp + targetUVIndex, yuv420sp + originalUVLineStart + left,cropImageWidth);originalUVLineStart += width;targetUVIndex += cropImageWidth;}}
}

2. 裁剪YV12I420

和裁剪NV21类似,Y的裁剪比较直接;但是对于UV而言,UV的大小各只有Y的大小的1/4,且是各自连续排序(U的宽高和V的宽高都是Y的宽高的一半),因此在横纵向都要进行跳行。

void cropYuv420p(char *yuv420p, char *cropYuv420p, int width, int height, int left, int top,int right, int bottom) {int halfWidth = width / 2;int cropImageWidth = right - left;int cropImageHeight = bottom - top;//复制Yint originalYLineStart = top * width;int targetYIndex = 0;//复制UVint originalULineStart = width * height + top * halfWidth / 2;int originalVLineStart = width * height + width * height / 4 + top * halfWidth / 2;int targetUIndex = cropImageWidth * cropImageHeight;int targetVIndex = cropImageWidth * cropImageHeight * 5 / 4;int halfImageWidth = halfWidth;int halfLeft = left / 2;int halfCropImageWidth = cropImageWidth / 2;for (int i = top; i < bottom; i++) {memcpy(cropYuv420p + targetYIndex, yuv420p + originalYLineStart + left, cropImageWidth);originalYLineStart += width;targetYIndex += cropImageWidth;if ((i & 1) == 0) {memcpy(cropYuv420p + targetUIndex, yuv420p + originalULineStart + halfLeft,halfCropImageWidth);memcpy(cropYuv420p + targetVIndex, yuv420p + originalVLineStart + halfLeft,halfCropImageWidth);originalULineStart += halfImageWidth;originalVLineStart += halfImageWidth;targetUIndex += halfCropImageWidth;targetVIndex += halfCropImageWidth;}}
}

3. 裁剪YUYV

NV21I420之类的数据不同,YUYV的排列方式是YUYV YUYV....,每行的连续4个byte会有共用关系,这4个byte相当于2个像素),每行的数据宽度是 width * 2。
注意:该函数对入参有限制,需要裁剪的边界都需要是偶数。

void cropYuyv(char *yuyv, char *cropYuyv, int width, int height, int left, int top, int right,int bottom) {int cropImageWidth = right - left;int cropImageHeight = bottom - top;int lineDataSize = width * 2;int cropLineDataSize = cropImageWidth * 2;int originalLineStart = top * width * 2;int targetIndex = 0;int lineOffsetDataSize = left * 2;for (int i = top; i < bottom; i++) {memcpy(cropYuyv + targetIndex, yuyv + originalLineStart + lineOffsetDataSize, cropLineDataSize);originalLineStart += lineDataSize;targetIndex += cropLineDataSize;}
}

4. 裁剪BGR24

无论是BGR24RGB24,在裁剪时,都是以3个byte为一个整体进行裁剪,因此以下代码兼容24bpp的RGB数据的裁剪。

void cropRgb24(char *rgb24, char *cropRgb24, int width, int height, int left, int top, int right,int bottom) {int cropImageWidth = right - left;int cropImageHeight = bottom - top;int lineDataSize = width * 3;int cropLineDataSize = cropImageWidth * 3;int originalLineStart = top * lineDataSize;int targetIndex = 0;int lineOffsetDataSize = left * 3;for (int i = top; i < bottom; i++) {memcpy(cropRgb24 + targetIndex, rgb24 + originalLineStart + lineOffsetDataSize, cropLineDataSize);originalLineStart += lineDataSize;targetIndex += cropLineDataSize;}
}

FFmpeg之yuv裁剪(二十一)相关推荐

  1. ffmpeg实战教程(二)用SDL播放YUV,并结合ffmpeg实现简易播放器

    ffmpeg实战教程(二)用SDL播放YUV,并结合ffmpeg实现简易播放器 https://blog.csdn.net/King1425/article/details/71171142 我们先实 ...

  2. VTK学习笔记(二十一)vtk裁剪求截面面积

    VTK学习笔记(二十一)vtk裁剪求界面面积 1.代码 2.CMakeLists.txt 3.运行输出 4.面积正确性验证 4.1.代码 4.2.执行结果 1.代码 #pragma once#incl ...

  3. 中介者模式 调停者 Mediator 行为型 设计模式(二十一)

    中介者模式(Mediator) 调度.调停 意图 用一个中介对象(中介者)来封装一系列的对象交互,中介者使各对象不需要显式地相互引用,从而使其耦合松散 而且可以独立地改变它们之间的交互. 中介者模式又 ...

  4. 二十一世纪贫穷人的2008条语录

    流失的是岁月,留不走的是语言的录音-- 二十一世纪贫穷人的2006条语录 随便一条就能记住的:随便一条就能深思的:随便一条就能看下去的:随便一条就是哲理的:随便一条链接起来就是文章的:随便一条就能告诉 ...

  5. 二十一. Python基础(21)--Python基础(21)

    二十一. Python基础(21)--Python基础(21) 1 ● 类的命名空间 #对于类的静态属性:     #类.属性: 调用的就是类中的属性     #对象.属性: 先从自己的内存空间里找名 ...

  6. 某云数据中心网络解决方案(分享二十一)

    某云数据中心网络解决方案(分享二十一) 参考文章: (1)某云数据中心网络解决方案(分享二十一) (2)https://www.cnblogs.com/zywu-king/p/8284189.html ...

  7. iOS 11开发教程(二十一)iOS11应用视图美化按钮之实现按钮的响应(1)

    iOS 11开发教程(二十一)iOS11应用视图美化按钮之实现按钮的响应(1) 按钮主要是实现用户交互的,即实现响应.按钮实现响应的方式可以根据添加按钮的不同分为两种:一种是编辑界面添加按钮实现的响应 ...

  8. 运动控制器编程_快速入门 | 篇二十一:运动控制器ZHMI组态编程简介一

    点击上方"正运动小助手",随时关注新动态! 运动控制器ZHMI组态编程简介一  今天我们来学习一下,运动控制器的ZHMI组态编程简介.本文主要从产品概述.控制器连接触摸屏使用.HM ...

  9. SQL Server数据库开发的二十一条军规

    如果你正在负责一个基于SQL Server的项目,或者你刚刚接触SQL Server,你都有可能要面临一些数据库性能的问题,这篇文章会为你提供一些有用的指导(其中大多数也可以用于其它的DBMS). 在 ...

最新文章

  1. NanoPi NEO Air使用十五:使用V4L2驱动USB摄像头
  2. python 美颜人脸
  3. 欣赏多彩的计算机作品教案,五年级上信息技术教案-欣赏多彩的计算机作品长春版(三起).docx...
  4. springboot 控制台程序读取配置文件(原创)
  5. SAP License:2021年最新FICO面试答案
  6. Android开发笔记(一百七十七)借助FileProvider安装应用
  7. linux分析目录内存,在 Linux x86-64 模式下分析内存映射流程
  8. MySql 存储大量长字节 Text报错处理办法
  9. 第2节 网站点击流项目(下):5、访客分析
  10. 吉他录音混音教程|连这些录音知识都不懂,以后还怎么“混”?| MZD Studios
  11. 药物研发企业用哪个项目管理软件好?
  12. 电信云服务器装系统,天翼云主机重装系统的详细操作步骤
  13. 模拟题 czy的后宫
  14. Java使用JavaMail收发Email电子邮件
  15. 怎么让浏览器一直前置_上海居住证积分没有前置学历怎么解决?
  16. syntactic sugar - 语法糖 - 糖衣语法
  17. Cadence Orcad Capture元件位号自动编号的2种方法图文教程及视频演示
  18. Thinkpad E470重装WIN7系统后,重启进入boot menu的问题
  19. 关于:File.separator ( 详解 )
  20. 「数据库选型」抛弃MongoDB,拥抱PostgreSQL,工作更轻松

热门文章

  1. 关于maven modules开发时候,eclipse的dubug模式不能找到源代码
  2. 判定是否支持XHTML
  3. 利用光盘恢复grub引导器
  4. C#程序员66个编码好习惯
  5. Qt 发布 Android 自动驾驶技术预览
  6. 逆向工程平台 Radare2
  7. android pod 组件化_Flutter组件化导入至iOS现有工程中(CocoaPods篇)
  8. android http 图片上传,Android okHttp上传图片
  9. 模拟鱼群的matlab算法,IFSA人工鱼群算法
  10. apache 版本_Apache官宣!ShardingSphere首个Apache版本发布