zoukankan      html  css  js  c++  java
  • 对YUV数据进行裁剪

    项目中用到,用来对YUV数据(图片的yuv或者视频单帧yuv数据)进行裁剪。

    格式介绍:http://blog.csdn.net/vblittleboy/article/details/10945143

    import android.graphics.RectF;
    import android.util.Log;
    
    /**
     * 用来裁剪yuv图像
     * @author willhua
     *
     */
    public class YuvCroper {
        private static String LOG_TAG = "VideoCrop";
        public static int YUV_420SP = 0;  //也即NV12 YYY...UVUVUV...
        public static int YUV_420P = 1;  //也即I420  YYY...UUU...VVV...
        
        private final int mType;
        private byte[] mData;
        private final int mWidth;
        private final int mHeight;
        private final int mYLenght;
        private final int mCropLeft;
        private final int mCropTop;
        private int mCropWidth;
        private int mCropHeight;
        
        /**
         * 
         * @param type yuv数据类型:YUV_SP()   YUV_420P()
         * @param width yuv数据的原始宽度
         * @param height yuv数据的原始高度
         * @param crop 裁剪的区域。比如(0.25,0,1,0.85),每个值都在0-1之间
         * @throws Exception
         */
        public YuvCroper(int type, int width, int height, RectF crop) throws Exception{
            if(width <= 0 || height <= 0 || crop == null || crop.width() <= 0 || crop.height() <= 0){
                throw new Exception("ViewCrop:Wrong param! size:" + width + "*" + height + ". Crop:"+ crop);
            }
            mType = type;
            mWidth = width; 
            mHeight = height;
            mYLenght = mWidth * mHeight;
            mCropHeight = (int)(crop.height() * mHeight);
            mCropWidth = (int)(crop.width() * mWidth);
            mCropHeight = roundTo16(mCropHeight, mHeight);
            mCropWidth = roundTo16(mCropWidth, mWidth);
            mCropLeft = (int)(crop.left * mWidth) / 16 * 16;
            mCropTop = (int)(crop.top * mHeight) / 16 * 16;
            mData = new byte[mCropHeight * mCropWidth * 3 / 2];
            Log.d(LOG_TAG, "crop  point:" + mCropLeft + "*" + mCropTop + "     size:" + mCropWidth + "*" + mCropHeight);
        }
        
        /**
         * 单帧yuv数据
         * @param oriData
         * @return
         */
        public byte[] crop(byte[] oriData){
            if(oriData == null || oriData.length != mYLenght * 3 / 2){
                Log.d(LOG_TAG, "crop:wrong oriData!!!");
                return mData;
            }
            if(mType == YUV_420SP){
                processYuvsp(oriData);
            }else if(mType == YUV_420P){
                processYuv420p(oriData);
            }
            return mData;
        }
        
        private void processYuvsp(byte[] oriData){
            //copy y;
            int index = 0;
            int start = mCropLeft + mWidth * mCropTop;
            int end = mWidth * (mCropTop + mCropHeight);
            int oriStep = mWidth;
            int newstep = mCropWidth;
            index = copy(oriData, start, end, oriStep, newstep, index);
            
            //copy uv
            start = mYLenght + mWidth * mCropTop / 2 + mCropLeft;
            end = mYLenght + mWidth * (mCropTop + mCropHeight) / 2;
            oriStep = mWidth;
            newstep = mCropWidth;
            copy(oriData, start, end, oriStep, newstep, index);
        }
        
        private void processYuv420p(byte[] oriData){
            int index = 0;
            int start = mCropLeft + mCropTop * mWidth;
            int end = mWidth * (mCropTop + mCropHeight);
            int oriStep = mWidth;
            int newstep = mCropWidth;
            //copy y;
            index = copy(oriData, start, end, oriStep, newstep, index);
            
            //copy u
            start = mYLenght + (mWidth * mCropTop / 4 + mCropLeft / 2) ;
            end = mYLenght + mWidth * (mCropTop + mCropHeight) / 4;
            oriStep = mWidth / 2;
            newstep = mCropWidth / 2;
            index = copy(oriData, start, end, oriStep, newstep, index);
    
            //copy v
            start = mYLenght / 4 * 5 + mWidth * mCropTop / 4 + mCropLeft / 2;
            end = mYLenght / 4 * 5 + mWidth * (mCropTop + mCropHeight) / 4;
            copy(oriData, start, end, oriStep, newstep, index);   
        }
        
        private int copy(byte[] oriData, int start, int end, int oriStep, int newstep, int index){
            for(int i = start; i < end; i += oriStep){ 
                System.arraycopy(oriData, i, mData, index, newstep);
                index += newstep;
            }
            return index;
        }
        
        /**
         * 对于高通或者MTK平台,只支持宽高为16的整数备的数据
         * @param size
         * @param limit
         * @return
         */
        private int roundTo16(int size, int limit){
            if(size >= limit){
                return limit;
            }
            float f = size / 16f;
            int m;
            if(f - (int)f > 0.5f){
                m = ((int)(f + 0.5)) * 16;
            }else{
                m = (int)f * 16;
            }
            return m < 16 ? 16 : m;
        }
        
    }
  • 相关阅读:
    Bootstrap 2.3.2导航问题
    隐藏wordpress登陆后台
    WordPress 中文图片 上传 自动重命名
    wordpress上传附件提示抱歉,出于安全的考虑,不支持此文件类型
    移动端适配
    项目中常见的正则校验
    vue中 的 this.$nextTick (Vue中DOM的异步更新)
    vue中使用webscoket
    登堂入室---进阶代码
    Flex布局
  • 原文地址:https://www.cnblogs.com/willhua/p/6480527.html
Copyright © 2011-2022 走看看