package cc.util.android.image;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.util.Log; /**
* A class for helping deal the bitmap,
* like: get the orientation of the bitmap, compress bitmap etc.
* @author wangcccong
* @version 1.140122
* crated at: 2014-03-22
* update at: 2014-06-26
*/
public class BitmapHelper { /**
* get the orientation of the bitmap {@link android.media.ExifInterface}
* @param path
* @return
*/
public final static int getDegress(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;
} /**
* rotate the bitmap
* @param bitmap
* @param degress
* @return
*/
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;
} /**
* caculate the bitmap sampleSize
* @param path
* @return
*/
public final static int caculateInSampleSize(BitmapFactory.Options options, int rqsW, int rqsH) {
final int height = options.outHeight;
final int width = options.outWidth;
int inSampleSize = 1;
if (rqsW == 0 || rqsH == 0) return 1;
if (height > rqsH || width > rqsW) {
final int heightRatio = Math.round((float) height/ (float) rqsH);
final int widthRatio = Math.round((float) width / (float) rqsW);
inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio;
}
return inSampleSize;
} /**
* 压缩指定路径的图片,并得到图片对象
* @param context
* @param path bitmap source path
* @return Bitmap {@link android.graphics.Bitmap}
*/
public final static Bitmap compressBitmap(String path, int rqsW, int rqsH) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(path, options);
options.inSampleSize = caculateInSampleSize(options, rqsW, rqsH);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeFile(path, options);
} /**
* 压缩指定路径图片,并将其保存在缓存目录中,通过isDelSrc判定是否删除源文件,并获取到缓存后的图片路径
* @param context
* @param srcPath
* @param rqsW
* @param rqsH
* @param isDelSrc
* @return
*/
public final static String compressBitmap(Context context, String srcPath, int rqsW, int rqsH, boolean isDelSrc) {
Bitmap bitmap = compressBitmap(srcPath, rqsW, rqsH);
File srcFile = new File(srcPath);
String desPath = getImageCacheDir(context) + srcFile.getName();
int degree = getDegress(srcPath);
try {
if (degree != 0) bitmap = rotateBitmap(bitmap, degree);
File file = new File(desPath);
FileOutputStream fos = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.PNG, 70, fos);
fos.close();
if (isDelSrc) srcFile.deleteOnExit();
} catch (Exception e) {
// TODO: handle exception
Log.e("BitmapHelper-->compressBitmap", e.getMessage()+"");
}
return desPath;
} /**
* 此方法过期,该方法可能造成OutOfMemoryError,使用不含isAdjust参数的方法
* @param is
* @param reqsW
* @param reqsH
* @param isAdjust
* @return
*/
@Deprecated
public final static Bitmap compressBitmap(InputStream is, int reqsW, int reqsH, boolean isAdjust) {
Bitmap bitmap = BitmapFactory.decodeStream(is);
return compressBitmap(bitmap, reqsW, reqsH, isAdjust);
} /**
* 压缩某个输入流中的图片,可以解决网络输入流压缩问题,并得到图片对象
* @param context
* @param path bitmap source path
* @return Bitmap {@link android.graphics.Bitmap}
*/
public final static Bitmap compressBitmap(InputStream is, int reqsW, int reqsH) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ReadableByteChannel channel = Channels.newChannel(is);
ByteBuffer buffer = ByteBuffer.allocate(1024);
while (channel.read(buffer) != -1) {
buffer.flip();
while (buffer.hasRemaining()) baos.write(buffer.get());
buffer.clear();
}
byte[] bts = baos.toByteArray();
Bitmap bitmap = compressBitmap(bts, reqsW, reqsH);
is.close();
channel.close();
baos.close();
return bitmap;
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
return null;
}
} /**
* 压缩指定byte[]图片,并得到压缩后的图像
* @param bts
* @param reqsW
* @param reqsH
* @return
*/
public final static Bitmap compressBitmap(byte[] bts, int reqsW, int reqsH) {
final Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeByteArray(bts, 0, bts.length, options);
options.inSampleSize = caculateInSampleSize(options, reqsW, reqsH);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeByteArray(bts, 0, bts.length, options);
} /**
* 此方法已过期,该方法可能造成OutOfMemoryError,使用不含isAdjust参数的方法
* @param bitmap
* @param reqsW
* @param reqsH
* @return
*/
@Deprecated
public final static Bitmap compressBitmap(Bitmap bitmap, int reqsW, int reqsH, boolean isAdjust) {
if (bitmap == null || reqsW == 0 || reqsH == 0) return bitmap;
if (bitmap.getWidth() > reqsW || bitmap.getHeight() > reqsH) {
float scaleX = new BigDecimal(reqsW).divide(new BigDecimal(bitmap.getWidth()), 4, RoundingMode.DOWN).floatValue();
float scaleY = new BigDecimal(reqsH).divide(new BigDecimal(bitmap.getHeight()), 4, RoundingMode.DOWN).floatValue();
if (isAdjust) {
scaleX = scaleX < scaleY ? scaleX : scaleY;
scaleY = scaleX;
}
Matrix matrix = new Matrix();
matrix.postScale(scaleX, scaleY);
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
}
return bitmap;
} /**
* 压缩已存在的图片对象,并返回压缩后的图片
* @param bitmap
* @param reqsW
* @param reqsH
* @return
*/
public final static Bitmap compressBitmap(Bitmap bitmap, int reqsW, int reqsH) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 100, baos);
byte[] bts = baos.toByteArray();
Bitmap res = compressBitmap(bts, reqsW, reqsH);
baos.close();
return res;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return bitmap;
}
} /**
* 此方法过期,该方法可能造成OutOfMemoryError,使用不含isAdjust参数的方法
* get bitmap form resource dictory, and then compress bitmap according to reqsW and reqsH
* @param res {@link android.content.res.Resources}
* @param resID
* @param reqsW
* @param reqsH
* @return
*/
@Deprecated
public final static Bitmap compressBitmap(Resources res, int resID, int reqsW, int reqsH, boolean isAdjust) {
Bitmap bitmap = BitmapFactory.decodeResource(res, resID);
return compressBitmap(bitmap, reqsW, reqsH, isAdjust);
} /**
* 压缩资源图片,并返回图片对象
* @param res {@link android.content.res.Resources}
* @param resID
* @param reqsW
* @param reqsH
* @return
*/
public final static Bitmap compressBitmap(Resources res, int resID, int reqsW, int reqsH) {
final Options options = new Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resID, options);
options.inSampleSize = caculateInSampleSize(options, reqsW, reqsH);
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resID, options);
} /**
* 基于质量的压缩算法, 此方法未 解决压缩后图像失真问题
* <br> 可先调用比例压缩适当压缩图片后,再调用此方法可解决上述问题
* @param bts
* @param maxBytes 压缩后的图像最大大小 单位为byte
* @return
*/
public final static Bitmap compressBitmap(Bitmap bitmap, long maxBytes) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.PNG, 100, baos);
int options = 90;
while (baos.toByteArray().length > maxBytes) {
baos.reset();
bitmap.compress(CompressFormat.PNG, options, baos);
options -= 10;
}
byte[] bts = baos.toByteArray();
Bitmap bmp = BitmapFactory.decodeByteArray(bts, 0, bts.length);
baos.close();
return bmp;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return null;
}
} // public final static Bitmap compressBitmap(InputStream is, long maxBytes) {
// try {
// ByteArrayOutputStream baos = new ByteArrayOutputStream();
// byte[] bts = new byte[1024];
// while (is.read(bts) != -1) baos.write(bts, 0, bts.length);
// is.close();
// int options = 100;
// while (baos.toByteArray().length > maxBytes) {
//
// }
// } catch (Exception e) {
// // TODO: handle exception
// }
// } /**
* 得到指定路径图片的options
* @param srcPath
* @return Options {@link android.graphics.BitmapFactory.Options}
*/
public final static Options getBitmapOptions(String srcPath) {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(srcPath, options);
return options;
} /**
* 获取图片缓存路径
* @param context
* @return
*/
private static String getImageCacheDir(Context context) {
String dir = FileHelper.getCacheDir(context) + "Image" + File.separator;
File file = new File(dir);
if (!file.exists()) file.mkdirs();
return dir;
}
}

