android使用luban压缩图片

来源:互联网 发布:ubuntu显示隐藏文件 编辑:程序博客网 时间:2024/05/20 18:55

之前写了调用系统相机拍照和本地选择照片,今天我们就来使用luban工具将原图片压缩之后分图片质量依然保持不变的方法,我相信这个方法一定能满足你。本文章讲解的是单选图片,而不是批量添加图片,多选的我没写过。

先看下图:



图片质量没变,而且图片也有原来的2.2M变成256K。

下面是处理的代码:

首先我们先在gradle里面添加使用到的依赖:

compile 'com.github.bumptech.glide:glide:3.7.0'compile 'io.reactivex.rxjava2:rxandroid:2.0.1'compile 'io.reactivex.rxjava2:rxjava:2.1.0'
OK,下面来时撸/撸/撸/码

LuBanActivity代码:
public class LuBanActivity extends AppCompatActivity {    private static final String TAG = "Luban";    private static final int PHOTO_REQUEST_GALLERY = 2;// 从相册中选择    private String imgPath = "";    private TextView fileSize;    private TextView imageSize;    private TextView thumbFileSize;    private TextView thumbImageSize;    private ImageView image;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_lu_ban);        fileSize = (TextView) findViewById(R.id.file_size);        imageSize = (TextView) findViewById(R.id.image_size);        thumbFileSize = (TextView) findViewById(R.id.thumb_file_size);        thumbImageSize = (TextView) findViewById(R.id.thumb_image_size);        image = (ImageView) findViewById(R.id.image);        Button btnPhoto = (Button) findViewById(R.id.btn_photo);        btnPhoto.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                gallery();            }        });    }    //从相册取图片    public void gallery() {        // 激活系统图库,选择一张图片        Intent intent = new Intent(Intent.ACTION_PICK, null);        intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,                "image/*");        startActivityForResult(intent, PHOTO_REQUEST_GALLERY);    }    @Override    protected void onActivityResult(int requestCode, int resultCode, Intent data) {        super.onActivityResult(requestCode, resultCode, data);        if (resultCode == RESULT_OK && requestCode == PHOTO_REQUEST_GALLERY) {//相册            if (data != null) {                Uri uri = data.getData();                /**获取路径**/                String[] proj = {MediaStore.Images.Media.DATA};                Cursor cursor = getContentResolver().query(uri, proj, null, null, null);                if (cursor.moveToFirst()) {                    int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);                    imgPath = cursor.getString(column_index);                }                File file = new File(imgPath);                fileSize.setText(file.length() / 1024 + "k");                imageSize.setText(computeSize(file)[0] + "*" + computeSize(file)[1]);                /**两种方法都可以压缩**///                compressWithRx(file); //Rxjava                compressWithLs(file); //luban            }        }    }    /**     * Rxjava处理     */    private void compressWithRx(File file) {        Flowable.just(file)                .observeOn(Schedulers.io())                .map(new Function<File, File>() {                    @Override public File apply(File file) throws Exception {                        return Luban.with(LuBanActivity.this).load(file).get();                    }                })                .observeOn(AndroidSchedulers.mainThread())                .subscribe(new Consumer<File>() {                    @Override public void accept(File file) throws Exception {                        Log.d(TAG, file.getAbsolutePath());                        Glide.with(LuBanActivity.this).load(file).into(image);                        thumbFileSize.setText(file.length() / 1024 + "k");                        thumbImageSize.setText(computeSize(file)[0] + "*" + computeSize(file)[1]);                    }                });    }    /**     * 压缩单张图片 Listener 方式     * luban处理     */    private void compressWithLs(File file) {        Luban.with(this)                .load(file)                .setCompressListener(new OnCompressListener() {                    @Override                    public void onStart() {                        Toast.makeText(LuBanActivity.this, "I'm start", Toast.LENGTH_SHORT).show();                    }                    @Override                    public void onSuccess(File file) {                        Log.i("path", file.getAbsolutePath());                        Glide.with(LuBanActivity.this).load(file).into(image);                        thumbFileSize.setText(file.length()/ 1024 + "k");                        thumbImageSize.setText(computeSize(file)[0] + "*" + computeSize(file)[1]);                    }                    @Override                    public void onError(Throwable e) {                    }                }).launch();    }    /**获取图片的尺寸**/    private int[] computeSize(File srcImg) {        int[] size = new int[2];        BitmapFactory.Options options = new BitmapFactory.Options();        options.inJustDecodeBounds = true;        options.inSampleSize = 1;        BitmapFactory.decodeFile(srcImg.getAbsolutePath(), options);        size[0] = options.outWidth;        size[1] = options.outHeight;        return size;    }}

xml布局:

<?xml version="1.0" encoding="utf-8"?><LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:fitsSystemWindows="true"  android:orientation="vertical">  <LinearLayout      android:layout_width="match_parent"      android:layout_height="wrap_content"      android:orientation="vertical"      android:padding="16dp">    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="原图参数" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">      <TextView          android:id="@+id/file_size"          android:layout_width="0dp"          android:layout_height="wrap_content"          android:layout_weight="1" />      <TextView          android:id="@+id/image_size"          android:layout_width="0dp"          android:layout_height="wrap_content"          android:layout_weight="1" />    </LinearLayout>    <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:text="压缩后参数" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:orientation="horizontal">      <TextView          android:id="@+id/thumb_file_size"          android:layout_width="0dp"          android:layout_height="wrap_content"          android:layout_weight="1" />      <TextView          android:id="@+id/thumb_image_size"          android:layout_width="0dp"          android:layout_height="wrap_content"          android:layout_weight="1" />    </LinearLayout>    <ImageView        android:id="@+id/image"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:contentDescription="@null"        />      </LinearLayout>  <RelativeLayout    android:layout_width="match_parent"    android:layout_height="match_parent">        <Button      android:id="@+id/btn_photo"      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:layout_alignParentBottom="true"      android:layout_alignParentEnd="true"      android:layout_alignParentRight="true"      android:layout_margin="16dp"      android:text="选择照片"/>  </RelativeLayout></LinearLayout>
工具类:

Luban类
/**luban压缩方法**/public class Luban implements Handler.Callback {  private static final String TAG = "Luban";  private static final String DEFAULT_DISK_CACHE_DIR = "luban_disk_cache";  private static final int MSG_COMPRESS_SUCCESS = 0;  private static final int MSG_COMPRESS_START = 1;  private static final int MSG_COMPRESS_ERROR = 2;  private File file;  private OnCompressListener onCompressListener;  private Handler mHandler;  private Luban(Builder builder) {    this.file = builder.file;    this.onCompressListener = builder.onCompressListener;    mHandler = new Handler(Looper.getMainLooper(), this);  }  public static Builder with(Context context) {    return new Builder(context);  }  /**   * Returns a file with a cache audio name in the private cache directory.   *   * @param context   *     A context.   */  private File getImageCacheFile(Context context) {    if (getImageCacheDir(context) != null) {      return new File(getImageCacheDir(context) + "/" + System.currentTimeMillis() + (int) (Math.random() * 1000) + ".jpg");    }    return null;  }  /**   * Returns a directory with a default name in the private cache directory of the application to   * use to store retrieved audio.   *   * @param context   *     A context.   *   * @see #getImageCacheDir(Context, String)   */  @Nullable  private File getImageCacheDir(Context context) {    return getImageCacheDir(context, DEFAULT_DISK_CACHE_DIR);  }  /**   * Returns a directory with the given name in the private cache directory of the application to   * use to store retrieved media and thumbnails.   *   * @param context   *     A context.   * @param cacheName   *     The name of the subdirectory in which to store the cache.   *   * @see #getImageCacheDir(Context)   */  @Nullable  private File getImageCacheDir(Context context, String cacheName) {    File cacheDir = context.getExternalCacheDir();    if (cacheDir != null) {      File result = new File(cacheDir, cacheName);      if (!result.mkdirs() && (!result.exists() || !result.isDirectory())) {        // File wasn't able to create a directory, or the result exists but not a directory        return null;      }      return result;    }    if (Log.isLoggable(TAG, Log.ERROR)) {      Log.e(TAG, "default disk cache dir is null");    }    return null;  }  /**   * start asynchronous compress thread   */  @UiThread  private void launch(final Context context) {    if (file == null && onCompressListener != null) {      onCompressListener.onError(new NullPointerException("image file cannot be null"));    }    new Thread(new Runnable() {      @Override public void run() {        try {          mHandler.sendMessage(mHandler.obtainMessage(MSG_COMPRESS_START));          File result = new Engine(file, getImageCacheFile(context)).compress();          mHandler.sendMessage(mHandler.obtainMessage(MSG_COMPRESS_SUCCESS, result));        } catch (IOException e) {          mHandler.sendMessage(mHandler.obtainMessage(MSG_COMPRESS_ERROR, e));        }      }    }).start();  }  /**   * start compress and return the file   */  @WorkerThread  private File get(final Context context) throws IOException {    return new Engine(file, getImageCacheFile(context)).compress();  }  @Override public boolean handleMessage(Message msg) {    if (onCompressListener == null) return false;    switch (msg.what) {      case MSG_COMPRESS_START:        onCompressListener.onStart();        break;      case MSG_COMPRESS_SUCCESS:        onCompressListener.onSuccess((File) msg.obj);        break;      case MSG_COMPRESS_ERROR:        onCompressListener.onError((Throwable) msg.obj);        break;    }    return false;  }  public static class Builder {    private Context context;    private File file;    private OnCompressListener onCompressListener;    Builder(Context context) {      this.context = context;    }    private Luban build() {      return new Luban(this);    }    public Builder load(File file) {      this.file = file;      return this;    }    public Builder putGear(int gear) {      return this;    }    public Builder setCompressListener(OnCompressListener listener) {      this.onCompressListener = listener;      return this;    }    public void launch() {      build().launch(context);    }    public File get() throws IOException {      return build().get(context);    }  }}

Engine类
/** * Responsible for starting compress and managing active and cached resources. * 压缩算法思路 */class Engine {  private ExifInterface srcExif;  private File srcImg;  private File tagImg;  private int srcWidth;  private int srcHeight;  Engine(File srcImg, File tagImg) throws IOException {    if (isJpeg(srcImg)) {      this.srcExif = new ExifInterface(srcImg.getAbsolutePath());    }    this.tagImg = tagImg;    this.srcImg = srcImg;    BitmapFactory.Options options = new BitmapFactory.Options();    options.inJustDecodeBounds = true;    options.inSampleSize = 1;    BitmapFactory.decodeFile(srcImg.getAbsolutePath(), options);    this.srcWidth = options.outWidth;    this.srcHeight = options.outHeight;  }  private boolean isJpeg(File photo) {    return photo.getAbsolutePath().contains("jpeg") || photo.getAbsolutePath().contains("jpg");  }  private int computeSize() {    int mSampleSize;    srcWidth = srcWidth % 2 == 1 ? srcWidth + 1 : srcWidth;//临时宽,将宽变作偶数    srcHeight = srcHeight % 2 == 1 ? srcHeight + 1 : srcHeight;//临时高,将高变作偶数    srcWidth = srcWidth > srcHeight ? srcHeight : srcWidth;//将小的一边给width,最短边    srcHeight = srcWidth > srcHeight ? srcWidth : srcHeight;//将大的一边给height,最长边    double scale = ((double) srcWidth / srcHeight);//比例,图片短边除以长边为该图片比例    if (scale <= 1 && scale > 0.5625) {      //判断最长边是否过界      if (srcHeight < 1664) {//最长边小于1664px        mSampleSize = 1;      } else if (srcHeight >= 1664 && srcHeight < 4990) {        mSampleSize = 2;      } else if (srcHeight >= 4990 && srcHeight < 10240) {        mSampleSize = 4;      } else {        mSampleSize = srcHeight / 1280 == 0 ? 1 : srcHeight / 1280;      }    } else if (scale <= 0.5625 && scale > 0.5) {//比例在[0.5625,00.5)区间      mSampleSize = srcHeight / 1280 == 0 ? 1 : srcHeight / 1280;    } else {//比例小于0.5      mSampleSize = (int) Math.ceil(srcHeight / (1280.0 / scale));    }    return mSampleSize;  }  private Bitmap rotatingImage(Bitmap bitmap) {    if (srcExif == null) return bitmap;    Matrix matrix = new Matrix();    int angle = 0;    int orientation = srcExif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);    switch (orientation) {      case ExifInterface.ORIENTATION_ROTATE_90:        angle = 90;        break;      case ExifInterface.ORIENTATION_ROTATE_180:        angle = 180;        break;      case ExifInterface.ORIENTATION_ROTATE_270:        angle = 270;        break;    }    matrix.postRotate(angle);    return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);  }  File compress() throws IOException {    BitmapFactory.Options options = new BitmapFactory.Options();    options.inSampleSize = computeSize();    Bitmap tagBitmap = BitmapFactory.decodeFile(srcImg.getAbsolutePath(), options);    ByteArrayOutputStream stream = new ByteArrayOutputStream();    tagBitmap = rotatingImage(tagBitmap);    tagBitmap.compress(Bitmap.CompressFormat.JPEG, 50, stream);    tagBitmap.recycle();    FileOutputStream fos = new FileOutputStream(tagImg);    fos.write(stream.toByteArray());    fos.flush();    fos.close();    stream.close();    return tagImg;  }}
OnCompressListener接口实现
public interface OnCompressListener {  /**   * Fired when the compression is started, override to handle in your own code   * //压缩开始前   */  void onStart();  /**   * Fired when a compression returns successfully, override to handle in your own code   * 压缩成功后   */  void onSuccess(File file);  /**   * Fired when a compression fails to complete, override to handle in your own code   * //压缩失败   */  void onError(Throwable e);}
OK,以上就是完整的代码。当然了,imageview的属性大家可以自己设置,别忘了添加scaleType属性
我试用的是。  android:scaleType="centerCrop"

scaleType属性大家都知道,不了解的可以百度下。


多说一句话:需要阿胶糕的可以  + 微信18703691242
阅读全文
1 0
原创粉丝点击