安卓原生代码实现图片压缩框架

来源:互联网 发布:路由数据割接涉及 编辑:程序博客网 时间:2024/06/16 15:40

使用NDK 哈夫曼算法压缩图片请看我相关文章。今天发表的是使用android.bitmap实现。

package com.zhiweism.youerplatformparent.utils;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import com.zhiweism.youerplatformparent.R;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.os.Environment;public class FileUtils {public static File inputstreamToFile(InputStream ins,File file)throws Exception{OutputStream os = new FileOutputStream(file);int bytesRead = 0;byte[] buffer = new byte[8192];while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {os.write(buffer, 0, bytesRead);}os.close();ins.close();return file;}/**      * @param path      * @return      * @throws IOException      * 压缩图片      */      public static Bitmap revitionImageSize(String path) throws IOException {          //根据文件路径,创建一个字节缓冲输入流          BufferedInputStream in = new BufferedInputStream(new FileInputStream(new File(path)));          BitmapFactory.Options options = new BitmapFactory.Options();          options.inJustDecodeBounds = true;          //根据流返回一个位图也就是bitmap,当options.inJustDecodeBounds = true的时候不需要完全解码,          // 它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM了          BitmapFactory.decodeStream(in, null, options);          //关闭流          in.close();          int i = 0;          Bitmap bitmap = null;          while (true) {              // options.outWidth >> i 。右移运算符,num >> 1,相当于num除以2              if ((options.outWidth >> i <= 1000) && (options.outHeight >> i <= 1000)) {                  //得到一个输入流                  in = new BufferedInputStream(new FileInputStream(new File(path)));                  //为了解决图片解码时候出现SanpleSize错误,设置恰当的inSampleSize可以使BitmapFactory分配更少的空间以消除该错误                  //你将 inSampleSize 赋值为2,那就是每隔2行采1行,每隔2列采一列,那你解析出的图片就是原图大小的1/4.                  // Math.pow(2.0D, i)次方运算,2的i次方是多少                  options.inSampleSize = (int) Math.pow(2.0D, i);                  // 这里之前设置为了true,所以要改为false,否则就创建不出图片                  options.inJustDecodeBounds = false;                  bitmap = BitmapFactory.decodeStream(in, null, options);                  break;              }              i += 1;          }          return bitmap;      }        public static Bitmap revitionImageSize(File path) throws IOException {          //根据文件路径,创建一个字节缓冲输入流          BufferedInputStream in = new BufferedInputStream(new FileInputStream(path));          BitmapFactory.Options options = new BitmapFactory.Options();          options.inJustDecodeBounds = true;          //根据流返回一个位图也就是bitmap,当options.inJustDecodeBounds = true的时候不需要完全解码,          // 它仅仅会把它的宽,高取回来给你,这样就不会占用太多的内存,也就不会那么频繁的发生OOM了          BitmapFactory.decodeStream(in, null, options);          //关闭流          in.close();          int i = 0;          Bitmap bitmap = null;          while (true) {              // options.outWidth >> i 。右移运算符,num >> 1,相当于num除以2              if ((options.outWidth >> i <= 1000) && (options.outHeight >> i <= 1000)) {                  //得到一个输入流                  in = new BufferedInputStream(new FileInputStream(path));                  //为了解决图片解码时候出现SanpleSize错误,设置恰当的inSampleSize可以使BitmapFactory分配更少的空间以消除该错误                  //你将 inSampleSize 赋值为2,那就是每隔2行采1行,每隔2列采一列,那你解析出的图片就是原图大小的1/4.                  // Math.pow(2.0D, i)次方运算,2的i次方是多少                  options.inSampleSize = (int) Math.pow(2.0D, i);                  // 这里之前设置为了true,所以要改为false,否则就创建不出图片                  options.inJustDecodeBounds = false;                  bitmap = BitmapFactory.decodeStream(in, null, options);                  break;              }              i += 1;          }          return bitmap;      }        /**      * @param bitmap      * 保存图片到SD卡的方法      */      public static File saveBitmapFile(Context context,Bitmap bitmap,String fileName){          //Environment.getExternalStorageDirectory() 获取Android外部存储的空间,当有外部SD卡就在外部SD卡上建立。          //没有外部SD卡就在内部SD卡的非data/data/目录建立目录。(data/data/目录才是真正的内存目录。)          //IMAGE_NAME文件的名字,随便起。比如(xxx.jpg)      File dir = new File(Environment.getExternalStorageDirectory() + File.separator + context.getString(R.string.app_path) + File.separator + "friends_image"); if(!dir.exists())dir.mkdirs();File tempFile = new File(dir, fileName);        try {            //创建一个输出流,将数据写入到创建的文件对象中.            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempFile));              ////30 是压缩率,表示压缩70%; 如果不压缩是100,             bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bos);           /* 为什么要调用flush()方法?当FileOutputStream作为BufferedOutputStream构造函数的参数传入,然后对BufferedOutputStream进行写入操作,才能利用缓冲及flush()。             查看BufferedOutputStream的源代码,发现所谓的buffer其实就是一个byte[]。             BufferedOutputStream的每一次write其实是将内容写入byte[],当buffer容量到达上限时,会触发真正的磁盘写入。             而另一种触发磁盘写入的办法就是调用flush()了。*/              bos.flush();              //关闭流对象              bos.close();              return tempFile;        } catch (IOException e) {              e.printStackTrace();              return null;        }      } }


0 0