图片压缩
来源:互联网 发布:snh48 成员家境 知乎 编辑:程序博客网 时间:2024/04/28 16:56
1. 获取原图片尺寸
通常,我们使用BitmapFactory.decodeResource()方法来从资源文件中读取一张图片并生成一个Bitmap。通过BitmapFactory.Options类类指定解码方法。在解码图片的时候设置inJustDecodeBounds属性设置为true,可以避免内存分配,decodeResource()方法就不会生成Bitmap对象,而仅仅是读取该图片的尺寸和类型信息:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//true即只读边不读内容
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
为了避免java.lang.OutOfMemeory异常,在解码图片之前就要检查图片的尺寸,除非你十分确信图片资源的尺寸是可预见的并且有着充裕的可用内存。
2. 根据原图尺寸和目标区域的尺寸计算出合适的Bitmap尺寸
BitmapFactory.Options类有一个参数inSampleSize,该参数为int型,他的值指示了在解析图片为Bitmap时在长宽两个方向上像素缩小的倍数。inSampleSize的默认值和最小值为1(当小于1时,解码器将该值当做1来处理),且在大于1时,该值只能为2的幂(当不为2的幂时,解码器会取与该值最接近的2的幂)。例如,当inSampleSize为2时,一个2000*1000的图片,将被缩小为1000*500,相应地,它的像素数和内存占用都被缩小为了原来的1/4:
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 halfHeight = height / 2;
final int halfWidth = width / 2;
// 在保证解析出的bitmap宽高分别大于目标尺寸宽高的前提下,取可能的inSampleSize的最大值
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
//高度和宽度都按照此比例进行压缩
return inSampleSize;
}
3.根据计算出的inSampleSize生成Bitmap
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// //加载图片的边界信息(只读取图片的高度,宽度,不读取具体字节)
final BitmapFactory.Options options = new BitmapFactory.Options();
//将此选项设置true,此时再加载图片就会只读取图片边界信息了
options.inJustDecodeBounds = true;
//加载图片边界,并将边界信息封装到options对象
BitmapFactory.decodeResource(res, resId, options);
// 计算 inSampleSize 的
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 根据计算出的 inSampleSize 来解码图片生成Bitmap
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
这里有一点要注意,就是要在第二遍decode之前把inJustDecodeBounds设置回false。
4. 调用以上的decodeSampledBitmapFromResource方法,使用自定尺寸的Bitmap。
如果你要将一张大图设置为一个100*100的缩略图,执行以下代码:
mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
到此,使用decodeResource()方法将一个大图解析为小尺寸bitmap的应用就完成了。同理,还可以使用decodeStream(),decodeFile()等方法做相同的事,原理是一样的
延伸:一个Bitmap到底占用多大内存?系统给每个应用程序分配多大内存?
· Bitmap占用的内存为:像素总数 * 每个像素占用的内存。在Android中,Bitmap有四种像素类型:ARGB_8888、ARGB_4444、ARGB_565、ALPHA_8,他们每个像素占用的字节数分别为4、2、2、1。因此,一个2000*1000的ARGB_8888类型的Bitmap占用的内存为2000*1000*4=8000000B=8MB。
· Android根据设备屏幕尺寸和dpi的不同,给系统分配的单应用程序内存大小也不同,具体如下表(表格取自Android 4.4 Compatibility Definition Document (CDD)):
2)图片在工作线程加载
在工作线程加载并压缩图片:记住:以后在activity写内部类时,内部类又是一个线程对象,请尽量使用静态内部类
继承AsyncTask,利用弱引用,引用外部类的中的属性imageView
在doInBackground 返回值为使用decodeResource()方法,将一个大图解析为小尺寸bitmap的应用
onPostExecute用if判断弱引用与(bitmap)result是否为空如果为空返回,不为空则提取imageview,再用if语句imageview判断是否为空,如果不为空则将bitmap写进imageview
通常,我们使用BitmapFactory.decodeResource()方法来从资源文件中读取一张图片并生成一个Bitmap。通过BitmapFactory.Options类类指定解码方法。在解码图片的时候设置inJustDecodeBounds属性设置为true,可以避免内存分配,decodeResource()方法就不会生成Bitmap对象,而仅仅是读取该图片的尺寸和类型信息:
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;//true即只读边不读内容
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;
为了避免java.lang.OutOfMemeory异常,在解码图片之前就要检查图片的尺寸,除非你十分确信图片资源的尺寸是可预见的并且有着充裕的可用内存。
2. 根据原图尺寸和目标区域的尺寸计算出合适的Bitmap尺寸
BitmapFactory.Options类有一个参数inSampleSize,该参数为int型,他的值指示了在解析图片为Bitmap时在长宽两个方向上像素缩小的倍数。inSampleSize的默认值和最小值为1(当小于1时,解码器将该值当做1来处理),且在大于1时,该值只能为2的幂(当不为2的幂时,解码器会取与该值最接近的2的幂)。例如,当inSampleSize为2时,一个2000*1000的图片,将被缩小为1000*500,相应地,它的像素数和内存占用都被缩小为了原来的1/4:
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 halfHeight = height / 2;
final int halfWidth = width / 2;
// 在保证解析出的bitmap宽高分别大于目标尺寸宽高的前提下,取可能的inSampleSize的最大值
while ((halfHeight / inSampleSize) > reqHeight
&& (halfWidth / inSampleSize) > reqWidth) {
inSampleSize *= 2;
}
}
//高度和宽度都按照此比例进行压缩
return inSampleSize;
}
3.根据计算出的inSampleSize生成Bitmap
public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
int reqWidth, int reqHeight) {
// //加载图片的边界信息(只读取图片的高度,宽度,不读取具体字节)
final BitmapFactory.Options options = new BitmapFactory.Options();
//将此选项设置true,此时再加载图片就会只读取图片边界信息了
options.inJustDecodeBounds = true;
//加载图片边界,并将边界信息封装到options对象
BitmapFactory.decodeResource(res, resId, options);
// 计算 inSampleSize 的
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// 根据计算出的 inSampleSize 来解码图片生成Bitmap
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
这里有一点要注意,就是要在第二遍decode之前把inJustDecodeBounds设置回false。
4. 调用以上的decodeSampledBitmapFromResource方法,使用自定尺寸的Bitmap。
如果你要将一张大图设置为一个100*100的缩略图,执行以下代码:
mImageView.setImageBitmap(decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));
到此,使用decodeResource()方法将一个大图解析为小尺寸bitmap的应用就完成了。同理,还可以使用decodeStream(),decodeFile()等方法做相同的事,原理是一样的
延伸:一个Bitmap到底占用多大内存?系统给每个应用程序分配多大内存?
· Bitmap占用的内存为:像素总数 * 每个像素占用的内存。在Android中,Bitmap有四种像素类型:ARGB_8888、ARGB_4444、ARGB_565、ALPHA_8,他们每个像素占用的字节数分别为4、2、2、1。因此,一个2000*1000的ARGB_8888类型的Bitmap占用的内存为2000*1000*4=8000000B=8MB。
· Android根据设备屏幕尺寸和dpi的不同,给系统分配的单应用程序内存大小也不同,具体如下表(表格取自Android 4.4 Compatibility Definition Document (CDD)):
屏幕尺寸
DPI
应用内存
small / normal / large
ldpi / mdpi
16MB
small / normal / large
tvdpi / hdpi
32MB
small / normal / large
xhdpi
64MB
small / normal / large
400dpi
96MB
small / normal / large
xxhdpi
128MB
xlarge
mdpi
32MB
xlarge
tvdpi / hdpi
64MB
xlarge
xhdpi
128MB
xlarge
400dpi
192MB
xlarge
xxhdpi
256MB
2)图片在工作线程加载
在工作线程加载并压缩图片:记住:以后在activity写内部类时,内部类又是一个线程对象,请尽量使用静态内部类
继承AsyncTask,利用弱引用,引用外部类的中的属性imageView
在doInBackground 返回值为使用decodeResource()方法,将一个大图解析为小尺寸bitmap的应用
onPostExecute用if判断弱引用与(bitmap)result是否为空如果为空返回,不为空则提取imageview,再用if语句imageview判断是否为空,如果不为空则将bitmap写进imageview
1 0
- 图片压缩。大小压缩
- 图片压缩按比例压缩
- 压缩图片
- 压缩图片
- 图片压缩
- 图片压缩
- 图片压缩
- 图片压缩
- 压缩图片
- 图片压缩
- 图片压缩
- 图片压缩
- 图片压缩
- 图片压缩
- 图片压缩
- 图片压缩
- 压缩图片
- 图片压缩
- Java实现-高效排序算法之归并排序
- 1103. Integer Factorization (30)【搜索+剪枝】——PAT (Advanced Level) Practise
- QT实现五子棋(附源码)
- Vjudge 2016-5-10 math test
- utilities(matlab)—— ZCA 白化
- 图片压缩
- 1104. Sum of Number Segments (20)【数学题】——PAT (Advanced Level) Practise
- android开发笔记之多媒体—Canvas的相关方法
- MyEclipse快捷键
- 《数据结构》2.5-将链表A分解成B和C
- 1105. Spiral Matrix (25)【模拟】——PAT (Advanced Level) Practise
- 【转载自海子博客】浅谈Java中的equals和==
- window.location的使用
- Java Lock and Condition Example using Producer Consumer Solution