Android多媒体开发 Pro Android Media 第一章 Android图像编程入门 2

来源:互联网 发布:三星移动网络定时开关 编辑:程序博客网 时间:2024/05/17 08:03

采集更大的图像 

为了解决大小限制,从Android 1.5开始,在大多数机器上,我们传入一个extra到激活相机应用的Intent中。此extra的名字在MediaStore类中定义为EXTRA_OUTPUT。它的值(extra以名称-值对的形式存在)以URI的形式,为相机应用指定了拍摄的图像保存的地方。

下面的代码段要求相机应用将图像保存到设备的SD卡,文件名为myfavoritepicture.png。

String imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath()    + "/myfavoritepicture.jpg"; File imageFile = new File(imageFilePath);  Uri imageFileUri = Uri.fromFile(imageFile);  Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);  i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageFileUri);  startActivityForResult(i, CAMERA_RESULT); 
注意:上述创建图像文件URI的代码段可以简化如下:imageFileUri =  Uri.parse("file:///sdcard/myfavoritepicture.jpg"); 虽然在实践中,所示的方法设备无关性更强,而且当SD卡的命名规则或者URI的语法因本地系统改变时,仍然能够兼容。

显示大图像

加载和显示图像涉及大量使用内存。例如,HTC G1手机拥有一个320万像素的摄像头。320M像素的摄像头,拍摄的图像通常为2048x1536像素。显示32位的这样大小的图像需要多达100663kb,大约13MB的内存。虽然不能肯定我们的应用就会耗尽内存,但是它显然使内存耗尽的可能性大大增加了。

Android给我们提供了一个名为BitmapFactory的工具类,它提供了一系列的静态方法从各种源加载位图图像。我们的需求是从文件加载图像,并把它显示在我们最初的activity中。幸运的是,BitmapFactory提供的加载方法都接受BitmapFactory.Options类,它允许我们定义将位图读入到内存的方式。具体来说,我们可以设置BitmapFactory加载图像的采样大小。指定BitmapFactory.Options类的inSampleSize参数,得到的位图图像将为原图大小inSampleSize分之一。例如,像我在这里做的,inSampleSize设置为8,将生成一个原图1/8大小的图像。

BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();  bmpFactoryOptions.inSampleSize = 8;  Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);  imv.setImageBitmap(bmp);

这是一个快速加载大图像的方法,但是没有考虑图像的原始大小以及屏幕的大小。如果我们缩放图像使之适应我们的屏幕,那就更好了。

下面的代码段说明了如何使用屏幕的大小确定加载图像时的采样值。当我们采用这些方法时,图像能够确保尽可能的填充屏幕。然而,如果图像的任一维度只显示100像素,则这个值将用来替换屏幕的维度。获取显示屏维度的代码如下:

Display currentDisplay = getWindowManager().getDefaultDisplay();  int dw = currentDisplay.getWidth();  int dh = currentDisplay.getHeight(); 

需要计算,才能得出图像的尺寸。为此,我们使用BitmapFactory和BitmapFactory.Options来帮忙。将BitmapFactory.Options.inJustDecodeBounds的值设置为true。这会告知BitmapFactory只需给出图像大小信息,无需解码图像本身。当我们使用这个方法时,BitmapFactory将给BitmapFactory.Options.outHeight和BitmapFactory.Options.outWidth两个变量赋值。

//加载图像的外形尺寸,而非图像本身 BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();  bmpFactoryOptions.inJustDecodeBounds = true; Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);  int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)dh);  int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)dw);  Log.v("HEIGHTRATIO",""+heightRatio);  Log.v("WIDTHRATIO",""+widthRatio); 

用图像的高度和宽度分别除以显示屏的高度和宽度,得到高度比和宽度比。然后,我们其中较大的那个作为缩放的比值。将这个比值赋给BitmapFactory.Options.inSampleSize变量,就可以得到一个加载到内存,大小接近我们所需的图像—在本例中,接近屏幕大小。

//如果两个比值都大于1,//那么图像的某一边大于屏幕 if (heightRatio > 1 && widthRatio > 1)  {      if (heightRatio > widthRatio)  {         //高度比较大,以它进行缩小        bmpFactoryOptions.inSampleSize = heightRatio;      }      else  {          //宽度比较大,以它进行缩小        bmpFactoryOptions.inSampleSize = widthRatio;      }  }  // 真正解码图像bmpFactoryOptions.inJustDecodeBounds = false;  bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);

这里是通过Intent使用内置相机应用,并显示所得图片的完整例子代码。图1-3 显示了此示例产生的,满屏大小的图像。

package com.apress.proandroidmedia.ch1.sizedcameraintent;  import java.io.File;  import android.app.Activity;  import android.content.Intent;  import android.graphics.Bitmap;  import android.graphics.BitmapFactory;  import android.net.Uri;  import android.os.Bundle;  import android.os.Environment;  import android.util.Log;  import android.view.Display;  import android.widget.ImageView;  public class SizedCameraIntent extends Activity {      final static int CAMERA_RESULT = 0;      ImageView imv;  String imageFilePath;      @Override  public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          setContentView(R.layout.main);          imageFilePath = Environment.getExternalStorageDirectory().getAbsolutePath()             + "/myfavoritepicture.jpg";          File imageFile = new File(imageFilePath);          Uri imageFileUri = Uri.fromFile(imageFile);          Intent i = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);          i.putExtra(android.provider.MediaStore.EXTRA_OUTPUT, imageFileUri);          startActivityForResult(i,CAMERA_RESULT);      }      protected void onActivityResult(int requestCode, int resultCode, Intent intent) {          super.onActivityResult(requestCode, resultCode, intent);          if (resultCode == RESULT_OK)  {              //取得ImageView的引用             imv = (ImageView) findViewById(R.id.ReturnedImageView);              Display currentDisplay = getWindowManager().getDefaultDisplay();              int dw = currentDisplay.getWidth();              int dh = currentDisplay.getHeight();             //加载图片的尺寸信息,而非图像本身            BitmapFactory.Options bmpFactoryOptions = new BitmapFactory.Options();              bmpFactoryOptions.inJustDecodeBounds = true;              Bitmap bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);              int heightRatio = (int)Math.ceil(bmpFactoryOptions.outHeight/(float)dh);              int widthRatio = (int)Math.ceil(bmpFactoryOptions.outWidth/(float)dw);            Log.v("HEIGHTRATIO",""+heightRatio);              Log.v("WIDTHRATIO",""+widthRatio);             // 如果两个比值都大于1,            // 那么图像的某一边大于屏幕             if (heightRatio > 1 && widthRatio > 1)  {                  if (heightRatio > widthRatio)  {                     // 高度比较大,以它进行缩小                    bmpFactoryOptions.inSampleSize = heightRatio;                 }                  else  {                     // 宽度比较大,以它进行缩小                    bmpFactoryOptions.inSampleSize = widthRatio;                  }             }               // 真正解码图像             bmpFactoryOptions.inJustDecodeBounds = false;               bmp = BitmapFactory.decodeFile(imageFilePath, bmpFactoryOptions);              // 显示图像              imv.setImageBitmap(bmp);           }      }  }

上述代码需要下面的 layout/main.xml文件:

<?xml version="1.0" encoding="utf-8"?>  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"      android:orientation="vertical"      android:layout_width="fill_parent"      android:layout_height="fill_parent" >     <ImageView android:id="@+id/ReturnedImageView"         android:layout_width="wrap_content"         android:layout_height="wrap_content">    </ImageView>  </LinearLayout> 

图1-3. 返回的满屏大小图像显示在ImageView中


1 0
原创粉丝点击