需要注意Y
、U
、V
三者的共用关系,Y
的裁剪比较直接;但是对于U
和V
而言,U
和V
的大小各只有Y
的大小的1/4(U
的宽高和V
的宽高都是Y
的宽高的一半),因此在横纵向都要进行跳行,在横向由于U
和V
是交叉排序,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;
//复制Y
int originalYLineStart = top * width;
int targetYIndex = 0;
//复制UV
int 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;
}
}
}
和裁剪NV21
类似,Y的裁剪比较直接;但是对于U
和V
而言,U
和V
的大小各只有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;
//复制Y
int originalYLineStart = top * width;
int targetYIndex = 0;
//复制UV
int 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;
}
}
}
**和NV21
、I420
之类的数据不同,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;
【延伸Android必备知识点】
【Android部分高级架构视频学习资源】
**Android精讲视频学习后更加是如虎添翼!**进军BATJ大厂等(备战)!现在都说互联网寒冬,其实无非就是你上错了车,且穿的少(技能),要是你上对车,自身技术能力够强,公司换掉的代价大,怎么可能会被裁掉,都是淘汰末端的业务Curd而已!现如今市场上初级程序员泛滥,这套教程针对Android开发工程师1-6年的人员、正处于瓶颈期,想要年后突破自己涨薪的,进阶Android中高级、架构师对你更是如鱼得水!
**任何市场都是优胜略汰适者生存,只要你技术过硬,到哪里都不存在饱和不饱和的问题,所以重要的还是提升自己。懂得多是自己的加分项 而不是必须项。门槛高了只能证明这个市场在不断成熟化!**另外一千个读者就有一千个哈姆雷特,所以以上只是自己的关键,不喜勿喷!
如果你是卡在缺少学习资源的瓶颈上,那么刚刚好我能帮到你。欢迎关注会持续更新和分享的。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!
不断成熟化!**另外一千个读者就有一千个哈姆雷特,所以以上只是自己的关键,不喜勿喷!
如果你是卡在缺少学习资源的瓶颈上,那么刚刚好我能帮到你。欢迎关注会持续更新和分享的。
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》,点击传送门,即可获取!