百恒网络
安卓开发之缩放和显示位图
  • 百恒服务
  • APP开发
  • 网页案例
  • 网页知识
  • 关于我们
  • 联系我们
  • 安卓开发之缩放和显示位图

    2018-12-04 15:37:10 2782
           使用相机intent,我们就可以成功拍摄现场照片并保存了。

           有了照片,接下来就是找到并加载它,然后展示给用户看。在南昌APP开发的技术实现上,这需要加载照片到大小合适的Bitmap对象中。要从文件生成Bitmap对象,我们需要BitmapFactory类:
           Bitmap bitmap = BitmapFactory.decodeFile(mPhotoFile.getPath());

           看到这里,有没有感觉不对劲?肯定有的。问题在于:介绍Bitmap时,我们提到“大小合适”。Bitmap是个简单对象,它只存储实际像素数据。也就是说,即使原始照片已压缩过,但存入Bitmap对象时,文件并不会同样压缩。因此,16万像素24位已压缩为5Mb大小的JPG照片文件,一旦载入Bitmap对象,就会立即膨胀至48Mb大小!

           这其实个问题是可以设法解决的,但需要手工缩放位图照片。具体做法就是,首先确认文件到底有多大,然后考虑按照给定区域大小合理缩放文件。最后,重新读取缩放后的文件,创建Bitmap对象。

           创建名为PictureUtils.java的新类,并在其中添加getScaledBitmap(String, int, int)缩放方法,如下代码清单所示。

           创建getScaledBitmap(...)方法(PictureUtils.java)
           public class PictureUtils {
           public static Bitmap getScaledBitmap(String path, int destWidth, int destHeight) {
           // Read in the dimensions of the image on disk
           BitmapFactory.Options options = new BitmapFactory.Options();
           options.inJustDecodeBounds = true;
           BitmapFactory.decodeFile(path, options);

           float srcWidth = options.outWidth;
           float srcHeight = options.outHeight;
     
           // Figure out how much to scale down by
           int inSampleSize = 1;
           if (srcHeight > destHeight || srcWidth > destWidth) {
           if (srcWidth > srcHeight) {
           inSampleSize = Math.round(srcHeight / destHeight);
           } else {
           inSampleSize = Math.round(srcWidth / destWidth);
           }
           }

           options = new BitmapFactory.Options();
           options.inSampleSize = inSampleSize;
           // Read in and create final bitmap
           return BitmapFactory.decodeFile(path, options);
           }
           } 

           上述方法中,inSampleSize值很关键。它决定着缩略图像素的大小。假设这个值是1的话,就表明缩略图和原始照片的水平像素大小一样。如果是2的话,它们的水平像素比就是1∶2。因此,inSampleSize值为2时,缩略图的像素数就是原始文件的四分之一。

           问题总是接踵而来,解决了缩放问题,又冒出了新问题:fragment刚启动时,PhotoView
           究竟有多大无人知道。onCreate(...)、onStart()和onResume()方法启动后,才会有实例化布局出现。也就在此时,显示在屏幕上的视图才会有大小尺寸。这也是出现新问题的原因。

           解决方案有两个:要么等布局实例化完成并显示,要么干脆使用保守估算值。特定条件下,尽管估算比较主观,但确实是一个切实可行的办法。再添加一个getScaledBitmap(String,Activity)静态Bitmap估算方法,如下代码所示。

           编写合理的缩放方法(PictureUtils.java)
           public class PictureUtils {
           public static Bitmap getScaledBitmap(String path, Activity activity) {
           Point size = new Point();
           activity.getWindowManager().getDefaultDisplay()
           .getSize(size);
           return getScaledBitmap(path, size.x, size.y);
           }
           ... 

           该方法先确认屏幕的尺寸,然后按此缩放图像。这样,就能保证载入的ImageView永远不会过大。看到没有,无论如何,这是一个比较保守的估算有时就是能解决问题。

           接下来,为把Bitmap载入ImageView。在CrimeFragment.java中,添加刷新mPhotoView的方法,如下代码清单所示。
           更新mPhotoView(CrimeFragment.java)
           ...
           private String getCrimeReport() {
           ...
           }
           private void updatePhotoView() {
           if (mPhotoFile == null || !mPhotoFile.exists()) {
           mPhotoView.setImageDrawable(null);
           } else {
           Bitmap bitmap = PictureUtils.getScaledBitmap(
           mPhotoFile.getPath(), getActivity());
           mPhotoView.setImageBitmap(bitmap);
           }
           }
           } 

           然后,分别在onCreateView(...)和onActivityResult(...)方法中调用updatePhotoView()
           方法,如下代码清单所示。

           调用updatePhotoView()方法(CrimeFragment.java)
           mPhotoButton.setOnClickListener(new View.OnClickListener() {
           @Override
           public void onClick(View v) {
           startActivityForResult(captureImage, REQUEST_PHOTO);
           }
           });
           mPhotoView = (ImageView) v.findViewById(R.id.crime_photo);
           updatePhotoView();
           return v;
           }
           @Override
           public void onActivityResult(int requestCode, int resultCode, Intent data) {
           if (resultCode != Activity.RESULT_OK) {
           return;
           }
           if (requestCode == REQUEST_DATE) {
           ...
           } else if (requestCode == REQUEST_CONTACT && data != null) {
           ...
           } else if (requestCode == REQUEST_PHOTO) {
           updatePhotoView();
           }
           } 

           再次运行应用,这样就可以看到已拍照片的缩略图了。
    展开分享
    服务
    案例
    首页
    动态
    联系
    咨询