温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Android开发怎么实现图片大小与质量压缩及保存

发布时间:2022-04-27 16:30:21 来源:亿速云 阅读:171 作者:iii 栏目:开发技术

本篇内容主要讲解“Android开发怎么实现图片大小与质量压缩及保存”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Android开发怎么实现图片大小与质量压缩及保存”吧!

    Android中图片有四种属性

    ALPHA_8:每个像素占用1byte内存

    ARGB_4444:每个像素占用2byte内存

    ARGB_8888:每个像素占用4byte内存 (默认)

    RGB_565:每个像素占用2byte内存

    Android默认的颜色模式为ARGB_8888,这个颜色模式色彩最细腻,显示质量最高。但同样的,占用的内存也最大。所以在对图片效果不是特别高的情况下使用RGB_565(565没有透明度属性)

    Android目前常用图片格式

    有png,jpeg和webp

    png:无损压缩图片格式,支持Alpha通道,Android切图素材多采用该格式

    jpeg:有损压缩图片格式,不支持背景透明,适用于照片等色彩丰富的(大图压缩,不适合logo)

    webp:是一种同时提供了有损压缩和无损压缩的图片格式,派生自视频编码格式VP8,从谷歌官网来看,无损webp平均比png小26%,有损的webp平均比jpeg小25%~34%,无损webp支持Alpha通道,有损webp在一定的条件下同样支持,有损webp在Android4.0(API 14)之后支持,无损和透明在Android4.3(API18)之后支持

    使用

    大小压缩

    private Bitmap getimage(String srcPath) {  
            BitmapFactory.Options newOpts = new BitmapFactory.Options();  
            //开始读入图片,此时把options.inJustDecodeBounds 设回true了  
            newOpts.inJustDecodeBounds = true;  
            Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);//此时返回bm为空  
            newOpts.inJustDecodeBounds = false;  
            int w = newOpts.outWidth;  
            int h = newOpts.outHeight;  
            //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为  
            float hh = 800f;//这里设置高度为800f  
            float ww = 480f;//这里设置宽度为480f  
            //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可  
            int be = 1;//be=1表示不缩放  
            if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放  
                be = (int) (newOpts.outWidth / ww);  
            } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放  
                be = (int) (newOpts.outHeight / hh);  
            }  
            if (be <= 0)  
                be = 1;  
            newOpts.inSampleSize = be;//设置缩放比例  
            //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了  
            bitmap = BitmapFactory.decodeFile(srcPath, newOpts);  
            return compressImage(bitmap);//压缩好比例大小后再进行质量压缩  
        }

    质量压缩

    注意:

    第二次压缩之前都要先清空 baos.reset(); 再进行压缩

    image.compress(Bitmap.CompressFormat.JPEG, quality, baos);

    有时候我们采用质量压缩没有效果,有可能是每次压缩的质量过小,所以我们可以尝试修改压缩质量(quality)是10;

    quality压缩机提示,0-100。0表示压缩小尺寸,100意味着最大质量的压缩。一些格式,如无损的PNG,将忽略质量设定;

    private Bitmap compressImage(Bitmap image) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
            int options = 90;
            int length = baos.toByteArray().length / 1024;
            if (length>5000){
                //重置baos即清空baos
                baos.reset();
                //质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
                image.compress(Bitmap.CompressFormat.JPEG, 10, baos);
            }else if (length>4000){
                baos.reset();
                image.compress(Bitmap.CompressFormat.JPEG, 20, baos);
            }else if (length>3000){
                baos.reset();
                image.compress(Bitmap.CompressFormat.JPEG, 50, baos);
            }else if (length>2000){
                baos.reset();
                image.compress(Bitmap.CompressFormat.JPEG, 70, baos);
            }
            //循环判断如果压缩后图片是否大于1M,大于继续压缩
            while (baos.toByteArray().length / 1024>1024) {
                //重置baos即清空baos
                baos.reset();
                //这里压缩options%,把压缩后的数据存放到baos中
                image.compress(Bitmap.CompressFormat.JPEG, options, baos);
                //每次都减少10
                options -= 10;
            }
            //把压缩后的数据baos存放到ByteArrayInputStream中
            ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
            //把ByteArrayInputStream数据生成图片
            Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);
            return bitmap;
        }

    混合方式压缩

    private Bitmap comp(Bitmap image) {  
        ByteArrayOutputStream baos = new ByteArrayOutputStream();         
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);  
        if( baos.toByteArray().length / 1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出    
            baos.reset();//重置baos即清空baos  
            image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//这里压缩50%,把压缩后的数据存放到baos中  
        }  
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());  
        BitmapFactory.Options newOpts = new BitmapFactory.Options();  
        //开始读入图片,此时把options.inJustDecodeBounds 设回true了  
        newOpts.inJustDecodeBounds = true;  
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);  
        newOpts.inJustDecodeBounds = false;  
        int w = newOpts.outWidth;  
        int h = newOpts.outHeight;  
        //现在主流手机比较多是800*480分辨率,所以高和宽我们设置为  
        float hh = 800f;//这里设置高度为800f  
        float ww = 480f;//这里设置宽度为480f  
        //缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可  
        int be = 1;//be=1表示不缩放  
        if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放  
            be = (int) (newOpts.outWidth / ww);  
        } else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放  
            be = (int) (newOpts.outHeight / hh);  
        }  
        if (be <= 0)  
            be = 1;  
        newOpts.inSampleSize = be;//设置缩放比例  
        //重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了  
        isBm = new ByteArrayInputStream(baos.toByteArray());  
        bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);  
        return compressImage(bitmap);//压缩好比例大小后再进行质量压缩  
    }

    采样率压缩

    采样率压缩是通过设置BitmapFactory.Options.inSampleSize,来减小图片的分辨率,进而减小图片所占用的磁盘空间和内存大小。

    设置的inSampleSize会导致压缩的图片的宽高都为1/inSampleSize,整体大小变为原始图片的inSampleSize平方分之一,当然,这些有些注意点:

    • 1、inSampleSize小于等于1会按照1处理

    • 2、inSampleSize只能设置为2的平方,不是2的平方则最终会减小到最近的2的平方数,如设置7会按4进行压缩,设置15会按8进行压缩。

    /**
     * 
     * @param inSampleSize  可以根据需求计算出合理的inSampleSize
     */
    public static void compress(int inSampleSize) {
        File sdFile = Environment.getExternalStorageDirectory();
        File originFile = new File(sdFile, "originImg.jpg");
        BitmapFactory.Options options = new BitmapFactory.Options();
        //设置此参数是仅仅读取图片的宽高到options中,不会将整张图片读到内存中,防止oom
        options.inJustDecodeBounds = true;
        Bitmap emptyBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);
        options.inJustDecodeBounds = false;
        options.inSampleSize = inSampleSize;
        Bitmap resultBitmap = BitmapFactory.decodeFile(originFile.getAbsolutePath(), options);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        resultBitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);
        try {
            FileOutputStream fos = new FileOutputStream(new File(sdFile, "resultImg.jpg"));
            fos.write(bos.toByteArray());
            fos.flush();
            fos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    图片保存到本地

     /**
         * 保存bitmap到本地
         * @param context the context
         * @param mBitmap the m bitmap
         * @return string
         */
        public static String saveBitmap(Context context, Bitmap mBitmap) {
            String savePath;
            File filePic;
            try {
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    savePath = SD_PATH;
                } else {
                    savePath = context.getApplicationContext().getFilesDir().getAbsolutePath() + IN_PATH;
                }
                filePic = new File(savePath + DateTimeHelper.format(new Date(), "yyyyMMddHHmmss") + ".jpg");
                Log.d("LUO", "图片地址====" + filePic);
                if (!filePic.exists()) {
                    filePic.getParentFile().mkdirs();
                    filePic.createNewFile();
                }
                FileOutputStream fos = new FileOutputStream(filePic);
                //不压缩,保存本地
                mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                fos.flush();
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
                return null;
            }
            return filePic.getAbsolutePath();
        }

    到此,相信大家对“Android开发怎么实现图片大小与质量压缩及保存”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI