安卓中常用的位图操作

一、View转换为Bitmap

       在Android中所有的控件都是View的直接子类或者间接子类,经由过程它们可以组成丰硕的UI界面。在视窗显示的时辰Android会把这些控件都加载到RAM中,形成一个以ViewRoot为根节点的控件树,然后由根节点起头逐级把控件绘制到屏幕上。

       可以经由过程挪用控件的setDrawingCacheEnabled(true)体例,开启绘图缓存功能,在绘制View的时辰把图像缓存起来,然后经由过程getDrawingCache()体例获取这个缓存的Bitmap。需要注重的是,当不再使用这个Bitmap时,需要挪用destroyDrawingCache()体例,释放Bitmap资本。因为在绘制View到屏幕时缓存图像会降低控件绘制的效率,是以只会在需要使用View的图像缓存的时辰才挪用setDrawingCacheEnabled(true)体例开启图像缓存功能,当不再使用图像缓存时需要挪用setDrawingCacheEnabled(false) 封锁图像缓存功能。

       这种体例在撑持拖拽类型的应用中经常见到,在Android系统的Launcher应用中也使用了这种体例,当用户拖拽应用的快捷图标时,获取到控件对应的Bitmap,然后操作这个Bitmap跟着手指移动。

       下面经由过程一段轨范代码来声名若何获取View对应的Bitmap。在轨范代码中使用了两个ImageView并给它们都设置了显示的图像资本,然后把第一个ImageView对应的bitmap显示到第二个ImageView中。因为在Activity的onCreate体例中挪用这个体例,当执行Activity的onCreate体例时,控件还没有筹备好,所以需要使用Handler进行延迟操作,Java轨范代码如下文所示:

// View转换为Bitmap 
    void getDrawingCache(final ImageView sourceImageView, 
            final ImageView destImageView) { 
                                          
        new Handler().postDelayed(new Runnable() { 
                                          
            @Override
            public void run() { 
                // TODO Auto-generated method stub 
                // 开启bitmap缓存 
                sourceImageView.setDrawingCacheEnabled(true); 
                // 获取bitmap缓存 
                Bitmap mBitmap = sourceImageView.getDrawingCache(); 
                // 显示 bitmap 
                destImageView.setImageBitmap(mBitmap); 
                                          
                // Bitmap mBitmap = sourceImageView.getDrawingCache(); 
                // Drawable drawable = (Drawable) new BitmapDrawable(mBitmap); 
                // destImageView.setImageDrawable(drawable); 
                new Handler().postDelayed(new Runnable() { 
                    @Override
                    public void run() { 
                        // TODO Auto-generated method stub 
                        // 不再显示bitmap缓存 
                        // destImageView.setImageBitmap(null); 
                        destImageView.setImageResource(R.drawable.anims); 
                                          
                        // 使用这句话而不是用上一句话是错误的,空指针挪用 
                        // destImageView.setBackgroundDrawable(null); 
                        // 封锁bitmap缓存 
                        sourceImageView.setDrawingCacheEnabled(false); 
                        // 释放bitmap缓存资本 
                        sourceImageView.destroyDrawingCache(); 
                    } 
                }, DELAY_TIME); 
            } 
        }, DELAY_TIME); 
    }



       运行下场如下文所示:


图7-3  Demo运行下场图1



图7-4  Demo运行下场图2



二、图像圆角措置  

       在Android中可以很容经由过程图像叠加的轨则为图像添加圆角下场。正常情形下,在已有的图像上绘图时将会在其上面添加一层新的图像。假如绘图时使用的Paint是完全不透明的,那么它将完全隐瞒住下面的图像,假如Paint是部门透明的,那么它将会对重叠部门图像的颜色叠加措置。经由过程PorterDuffXfermode轨则可以设置绘制图像时的叠加轨则。PorterDuffXfermode长短常壮大的转换模式,使用它可以设置图像叠加的Porter-Duff轨则,来节制Paint若何与Canvas上已有的图像进行叠加。下面列举了常用的12条Porter-Duff轨则及其暗示的寄义: 

       PorterDuff.Mode.CLEAR 断根画布上图像 
       PorterDuff.Mode.SRC 显示上层图像 
       PorterDuff.Mode.DST 显示下层图像 
       PorterDuff.Mode.SRC_OVER上下层图像都显示,下层居上显示 
       PorterDuff.Mode.DST_OVER 上下层都显示,下层居上显示 
       PorterDuff.Mode.SRC_IN 取两层图像交集部门,只显示上层图像 
       PorterDuff.Mode.DST_IN 取两层图像交集部门,只显示下层图像 
       PorterDuff.Mode.SRC_OUT 取上层图像非交集部门 
       PorterDuff.Mode.DST_OUT 取下层图像非交集部门 
       PorterDuff.Mode.SRC_ATOP 取下层图像非交集部门与上层图像交集部门 
       PorterDuff.Mode.DST_ATOP 取上层图像非交集部门与下层图像交集部门 
       PorterDuff.Mode.XOR 取两层图像的非交集部门 

       下面使用PorterDuff.Mode.SRC_IN轨则来给图像添加圆角下场,首要的思绪是先绘制一个圆角矩形,然后在上面绘制图像,取图像与圆角矩形的交集部门,只保留图像。Java轨范代码如下文所示:
