Bitmap使用

Posted Could_Deng

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bitmap使用相关的知识,希望对你有一定的参考价值。

一.Bitmap

1.Bitmap的生成

/**
     * 由本地文件路径、网络url或者项目的资源文件,生成Bitmap(旧,极端情况下可能造成OOM)
     * @param filePath
     */
    private void productBitmap(String filePath){
        Bitmap des_bitmap = null;
        BitmapFactory.Options options  = new BitmapFactory.Options();

        //本地文件路径或者网络url
        Uri uri = Uri.parse(filePath);
        des_bitmap = BitmapFactory.decodeFile(uri.toString(),options);

        //项目资源文件
        des_bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);

        if(iv_bitmap_test!=null) {
            iv_bitmap_test.setImageBitmap(des_bitmap);
        }else{
            iv_bitmap_test = (ImageView) findViewById(R.id.iv_bitmap_test);
            iv_bitmap_test.setImageBitmap(des_bitmap);
        }
    }

 

2.bitmap缩放、等图像变换

(1)长宽相同比例缩放

用BitmapFactory的decodeFile方法,然后通过传递进去 BitmapFactory.Option类型的参数进行取缩略图,在Option中,属性值inSampleSize表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4。

经过阅读文档发现,Options中有个属性inJustDecodeBounds,文档中的是这么说的:

If set to true, the decoder will return null (no bitmap), but the out... fields will still be set, allowing the caller to query the bitmap without having to allocate the memory for its pixels.  

意思就是说如果该值设为true那么将不返回实际的bitmap对象,不给其分配内存空间但是可以得到一些解码边界信息即图片大小等信息。因此我们可以通过设置inJustDecodeBounds为true,获取到outHeight(图片原始高度)和 outWidth(图片的原始宽度),然后计算一个inSampleSize(缩放值),就可以取图片了,这里要注意的是,inSampleSize 可能等于0,必须做判断。也就是说先将Options的属性inJustDecodeBounds设为true,先获取图片的基本大小信息数据(信息没有保存在bitmap里面,而是保存在options里面),通过options.outHeight和 options. outWidth获取的大小信息以及自己想要到得图片大小计算出来缩放比例inSampleSize,然后紧接着将inJustDecodeBounds设为false,就可以根据已经得到的缩放比例得到自己想要的图片缩放图了。

/**
     * 由File转成长宽固定相同比例的bitmap。实现长宽等比例缩放
     * @return
     */
    private Bitmap resizeBitmap(String filePath){
        Bitmap des_bitmap ;

        BitmapFactory.Options options = new BitmapFactory.Options();
        //表示缩略图大小为原始图片大小的几分之一,即如果这个值为2,则取出的缩略图的宽和高都是原始图片的1/2,图片大小就为原始大小的1/4
        options.inJustDecodeBounds = true;
        des_bitmap = BitmapFactory.decodeFile(filePath,options);//des_bitmap为null.因为options.inJustDecodeBounds = true,节省内存

        //长宽按照相同比例缩放
        int height = options.outHeight;
        int width = options.outWidth;
        int scale;//缩放值,因为为等比例缩放.
        if(height > width){//以高为准
            scale = (int) (height/200.0f);//该200说明目标大小为200PX
        }else{
            scale = (int) (width/200.0f);//该200说明目标大小为200PX
        }
        if(scale<=0){
            scale = 1;
        }
        options.inSampleSize = scale;
        options.inJustDecodeBounds = false;
        Bitmap new_bitmap = BitmapFactory.decodeFile(filePath,options);//des_bitmap不为null
        if(des_bitmap!=new_bitmap){
            des_bitmap.recycle();//注意销毁不用的bitmap
        }
        return new_bitmap;
    }

 

(2)Bitmap与Matrix搭配,实现缩放或者其他形变例如旋转