Android 图片压缩,基于比例和质量压缩的更多相关文章

  1. Android中图片压缩(质量压缩和尺寸压缩)

    关于Android 图片压缩的学习: 自己总结分为质量压缩和像素压缩.质量压缩即:将Bitmap对象保存到对应路径下是所占用的内存减小,但是当你重新读取压缩后的file为Bitmap时,它所占用的内存 ...

  2. Golang 编写的图片压缩程序,质量、尺寸压缩,批量、单张压缩

    目录: 前序 效果图 简介 全部代码 前序: 接触 golang 不久,一直是边学边做,边总结,深深感到这门语言的魅力,等下要跟大家分享是最近项目 服务端 用到的图片压缩程序,我单独分离了出来,做成了 ...

  3. Android图片压缩方法总结

    本文总结Android应用开发中三种常见的图片压缩方法,分别是:质量压缩法.比例压缩法(根据路径获取图片并压缩)和比例压缩法(根据Bitmap图片压缩).   第一:质量压缩方法:   ? 1 2 3 ...

  4. android图片压缩方法

    android 图片压缩方法: 第一:质量压缩法: private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = ...

  5. android图片压缩的3种方法实例

    android 图片压缩方法: 第一:质量压缩法: private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = ...

  6. 性能优化——Android图片压缩与优化的几种方式

    图片优化压缩方式大概可以分为以下几类:更换图片格式,质量压缩,采样率压缩,缩放压缩,调用jpeg压缩等1.设置图片格式Android目前常用的图片格式有png,jpeg和webp,png:无损压缩图片 ...

  7. android图片压缩总结

    一.bitmap 图片格式介绍 android中图片是以bitmap形式存在的,那么bitmap所占内存,直接影响到了应用所占内存大小,首先要知道bitmap所占内存大小计算方式: bitmap内存大 ...

  8. Android 图片压缩各种方式

       前言:由于公司项目当中需要用到压缩这块的相应技术,之前也做过的图片压缩都不是特别的理想, 所以这次花了很多心思,仔细研究和在网上找到了很多相对应的资料.为了就是 以后再做的时候直接拿来用就可以了 ...

  9. 利用反射快速给Model实体赋值 使用 Task 简化异步编程 Guid ToString 格式知多少?(GUID 格式) Parallel Programming-实现并行操作的流水线(生产者、消费者) c# 无损高质量压缩图片代码 8种主要排序算法的C#实现 (一) 8种主要排序算法的C#实现 (二)

    试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...