public Bitmap getRoundedBitmap() { 
                                        
        Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), 
                R.drawable.default_1); 
        // 建树新的位图 
        Bitmap bgBitmap = Bitmap.createBitmap(mBitmap.getWidth(), 
                mBitmap.getHeight(), Config.ARGB_8888); 
                                        
        // 把建树的位图作为画板 
        Canvas mCanvas = new Canvas(bgBitmap); 
        Paint mPaint = new Paint(); 
        Rect mRect = new Rect(0, 0, mBitmap.getWidth(), mBitmap.getHeight()); 
        RectF mRectF = new RectF(mRect); 
                                        
        // 设置圆角半径为20 
        float roundPx = 15; 
        mPaint.setAntiAlias(true); 
        // 先绘制圆角矩形 
        mCanvas.drawRoundRect(mRectF, roundPx, roundPx, mPaint); 
                                        
        // 设置图像的叠加模式 
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 
        // 绘制图像 
        mCanvas.drawBitmap(mBitmap, mRect, mRect, mPaint); 
        return bgBitmap; 
                                        
    }


       下场如下文所示图所示: 


图7-5  图像圆角措置



三、图像灰化措置  

       在Android中可以经由过程ColorMatrix类实现图像措置软件中的滤镜下场,经由过程ColorMatrix类可以对位图中的每个像素进行变换措置,达到非凡的滤镜下场,下面经由过程一个例子来介绍若何经由过程ColorMatrix对图像进行灰化措置,Java轨范代码如下文所示: 
// 图像灰化措置 
    public Bitmap getGrayBitmap() { 
        Bitmap mBitmap = BitmapFactory.decodeResource(getResources(), 
                R.drawable.anims); 
        Bitmap mGrayBitmap = Bitmap.createBitmap(mBitmap.getWidth(), 
                mBitmap.getHeight(), Config.ARGB_8888); 
        Canvas mCanvas = new Canvas(mGrayBitmap); 
        Paint mPaint = new Paint(); 
        // 建树颜色变换矩阵 
        ColorMatrix mColorMatrix = new ColorMatrix(); 
        // 设置灰度影响规模 
        mColorMatrix.setSaturation(0); 
        // 建树颜色过滤矩阵 
        ColorMatrixColorFilter mColorFilter = new ColorMatrixColorFilter( 
                mColorMatrix); 
        // 设置画笔的颜色过滤矩阵 
        mPaint.setColorFilter(mColorFilter); 
        // 使用措置后的画笔绘制图像 
        mCanvas.drawBitmap(mBitmap, 0, 0, mPaint); 
        return mGrayBitmap; 
    }


       下场如下文所示图所示: 


图7-6  图像灰化措置



四、提取图像Alpha位图  

       Android中的ARGB_8888类型的位图由Alpha(透明度)、Red(红)、Green(绿)、Blue(蓝)四部门组成,其中Alpha部门也就是常说的Alpha通道,它节制图像的透明度。在Android中Bitmap类供给了extractAlpha()体例,可以把位图中的Alpha部门提掏出来作为一个新的位图,然后与填充颜色后的Paint连系从头绘制一个新图像。下面经由过程一个例子来声名Bitmap类的extractAlpha()体例的使用,Java轨范代码如下文所示: 
// 提取图像Alpha位图 
    public Bitmap getAlphaBitmap() { 
        BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() 
                .getDrawable(R.drawable.anims); 
        Bitmap mBitmap = mBitmapDrawable.getBitmap(); 
                            
        // BitmapDrawable的getIntrinsicWidth()体例,Bitmap的getWidth()体例 
        // 注重这两个体例的区别 
        // Bitmap mAlphaBitmap = 
        // Bitmap.createBitmap(mBitmapDrawable.getIntrinsicWidth(), 
        // mBitmapDrawable.getIntrinsicHeight(), Config.ARGB_8888); 
        Bitmap mAlphaBitmap = Bitmap.createBitmap(mBitmap.getWidth(), 
                mBitmap.getHeight(), Config.ARGB_8888); 
                            
        Canvas mCanvas = new Canvas(mAlphaBitmap); 
        Paint mPaint = new Paint(); 
                            
        mPaint.setColor(Color.BLUE); 
                            
        // 从原位图中提取只包含alpha的位图 
        Bitmap alphaBitmap = mBitmap.extractAlpha(); 
                            
        // 在画布上(mAlphaBitmap)绘制alpha位图 
        mCanvas.drawBitmap(alphaBitmap, 0, 0, mPaint); 
                            
        return mAlphaBitmap; 
                            
    }