/**
     * 由Bitmap转成指定大小的Bitmap,实现缩放成指定准确大小Bitmap
     * @param filePath
     * @param sWidth 目标宽
     * @param sHeight 目标高
     */
    private Bitmap resizeBitmap(String filePath,int sWidth,int sHeight){
        //缩放到指定的长宽
        Bitmap mBitmap;
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = false;
        mBitmap = BitmapFactory.decodeFile(filePath,options);
        if(mBitmap == null){
            return null;
        }
        int bmpWidth = mBitmap.getWidth();
        int bmpHeight = mBitmap.getHeight();
        // 缩放图片的尺寸
        float scaleWidth = (float) sWidth / bmpWidth; // 按固定大小缩放 sWidth 写多大就多大
        float scaleHeight = (float) sHeight / bmpHeight; //
        Matrix matrix = new Matrix();
    //matrix.postScale(1, -1); //镜像垂直翻转
    //matrix.postScale(-1, 1); //镜像水平翻转
    //matrix.postRotate(-90); //旋转-90度
matrix.postScale(scaleWidth, scaleHeight);// 产生缩放后的Bitmap对象 Bitmap resizeBitmap = Bitmap.createBitmap(mBitmap, 0, 0, bmpWidth, bmpHeight, matrix, false); mBitmap.recycle(); return resizeBitmap; }

 

 

3.bitmap模糊处理

(二)自定义的模糊

 

(一)高斯模糊

4.bitmap保存图像文件

(一)保存

/**
     * 保存内存中的bitmap到本地文件
     * @param bitmap 要保存的bitmap
     * @param localPath 保存在本地的文件名,绝对路径
     * */
    public static void saveBitmap2File(Bitmap bitmap,String localPath){
        if (bitmap == null) {
            return;
        }
        try {
            File file = new File(localPath);
            FileOutputStream fos = new FileOutputStream(file);
            assert bitmap != null;
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            fos.flush();
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

5.Bitmap的防止内存泄露小方法

(一)生成Bitmap时使用FileDescriptor

/**
     * 由本地文件生成bitmap时,节省内存的方法
     * @param context
     * @param filePath
     * @throws Exception
     */
    private void productBitmap(Context context,String filePath) throws Exception {
        Bitmap des_bitmap = null;
        BitmapFactory.Options options = new BitmapFactory.Options();

        //方法一.本地文件路径
        File file = new File(filePath);
        try {
            FileInputStream is = new FileInputStream(file);
            FileDescriptor fd = is.getFD();
            des_bitmap = BitmapFactory.decodeFileDescriptor(fd,null,options);
            if(iv_bitmap_test!=null) {
                iv_bitmap_test.setImageBitmap(des_bitmap);
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


        //方法二。
        //不允许网络url,只允许本地绝对路径即file://sdcard//开头
//        String url = "http://itfish.net/Home/Modules/Images/itfish_54346_0.jpg";
//        String url = Environment
//                .getExternalStorageDirectory().getAbsolutePath()
//                + File.separator+"fitmix"+File.separator+"Cover"+File.separator+"137_radio.jpg";
        String url = "file:///sdcard/"+"fitmix"+File.separator+"Cover"+File.separator+"137_radio.jpg";//注意路径
        ParcelFileDescriptor parcelFileDescriptor = context.getContentResolver().openFileDescriptor(Uri.parse(url),"r");
        FileDescriptor fileDescriptor ;
        if(parcelFileDescriptor != null){
            fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        }else{
            fileDescriptor = null;
        }

        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);

        int inSampleSize = 1;

        if (options.outHeight > 200.0f || options.outWidth > 200.0f) {
            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width lower or equal to the requested height and width.
            while ((options.outHeight / inSampleSize) > 200.0f || (options.outWidth / inSampleSize) > 200.0f) {
                inSampleSize *= 2;
            }
        }

        options.inSampleSize = inSampleSize;
        options.inJustDecodeBounds = false;

        Bitmap decodeSampledBitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor, null, options);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            parcelFileDescriptor.close();
        }

        iv_bitmap_test.setImageBitmap(decodeSampledBitmap);
    }

 

5.bitmap原理

 

 

以上是关于Bitmap使用的主要内容,如果未能解决你的问题,请参考以下文章

Android 性能优化读书笔记 Bitmap解码

Android 性能优化读书笔记 Bitmap解码

Bitmap(Type, String) 图片路径

bitmap.setPixel抛出了IllegalStateException 异常

Android ,base64转bitmap

C#中图片已经保存于Bitmap中,如何实现将该Bitmap图像保存在本地磁盘