如何获取图片,图片是系统资源,照相机,相册,无论是系统自带,还是美图秀秀这灰软件,都是通过Intent来调用其他APP来实现功能,因此针对Intnet的操作也是必不可少的,以及OOm解决压缩图片的问题也是常见的

选择图片

private static final int IMAGE_CODE = 2;
private  void toSelectImg()
{
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    startActivityForResult(intent, IMAGE_CODE);
}

获取图片资源

1.复写 onActivityResult

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (data == null) {
            return;
        }
        Uri uri;
        uri = data.getData();
}

这个uri获取的就是图片的位置,并且通过ContentResolver来获取图片

OOM大图解决方案

这个类包括了一些适用于处理和加载位图实体的通用技术,在某种程度上保持你的用户接口(UI)组件有回应,避免超过你应用的资源限制。如果你不注意,位图就会迅速地消耗你的可利用内存,以致于于严重的异常而导致应用的崩溃: **java.lang.OutofMemoryError: bitmap size exceeds VM budget. **

以下是在你的android应用程序中加载位图时会遇到的一些棘手问题:

  • 移动设备通常都只有有限的系统资源。Android设备可以为单个应用分配小到16MB大小的内存。Android兼容性定义文档(CDD),3.7章节,虚拟机兼容性给出了不同尺寸和密度的手机屏幕下应用程序所需的最小内存。在最小的内存限制下应用程序应当进行优化处理后运行。然而,请记住许多设备都 被配备了更高的内存限制。
  • 位图占据了大量的内存空间,特别是像图册这种富图像的应用。例如,Galaxy Nexus上的照相机所照的图片最大达到2592x1936像素(5万像素)。如果位图的配置使用ARGB_8888(Android 2.3的默认配置)那么加载这个图像到内存需要19MB的存储空间(259219364 bytes),直接超过了许多设备上的单应用限制。
  • Android应用UI通常需要许多图片需要马上被加载出来。像ListView,GridView和ViewPager等包含了许多位图的组建通常要求在手指滑动后马上就要在屏幕上马上显示出来。

有效地加载大位图文件

Loading Large Bitmaps Efficiently

图像有各种不同的形状和大小。在许多情况下,他们往往比一个典型应用程序的用户界面(UI)所需要的资源更大。例如,系统的Gallery程序展示使用Android设备的照相机所拍摄的照片通常要比你的设备的屏幕密度的分辨率更高。 既然你所使用的内存有限,理想状况下你只想在内存中加载一个低分辨率的版本。低分辨率的方案应该匹配显示它的UI组件的大小。一个更高分辨率的图片不提供任何可见的好处,但是由于额外的缩放会导致额外的性能开销,仍然占用缩放之前的内存,。 这节课将引导你在不超过内存限制的情况下通过解码大型位图,在内存中加载一个较小的位图子样本。

读取一个位图的尺寸和类型

Read Bitmap Dimensions and Type

为了从多种资源来创建一个位图,BitmapFactory类提供了几个解码的方法(decodeByteArray(),decodeFile(),decodeResource(),等等)。根据你的图像数据资源选择最合适的解码方法。这些方法试图请求分配内存来构造位图,因此很容易导致OutOfMemory异常。每种类型的解码方法都有额外的特征可以让你通过BitMapFactory.Options类指定解码选项。当解码时避免内存分配可以设置inJustDecodeBounds属性为true,位图对象返回null但是设置了outWidth,outHeight和outMimeType。这种技术允许你在创建位图(和分配内存)之前去读取图像的尺寸和类型。

BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(getResources(), R.id.myimage, options);
int imageHeight = options.outHeight;
int imageWidth = options.outWidth;
String imageType = options.outMimeType;

为了避免java.lang.OutOfMemory异常,在解码位图之前请检查它的尺寸,除非你十分确定资源提供给你的可预见的图像数据正好满足你的内存。

加载一个缩小版本到内存中(Load a Scaled Down Version into Memory)

