Android图片 压缩总结

原创 2015年07月08日 11:37:23

一.图片的存在形式

1.文件形式(即以二进制形式存在于硬盘上)
2.流的形式(即以二进制形式存在于内存中)
3.Bitmap形式
这三种形式的区别: 文件形式和流的形式对图片体积大小并没有影响,也就是说,如果你手机SD卡上的如果是100K,那么通过流的形式读到内存中,也一定是占100K的内存,注意是流的形式,不是Bitmap的形式,当图片以Bitmap的形式存在时,其占用的内存会瞬间变大, 我试过500K文件形式的图片加载到内存,以Bitmap形式存在时,占用内存将近10M,当然这个增大的倍数并不是固定的

检测图片三种形式大小的方法:
文件形式: file.length()
流的形式: 讲图片文件读到内存输入流中,看它的byte数
Bitmap:    bitmap.getByteCount()

二.常见的压缩方式

1.质量压缩方法 
   将图片保存到本地时进行压缩, 即将图片从Bitmap形式变为File形式时进行压缩
   特点是:  File形式的图片确实被压缩了, 但是当你重新读取压缩后的file为 Bitmap是,它占用的内存并没有改变
public static void compressBmpToFile(Bitmap bmp,File file){
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		int options = 80;//个人喜欢从80开始,
		bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
		while (baos.toByteArray().length / 1024 > 100) { 
			baos.reset();
			options -= 10;
			bmp.compress(Bitmap.CompressFormat.JPEG, options, baos);
		}
		try {
			FileOutputStream fos = new FileOutputStream(file);
			fos.write(baos.toByteArray());
			fos.flush();
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

方法说明: 该方法是压缩图片的质量, 注意它不会减少图片的像素,比方说, 你的图片是300K的, 1280*700像素的, 经过该方法压缩后, File形式的图片是在100以下, 以方便上传服务器, 但是你BitmapFactory.decodeFile到内存中,变成Bitmap时,它的像素仍然是1280*700, 计算图片像素的方法是 bitmap.getWidth()和bitmap.getHeight(), 图片是由像素组成的, 每个像素又包含什么呢? 熟悉PS的人知道, 图片是有色相,明度和饱和度构成的. 

该方法的官方文档也解释说, 它会让图片重新构造, 但是有可能图像的位深(即色深)和每个像素的透明度会变化,JPEG onlysupports opaque(不透明), 也就是说以jpeg格式压缩后, 原来图片中透明的元素将消失.所以这种格式很可能造成失真

既然它是改变了图片的显示质量, 达到了对File形式的图片进行压缩, 图片的像素没有改变的话, 那重新读取经过压缩的file为Bitmap时, 它占用的内存并不会少.(不相信的可以试试)

因为: bitmap.getByteCount() 是计算它的像素所占用的内存, 请看官方解释: Returns the number of bytes used to store this bitmap's pixels.

2.图片按比例大小压缩方法(根据路径获取图片并压缩)
// 根据路径获得图片并压缩,返回bitmap用于显示
public static Bitmap getSmallBitmap(String filePath) {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(filePath, options);

        // Calculate inSampleSize
    options.inSampleSize = calculateInSampleSize(options, 480, 800);

        // Decode bitmap with inSampleSize set
    options.inJustDecodeBounds = false;

    return BitmapFactory.decodeFile(filePath, options);
    }

//计算图片的缩放值
public static int calculateInSampleSize(BitmapFactory.Options options,int reqWidth, int reqHeight) {
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;

    if (height > reqHeight || width > reqWidth) {
             final int heightRatio = Math.round((float) height/ (float) reqHeight);
             final int widthRatio = Math.round((float) width / (float) reqWidth);
             inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
    }
        return inSampleSize;
}



//把bitmap转换成String
public static String bitmapToString(String filePath) {

        Bitmap bm = getSmallBitmap(filePath);
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        bm.compress(Bitmap.CompressFormat.JPEG, 40, baos);
        byte[] b = baos.toByteArray();
        return Base64.encodeToString(b, Base64.DEFAULT);
    }

public static void saveCompressBitmap(String fileName, Bitmap mBitmap) {
		File f = new File(fileName);
		try {
			f.createNewFile();
		} catch (IOException e) {
			// TODO Auto-generated catch block
		}
		FileOutputStream fOut = null;
		try {
			fOut = new FileOutputStream(f);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		mBitmap.compress(Bitmap.CompressFormat.JPEG, 98, fOut);
		try {
			fOut.flush();
		} catch (IOException e) {
			e.printStackTrace();
		}
		try {
			fOut.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

/*
压缩图片,处理某些手机拍照角度旋转的问题
*/
public static String compressImage(Context context,String filePath,String fileName,int q) throws FileNotFoundException {
        Bitmap bm = getSmallBitmap(filePath);
        int degree = readPictureDegree(filePath);

        if(degree!=0){//旋转照片角度
            bm=rotateBitmap(bm,degree);
        }

        File imageDir = SDCardUtils.getImageDir(context);

        File outputFile=new File(imageDir,fileName);

        FileOutputStream out = new FileOutputStream(outputFile);

        bm.compress(Bitmap.CompressFormat.JPEG, q, out);

        return outputFile.getPath();
    }

public static int readPictureDegree(String path) {
        int degree = 0;
        try {
            ExifInterface exifInterface = new ExifInterface(path);
            int orientation = exifInterface.getAttributeInt(
                    ExifInterface.TAG_ORIENTATION,
                    ExifInterface.ORIENTATION_NORMAL);
            switch (orientation) {
            case ExifInterface.ORIENTATION_ROTATE_90:
                degree = 90;
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                degree = 180;
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                degree = 270;
                break;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return degree;
    }

public static Bitmap rotateBitmap(Bitmap bitmap,int degress) {
        if (bitmap != null) {
            Matrix m = new Matrix();
            m.postRotate(degress); 
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),
                    bitmap.getHeight(), m, true);
            return bitmap;
        }
        return bitmap;
    }


3.图片按比例大小压缩方法(根据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);//压缩好比例大小后再进行质量压缩
	}


Android 图片选取压缩上传功能需要注意的

## 概述 在个人中心得图片选择上传功能的时候,一般为了节省流量和保证上传的成功率,都会选择压缩上传.其中涉及到了如下一些注意事项. ## 一. 图片压缩 android 系统的图片压缩大体上有...
  • wbwjx
  • wbwjx
  • 2016年04月07日 07:56
  • 881

Android图片压缩Bitmap,Drawable

今天做的图片压缩,差点把宝宝难死。。。。主要是因为各种马虎。。不过最终还是成功了。 下面做的不知道是哪位大神的原创了,因为打开了若干个页面,所有如果冒犯到了,与我联系,我会做出相应处理。 应用场景:公...
  • zhangzhangliyin
  • zhangzhangliyin
  • 2016年08月30日 23:27
  • 1055

Android图片压缩(质量压缩和尺寸压缩)、图片保存(本地和sqlite数据库)

Android图片压缩(质量压缩和尺寸压缩) 在做项目中遇到一个头疼的问题,读取本地图片时,由于图片太大,奔溃,对于我这种456M内存的破手机哪里受得了几M的照片 我要总结的有这么几点: ...
  • Junp_Lee
  • Junp_Lee
  • 2015年09月21日 14:58
  • 710

Android选取相册中的图片并对其进行压缩

Android选取相册中的图片并对其进行压缩    现在手机中相机的像素越来越高因,手机照的相片就越来越来大, 我们想通过选择相册中图片来显示在界面中,或者进行分享. 因为图片太大的原因很容易造成手机...
  • qq_23179075
  • qq_23179075
  • 2016年08月20日 15:17
  • 1412

Android 图片先gzip压缩然后在Base64转成字符串

图片用gzip解压,然后转为Base64 public static String pngToString(File f1, File f2) throws Exception {//第一个File是...
  • Dr_abandon
  • Dr_abandon
  • 2017年09月05日 09:30
  • 250

android实现一张或多张图片压缩并保持清晰上传

图片过大,大于1M的情况下上传服务器会很耗时,因此要实现压缩上传并且不失真 String mCurrentPhotoPath; Intent openCameraIntent = ne...
  • qq_34546643
  • qq_34546643
  • 2016年06月28日 12:07
  • 3066

安卓图片的压缩,尺寸,质量,采样率和微信压缩

图片压缩:分为质量压缩,尺寸压缩,采样率压缩,微信压缩(哈夫曼编码)(都不是重点,重点是第四种) 质量压缩:设置bitmap options属性,降低图片的质量,像素不会减少 尺寸压缩:通过缩放像素减...
  • maqianli23
  • maqianli23
  • 2017年01月02日 17:45
  • 2294

Android图片使用采样率压缩

package com.shuaijie.jiang.zuoye.utils; import android.content.Context; import android.graphic...
  • codeteenager
  • codeteenager
  • 2016年09月24日 15:23
  • 151

Android对图片常用(拍照,图库,拖拉,压缩上传)操作

本篇博客内容: 1 .android app拍照功能 2. 部分手机上拍照图片旋转问题 3. android图库获取图片功能 4. 查看图片,进行缩放,拖拉功能 5. 压缩图片,上传功能...
  • hexingen
  • hexingen
  • 2016年11月13日 21:47
  • 833

Android中的图片按比例大小压缩代码

/** * 图片按比例大小压缩(用于二维码) * * @param path * @return */ public static Bitmap getDecordeImage...
  • stop_pig
  • stop_pig
  • 2014年06月30日 20:44
  • 2818
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android图片 压缩总结
举报原因:
原因补充:

(最多只允许输入30个字)