BitmapFactory.Options参数作用

参数作用
  • BitmapFactory.Options这个参数可以设置Bitmap的采样率,通过该比那图片的宽度、高度、缩放比例等,以达到减少图片的像素的目的,设置这个值可以更好的控制、显示和使用Bitmap,可以使用该值降低OOM出现的概率
  • BitmapFactory.Options的常用成员变量(in开头的就是设置参数,out开头的就是获取参数):
public boolean inJustDecodeBounds;
public int inSampleSize;
public int inDensity;
public int inTargetDensity;
public int inScreenDensity;
public boolean inScaled;
public Bitmap.Config inPreferredConfig;
public int outWidth;
public  int outHeight;
public String outMimeType; 
inJustDecodeBounds
  • 如果将这个参数设置为true, 则表示只解析图片信息,不获取图片,不分配内存,能获取的信息有图片的宽度、高度和图片的MIME类型,分别通过options.outWidth(), options.outHeight(),options.outMimeType返回。
    • 首先将这个参数设置为true
    • 获取图片的宽和高
    • 和显示图片的控件进行比较
    • 如果图片过大就需要压缩
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeResource(getREsources(), R.drawable.XXX, options);
System.out.println(bitmap);
System.out.println(options.outWidth+" " +options.outHeight+" "+options.outMimeType);

结果:
null
XX, XX, XX
  • 上述结果说明:inJustDecodeBounds只会解析Bitmap的高,宽,并不会解析Bitmap对象,整个过程并不占用内存
inSampleSize压缩图片
  • 这个字段表示采样率(采样频率),是指每隔多少个样本采样一次作为结果,比如将这个结果设置为4,意味着从原本图片的4个像素中去一个像素作为返回结果,其余的都被丢弃,这样图片的宽和高就变为原来的1/4,所以采样率越大,图片越小,越失真。
  • 官方建议数值取2的整数次幂,否则系统会自动的向下取整,不可以设置小于1的数值,这样系统会一直使用1来设置采样率
设置采样率
  • 首先我们应该确定控件的大小,然后按照较小的倍数进行缩放,来保证图片不小于控件的大小,这样尽管会多占用内存,但是不至于太失真。
    • 原则:缩放后的图片的尺寸尽量大于等于相应的控件大小
步骤

(1) 获取图片的原始的宽高,通过将Options对象的inJustDecodeBounds属性设置为true后调用decodeResource()函数,实现不真正加载图片(不耗费内存的情况下)获取图片的信息

BitmapFactory.Options options  = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeREsource(getREsource(), resId,  options);

(2) 根据据原始宽高和目标宽高计算出inSampleSize

public static int calSampleSize(BitmapFactory.Options options, int dstWidth, int dstHeight){
    //原始宽高
    int rawWidth = options.outWidth;
    int rawHeight = options.outHeight;
    if(rawWidth > dstWidth || rawHeight > dstHeight){
        //得到图片比目标控件高大的倍数
        float ratioHeight = (float) rawheight/dstHeight;
        //得到图片比目标控件宽大的倍数
        float ratioWidth = (float) rawWidth.dstWidth;
        //两者中取最小的以便于覆盖控件不失真
        inSampleSize = (int)Math.min(ratioWidth, ratioHeight);
    }
    return inSampleSize;
}

(3) 根据采样率解析出压缩后的Bitmap

BitmapFactory.Options options2 = new BitmapFactory.Options();
options2.inSampleSize = sampleSize;
try{
    Bitmap bmp = BitmapFactory.decodeREsource(getResources(), R.drawable.XXX, options2);
    ...
 }catch(OutOfMemoryError e){
    ...
 }
加载一个完整的Bitmap文件需要占多少空间
文件夹drawable-ldpidrawable-mdpidrawable-hdpidrawable-xhdpidrawable-xxhdpidrawable-xxxhdpi
density11.5233.54
densityDpi160240320480560640
  • dendity:表示dpi和px的换算比例,1dpi = 1density px

  • densityDpi:表示在对应的分辨率下每英寸有多少个dpi

  • 屏幕上1英寸长 所对应的px数 = 每英寸的dpi数(densityDpi) * dpi所对应的px数(density)

  • 如果屏幕的分辨率和这些文件所在文件夹的分辨率不同时:

    • 缩放比例 = 屏幕分辨率/文件所在文件夹的分辨率
    • 但是在SD卡中的图片,Android的处理策略是不进行缩放
  • Bitmap大小的计算:

    • 默认存储的格式是ARGB_8888每个像素占8位4字节,所以使用宽*高 *4B即可
