【问题标题】:CWAC Camera: why my SimpleCameraHost saveImage is so slow, am I doing something wrong?CWAC Camera:为什么我的 SimpleCameraHost saveImage 这么慢,是我做错了什么吗?
【发布时间】:2014-08-05 15:04:07
【问题描述】:

如何优化这种和平的代码? saveImage 方法大约需要一分钟。

class ObrolSimpleHost extends SimpleCameraHost {
  private final String[] SCAN_TYPES = {"image/webp"};
  private Context context = null;

  public ObrolSimpleHost(Context _ctxt) {
    super(_ctxt);
    this.context = getActivity();
  }

  @Override public void saveImage(PictureTransaction xact, Bitmap bitmap) {
    File photo = getPhotoPath();
    if (photo.exists()) {
      photo.delete();
    }
    try {
      FileOutputStream fos = new FileOutputStream(photo.getPath());
      bitmap.compress(Bitmap.CompressFormat.WEBP, 70, fos);
      fos.flush();
      fos.getFD().sync();
      if (scanSavedImage()) {
        MediaScannerConnection.scanFile(context, new String[]{photo.getPath()}, SCAN_TYPES, null);
      }
    } catch (java.io.IOException e) {
      handleException(e);
    }
  }

  @Override public void saveImage(PictureTransaction xact, byte[] image) {
    // do nothing
  }
}

我正在从 CameraFragment 拨打 ObrolSimpleHost

PictureTransaction xact = new PictureTransaction(getHost());
xact.needBitmap(true);
takePicture(xact);

【问题讨论】:

  • 使用 Traceview 并准确找出问题所在。我建议您不要写信给ByteArrayOutputStream,然后转换为byte[],然后将byte[] 写为FileOutputStream。只需将FileOutputStream 传递给compress()。如果不出意外,这将有助于内存管理。
  • @CommonsWare 谢谢我已经编辑了代码。现在好看了吗?
  • 这是一个改进。你可能想在sync() 之前flush() FileOutputStream
  • @CommonsWare 谢谢,我刚刚编辑了代码。是的,它看起来确实好多了。
  • @CommonsWare 看起来是bitmap.compress(Bitmap.CompressFormat.WEBP, 70, fos); 的Android 问题我可以考虑的一个选项是减小图像大小。没错,我的设备上的图像大小超过 2-3MB。问题是,如何减少这个bitmap本身,使最终图像更小,压缩过程更快?

标签: android camera compression commonsware-cwac webp


【解决方案1】:

这是我自己的答案。

修复了CommonsWare 提到的问题,并在createScaledBitmap 压缩之前调整了bitmap 的大小:

class ObrolSimpleHost extends SimpleCameraHost {
  private final String[] SCAN_TYPES = {"image/" + imputType};
  private Context context = null;

  public ObrolSimpleHost(Context _ctxt) {
    super(_ctxt);
    this.context = getActivity();
  }

  @Override public void saveImage(PictureTransaction xact, Bitmap bitmap) {
    File photo = getPhotoPath();
    String path = photo.getPath().replace("jpg", imputType);
    if (photo.exists()) {
      photo.delete();
    }

    /**
     * Resizing bitmap, so save some ms in compression
     * http://stackoverflow.com/questions/17839388/creating-a-scaled-bitmap-with-createscaledbitmap-in-android
     */
    final int maxSize = 960;
    int outWidth;
    int outHeight;
    int inWidth = bitmap.getWidth();
    int inHeight = bitmap.getHeight();
    if(inWidth > inHeight){
      outWidth = maxSize;
      outHeight = (inHeight * maxSize) / inWidth;
    } else {
      outHeight = maxSize;
      outWidth = (inWidth * maxSize) / inHeight;
    }
    Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, outWidth, outHeight, false);

    try {
      FileOutputStream fos = new FileOutputStream(path);
      if (imputType.equals("jpeg")) {
        resizedBitmap.compress(Bitmap.CompressFormat.JPEG, 70, fos);
      } else {
        resizedBitmap.compress(Bitmap.CompressFormat.WEBP, 70, fos);
      }
      fos.flush();
      fos.getFD().sync();
      if (scanSavedImage()) {
        MediaScannerConnection.scanFile(context, new String[]{photo.getPath()}, SCAN_TYPES, null);
      }
    } catch (java.io.IOException e) {
      handleException(e);
    }
    EventBus.getDefault().postSticky(new Events.PreparingBitmapEvent(path));
    getActivity().finish();
  }

  @Override public void saveImage(PictureTransaction xact, byte[] image) {
    // do nothing
  }
}

代替标准的bitmap 使用其他使用JNI 构建的库

就我而言,我将尝试Roid-WebP

【讨论】:

    猜你喜欢
    • 2017-08-23
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    • 2011-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-14
    相关资源
    最近更新 更多