随机推荐

  1. 如何通过使用fiddler对Android系统设备抓包总结

    http://www.open-open.com/lib/view/open1427509907668.html

  2. CODEVS——T3008 加工生产调度

    http://codevs.cn/problem/3008/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 黄金 Gold 题解  查看运行结果     题目描述 Descr ...

  3. UVA 11346 Probability (几何概型, 积分)

    题目链接:option=com_onlinejudge&Itemid=8&page=show_problem&problem=2321">https://uva ...

  4. 深入理解javascript之原型

    理解原型 原型是一个对象.其它对象能够通过它实现属性继承. 不论什么一个对象都能够成为继承,全部对象在默认的情况下都有一个原型.由于原型本身也是对象,所以每一个原型自身又有一个原型. 不论什么一个对象 ...

  5. php实现希尔排序(总结)

    php实现希尔排序(总结) 一.总结 1.希尔排序的算法思路:分组排序, 缩小增量排序,插入排序 2.算法思路: 循环非常好写 有几次gap:log2(n) 每次gap有几组:gap组 每组有几个元素 ...

  6. 动态库dll使用module.def文件导出函数(像静态库一样使用)

    1.新建文件module.def. 2.动态库工程上右键->属性->链接器->输入->模块定义文件编辑它写入module.def 3.下面为module.def实例(smart ...

  7. ubuntu14.04.32 vmware11开发环境搭建

    win7 64  vmware11 ubuntu14.04.32 在vmaware上安装ubuntu,自定义安装,选择区域为上海,这样数据源就会自动设置为中国,获取网络数据会较快,也可以安装完之后改变 ...

  8. Javascript 继承和克隆

    个人总结: call 继承的是父类私有 prototype 继承的父类公有 create 可以将公有或私有继承到子类上去(克隆) for in 克隆 不管公有还是私有的都克隆成私有的 1.原型继承:将 ...

  9. vuex-store模块化配置

    一.目录结构: src -> js -> modules 1. 在modules下新建文件夹,文件夹名称按模块功能命名 如: modules ---- home -> homeMod ...

  10. BZOJ1576: [Usaco2009 Jan]安全路经Travel(树链剖分)

    Description Input * 第一行: 两个空格分开的数, N和M * 第2..M+1行: 三个空格分开的数a_i, b_i,和t_i Output * 第1..N-1行: 第i行包含一个数 ...