inScaled
  • 该参数表示是否对当前Bitmap图像进行缩放,如果设置为false表示不进行缩放,如果设置为true或者不设置表示默认的进行动态缩放,默认设置为true
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.niuniuya);
System.out.println(bitmap.getWidth()+" "+bitmap.getHeight()+" "+bitmap.getByteCount());
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = false;
Bitmap bmp = BitmapFactory.decodeResource(getResources(),R.drawable.niuniuya, options);
System.out.println(bmp.getWidth()+" "+bmp.getHeight()+" "+bitmap.getByteCount());


结果
1200 1200 5760000
400 400 640000
inDensity, inTargetDensity, inScreenDensity
  • inDensity:用于设置文件所在资源文件夹的屏幕分辨率
  • inTargetDensity:表示真实显示的屏幕分辨率
  • inScreenDensity:源码中并没有用到,实际上根本没什么用处
  • scale(缩放比)= inTargetDensity/inDensity
    • 所参数的作用就是通过手动的方式设置资源文件夹的分辨率和真实显示的屏幕分辨率来指定屏幕的缩放比例
options.inScaled = true;
options.inDensity = 1;
options.inTargetDensity = 2;
Bitmap bmp1 = BitmapFactory.decodeResource(getResources(), R.drawable.niuniuya, options);
System.out.println(bmp.getWidth()+" "+bmp.getHeight()+" "+bmp.getByteCount());

结果:
400 400 640000
800 800 2560000
inPreferredConfig
  • 这个参数是用来设置参数格式的,默认使用ARGB_8888, 还有RGB_565, ALPHA_8, ARGB_4444
options.inScaled = true;
options.inDensity = 1;
options.inTargetDensity = 2;
Bitmap bmp1 = BitmapFactory.decodeResource(getResources(), R.drawable.niuniuya, options);
System.out.println(bmp1.getWidth()+" "+bmp1.getHeight()+" "+bmp1.getByteCount());
options.inPreferredConfig = Bitmap.Config.RGB_565;
Bitmap bmp2 = BitmapFactory.decodeResource(getResources(), R.drawable.niuniuya, options);
System.out.println(bmp2.getWidth()+" "+bmp2.getHeight()+" "+bmp2.getByteCount());



结果:
宽和高是不会变的
800 800 2560000
800 800 1280000
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
对于拍摄照片我们可以直接调用系统自带的相机拍照,一般情况下无需我们自己开发相机拍照。 1、当点击按钮后我们可以通过Intent意图启动系统相机 @Override public void onClick(View v) { Intent intent=new Intent(MediaStore.ACTION_IMAGE_CAPTURE); String temName=new DateFormat().format("yyMMdd_hhmmss",System.currentTimeMillis())+"_"+(Math.random()*100)+".jpg"; //文件名 image_path=path+File.separator+temName; File file=new File(image_path); if(file.exists()){ file.delete(); } Uri u=Uri.fromFile(file); intent.putExtra(MediaStore.EXTRA_OUTPUT, u); startActivityForResult(intent, 0); } 在这里设置 intent.putExtra(MediaStore.EXTRA_OUTPUT, u);非常重要,如果不设置这个参数那么我们获取到的图片只是一个经过压缩后的缩略图,只有设置这个才能得到拍摄后的原图。 2、在startActivityForResult(intent, 0);后我们需要重写onActivityResult(int requestCode, int resultCode, Intent data)方法,如果设置了MediaStore.EXTRA_OUTPUT那么我们在这里data返回的是null。 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if(resultCode==RESULT_OK){ File file=new File(image_path); try { Uri uri = Uri.fromFile(file); BitmapFactory.Options options=new BitmapFactory.Options(); options.inJustDecodeBounds=true; BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options); options.inSampleSize=4; options.inJustDecodeBounds=false; Bitmap map=BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options); android.provider.MediaStore.Images.Media.insertImage(getContentResolver(), map, null, null); sendBroadcast(new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE,uri)); image.setImageBitmap(map); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } 蓝色部分是对图片进行简单的压缩处理,如果不进行处理会出现内存溢出。 红色部分是将图片保存在DCIM文件夹下。 绿色部分是发生一个广播通知系统重新扫描制定文件,这样我们就可以在图库本地图片中看到拍摄的图片。 3、最后记得在清单文件中加入调用系统相机和保存文件权限 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.CAMERA"/>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wjxbless

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值