现在的图像尺寸都是已知的,他们可以被用来决定是否应该加载完整的图片到内存或者是否用一个缩小的版本去代替加载。以下是一些值得考虑的因素:

  • 估计加载完整图像所需要的内存;
  • 你承诺加载这个图片所需空间带给你的程序的其他内存需求;
  • 准备加载图像的目标ImageView或UI组件尺寸;
  • 当前设备的屏幕尺寸和密度; 例如,如果1024768像素的图像最终被缩略地显示在一个12896像素的ImageView中,就不值得加载到内存中去。 告诉解码器去重新采样这个图像,加载一个更小的版本到内存中,在你的BitmapFactory.Option对象中设置inSampleSize为true。例如,将一个分辨率为20481536的图像用 inSampleSize值为4去编码将产生一个大小为大约512384的位图。加载这个到内存中仅使用0.75MB,而不是完整的12MB大小的图像(假设使用ARGB_8888位图的配置)。这里有一个方法在目标的宽度和高度的基础上来计算一个SampleSize的值。

NOTE:使用2的幂数设置inSampleSize的值可以使解码器更快,更有效。然而,如果你想在内存或硬盘中缓存一个图片调整后的版本,通常解码到合适的图像尺寸更适合来节省空间。 要使用这种方法,首先解码,将inJustDecodeBounds设置为true,将选项传递进去,然后再次解码,在使用新的inSampleSize值并将inJustDecodeBounds设置为false:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId,
 
  int reqWidth, int reqHeight) {
 
  // First decode with inJustDecodeBounds=true to check dimensions
 
  final BitmapFactory.Options options = new BitmapFactory.Options();
 
  options.inJustDecodeBounds = true;
 
  BitmapFactory.decodeResource(res, resId, options);
 
  // Calculate inSampleSize
 
  options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
 
  // Decode bitmap with inSampleSize set
 
  options.inJustDecodeBounds = false;
 
  return BitmapFactory.decodeResource(res, resId, options);
 
  }

这种方法可以很容易地加载任意大小的位图到一个ImageView显示一个100x100像素的缩略图,如下面的示例代码所示:

mImageView.setImageBitmap(
 
decodeSampledBitmapFromResource(getResources(), R.id.myimage, 100, 100));

你可以按照类似的过程,用适当的BitmapFactory.decode*中的方法去解码一个从其他资源得到的位图。

最终得到的效果图

OOMDemo

最佳实例

public class OOMActivity extends AppCompatActivity {

    private static final int IMAGE_CODE = 2;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_oom);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            OOMActivity.this.toSelectImg();
                        }
                    }).show();
        }
    });
}

private void toSelectImg() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    startActivityForResult(intent, IMAGE_CODE);
}


public static int log2(int value) {
    if (value == 0)
        return -1;
    else
        return 1 + log2(value >> 1);
}

// 关于图片大小在手机、平板中正确显示的计算,
// 以确保正确的显示图片,
// 且不超出内存
public static int calculateInSampleSize(
        BitmapFactory.Options options, int reqWidth, int reqHeight) {
    // Raw height and width of image
    final int height = options.outHeight;
    final int width = options.outWidth;
    int inSampleSize = 1;
    if (height > reqHeight || width > reqWidth) {
        //尽可能的增大缩小的比例
        if (width > height) {
            //Math.roudn,四舍五入
            inSampleSize = Math.round((float) height / (float) reqHeight);
        } else {
            inSampleSize = Math.round((float) width / (float) reqWidth);
        }
    }
    int bit2map = log2(inSampleSize);
    int lastSize = 1;
    for (int i = 0; i < bit2map; i++) {
        lastSize *= 2;
    }
    return lastSize;
}


//压缩图片,并显示在ActivityImageView中
private void showImg(Uri uri) {
    InputStream is = null;
    try {
        //大图OOM
        is = getContentResolver().openInputStream(uri);
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = false;

        int imageHeight = options.outHeight;
        int imageWidth = options.outWidth;
        options.inSampleSize = calculateInSampleSize(options, 480, 480);;//将原图大小缩小4倍
        //打印 图片的大小 imageHeight \width
        Log.d("OOM.Debug", "height:" + imageHeight + "widht:" + imageWidth);
        Bitmap bitmap = BitmapFactory.decodeStream(is, null, options);
        ImageView imgview = (ImageView) findViewById(R.id.oom_image);
        imgview.setImageBitmap(bitmap);

        is.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
}


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 2) {
        if (data == null) {
            return;
        }
        Uri uri;
        uri = data.getData();
        showImg(uri);
    }
}
}