图7-7  提取图像Alpha位图



       其中最后一幅图像是把原图像四个边距缩小两个dp,然后与Alpha位图一路绘制的功效,读者可以参照本章Demo中的getStrokeBitmap()体例。 

五、图像变换  

       Android开发框架供给了一个坐标变换矩阵Matrix类,它可以与Bitmap类的createBitmap体例连系使用,对图像进行缩放、扭转、扭曲等变换措置。图像变换操作就是对坐标变换矩阵进行矩阵乘法运算,Matrix类中供给了一些精练的体例如preScale、postScale、preRotate、postRotate、preSkrew、postSkrew、preTranslate、postTranslate等封装了矩阵的运算,它们与Bitmap类的createBitmap体例连系使用可以很轻易地对图像进行缩放、扭转、扭曲、平移操作。 

1)图像缩放 

       使用Matrix类preScale或者postScale可以对图像进行缩放操作,它的两个参数分袂为x和y坐标缩放比例,下面使用preScale对图像进行放大0.75倍,Java轨范代码如下文所示: 
// 图像缩放 
    public Bitmap getScaleBitmap() { 
        BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() 
                .getDrawable(R.drawable.anims); 
        Bitmap mBitmap = mBitmapDrawable.getBitmap(); 
        int width = mBitmap.getWidth(); 
        int height = mBitmap.getHeight(); 
        Matrix matrix = new Matrix(); 
        matrix.preScale(0.75f, 0.75f); 
        Bitmap mScaleBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, 
                matrix, true); 
                          
        return mScaleBitmap; 
                          
    }

       下场如下文所示图所示: 


图7-8  图像缩放



2)图像扭转  

       使用Matrix类preRotate或者postRotate可以对图像进行扭转操作,它只有一个参数暗示扭转的角度,下面使用preRotate对图像顺时针扭转30度,Java轨范代码如下文所示: 
​​c
// 图像扭转 
    public Bitmap getRotatedBitmap() { 
        BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() 
                .getDrawable(R.drawable.anims); 
        Bitmap mBitmap = mBitmapDrawable.getBitmap(); 
        int width = mBitmap.getWidth(); 
        int height = mBitmap.getHeight(); 
        Matrix matrix = new Matrix(); 
        matrix.preRotate(45); 
        Bitmap mRotateBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, 
                height, matrix, true); 
                     
        return mRotateBitmap; 
                     
    }

       下场如下文所示图所示: 


图7-9  图像扭转



3)图像倾斜  

       使用Matrix类preSkew或者postSkew可以对图像进行倾斜操作,它的两个参数分袂为x和y坐标倾斜度,下面使用preSkew对图像进行倾斜变换,Java轨范代码如下文所示: 

// 图像倾斜 
    public Bitmap getScrewBitmap() { 
        BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() 
                .getDrawable(R.drawable.anims); 
        Bitmap mBitmap = mBitmapDrawable.getBitmap(); 
        int width = mBitmap.getWidth(); 
        int height = mBitmap.getHeight(); 
                    
        Matrix matrix = new Matrix(); 
        matrix.preSkew(1.0f, 0.15f); 
        Bitmap mScrewBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, height, 
                matrix, true); 
                    
        return mScrewBitmap; 
                    
    }

       下场如下文所示图所示: 


图7-10  图像倾斜



4)图像倒影

       为图像添加倒影下场之后,图像看起来会有立体感,更有真实感,在Android中使用Matrix类可以很轻易实现图像的倒影下场。主若是Matrix的preScale体例的使用,给它设置负数缩放比例,图像就会进行反转。然后经由过程设置Shader添加渐变下场。Java轨范代码如下文所示:

// 图像倒影 
    private Bitmap getReflectedBitmap() { 
        BitmapDrawable mBitmapDrawable = (BitmapDrawable) getResources() 
                .getDrawable(R.drawable.anims); 
        Bitmap mBitmap = mBitmapDrawable.getBitmap(); 
        int width = mBitmap.getWidth(); 
        int height = mBitmap.getHeight(); 
               
        Matrix matrix = new Matrix(); 
        // 图像缩放,x轴变为原本的1倍,y轴为-1倍,实现图像的反转 
        matrix.preScale(1, -1); 
               
        // 建树反转后的图像Bitmap对象,图像高是原图的一半。 
        // Bitmap mInverseBitmap = Bitmap.createBitmap(mBitmap, 0, height/2, 
        // width, height/2, matrix, false); 
        // 建树尺度的Bitmap对象,宽和原图一致,高是原图的1.5倍。 
        // 注重两种createBitmap的分歧 
        // Bitmap mReflectedBitmap = Bitmap.createBitmap(width, height*3/2, 
        // Config.ARGB_8888); 
               
        Bitmap mInverseBitmap = Bitmap.createBitmap(mBitmap, 0, 0, width, 
                height, matrix, false); 
        Bitmap mReflectedBitmap = Bitmap.createBitmap(width, height * 2, 
                Config.ARGB_8888); 
               
        // 把新建的位图作为画板 
        Canvas mCanvas = new Canvas(mReflectedBitmap); 
               
        // 绘制图像 
        mCanvas.drawBitmap(mBitmap, 0, 0, null); 
        mCanvas.drawBitmap(mInverseBitmap, 0, height, null); 
               
        // 添加倒影的渐变下场 
        Paint mPaint = new Paint(); 
        Shader mShader = new LinearGradient(0, height, 0, 
                mReflectedBitmap.getHeight(), 0x70ffffff, 0x00ffffff, 
                TileMode.MIRROR); 
        mPaint.setShader(mShader); 
        // 设置叠加模式 
        mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN)); 
               
        // 绘制遮罩下场 
        mCanvas.drawRect(0, height, width, mReflectedBitmap.getHeight(), mPaint); 
               
        return mReflectedBitmap; 
               
    }






       下场如下文所示图所示:


图7-11  图像倒影



5)图像剪切  

       假如只需要图像的一部门,就必需对图像进行剪切措置,在原图像上选择一个剪切区域,使用PorterDuffXfermode图像叠加轨则,就可以把指定的图像区域剪切下来,下面经由过程三个轨范来声名假如对图像进行剪切操作。 

       第一步,建树一个新位图作为画板,然后把原图像画到新位图上面,Java轨范代码如下文所示: 
               

BitmapDrawable bd = (BitmapDrawable) getResources().getDrawable( 
            
        R.drawable.default_1); 
            
        Bitmap bitmap = bd.getBitmap(); 
            
        int w = bitmap.getWidth(); 
            
        int h = bitmap.getHeight(); 
            
        Bitmap bm = Bitmap.createBitmap(w, h, Config.ARGB_8888); 
            
        Canvas canvas = new Canvas(bm); 
            
        Paint mPaint = new Paint(); 
            
        mPaint.setAntiAlias(true); 
            
        mPaint.setStyle(Style.STROKE); 
            
        canvas.drawBitmap(bitmap, 0, 0, mPaint);





       下场如下文所示图所示: 


图7-12  第一步下场图



       第二步,绘制一个剪切区域,好比要剪切人物的脸部区域,需要在指定的位置绘制一个圆角矩形区域,轨范代码中的坐标是在调试中获得,在其他分辩率下会有所分歧,Java轨范代码如下文所示: 

                
int deltX = 76; 
          
        int deltY = 98; 
          
        DashPathEffect dashStyle = new DashPathEffect( 
                new float[] { 10, 5, 5, 5 }, 2);// 建树虚线边框样式 
          
        RectF faceRect = new RectF(0, 0, 88, 106); 
          
        float[] faceCornerii = new float[] { 30, 30, 30, 30, 75, 75, 75, 75 }; 
          
        Paint mPaint = new Paint();// 建树画笔 
          
        mPaint.setColor(0xFF6F8DD5); 
          
        mPaint.setStrokeWidth(6); 
          
        mPaint.setPathEffect(dashStyle); 
          
        Path clip = new Path();// 建树路径 
          
        clip.reset(); 
          
        clip.addRoundRect(faceRect, faceCornerii, Direction.CW);// 添加圆角矩形路径 
          
        canvas.save();// 保留画布 
          
        canvas.translate(deltX, deltY); 
          
        canvas.clipPath(clip, Region.Op.DIFFERENCE); 
          
        canvas.drawColor(0xDF222222); 
          
        canvas.drawPath(clip, mPaint);// 绘制路径 
          
        canvas.restore();





       下场如下文所示图所示: 


图7-13  第二步下场



       第三步,从原图像上获取指定区域的图像,并绘制到屏幕上,java轨范代码如下文所示: 

                
Rect srcRect = new Rect(0, 0, 88, 106); 
        srcRect.offset(deltX, deltY); 
         
        PaintFlagsDrawFilter dfd = new PaintFlagsDrawFilter( 
                Paint.ANTI_ALIAS_FLAG, 
         
                Paint.FILTER_BITMAP_FLAG); 
         
        canvas.setDrawFilter(dfd); 
         
        canvas.clipPath(clip);// 使用路径剪切画布 
         
        canvas.drawBitmap(bitmap, srcRect, faceRect, mPaint);




       下场如下文所示图所示: 


图7-13  第三部下场图


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值