yuv裁剪

1. 裁剪NV21或NV12需要注意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;
        }
    }
}

2. 裁剪YV12或I420
和裁剪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;
        }
    }
}

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

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
无论是BGR24、RGB24;在裁剪时;都是以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;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值