0

How to optimize this peace of code? It takes about a minute on saveImage method.

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
  }
}

I am calling ObrolSimpleHost from CameraFragment:

PictureTransaction xact = new PictureTransaction(getHost());
xact.needBitmap(true);
takePicture(xact);
Kamol Mavlonov
  • 365
  • 3
  • 9
  • Use Traceview and find out exactly where your problem lies. I would recommend you not write to `ByteArrayOutputStream`, then convert to a `byte[]`, then write the `byte[]` to a `FileOutputStream`. Just pass the `FileOutputStream` to `compress()`. If nothing else, that will help with memory management. – CommonsWare Aug 05 '14 at 15:15
  • @CommonsWare Thank you I have edited the code. Does it look better now? – Kamol Mavlonov Aug 05 '14 at 15:49
  • That's an improvement. You may want to `flush()` the `FileOutputStream` just before you `sync()`. – CommonsWare Aug 05 '14 at 15:51
  • @CommonsWare thank you, I just edited the code. Yes, it does look much much better. – Kamol Mavlonov Aug 06 '14 at 02:45
  • @CommonsWare looks like it is Android issue with `bitmap.compress(Bitmap.CompressFormat.WEBP, 70, fos);` One option I can consider is to reduce image size. Right know, the image size is over **2-3MB** on my device. The question is, how to reduce this `bitmap` itself so, the end image will be smaller and make faster compression process? – Kamol Mavlonov Aug 07 '14 at 04:09
  • "how to reduce this bitmap itself so" -- If you mean that you want the image to have fewer pixels, use `createScaledBitmap()` on `Bitmap`, I guess. I haven't played with this personally. – CommonsWare Aug 07 '14 at 11:34
  • @CommonsWare it works. By resizing bitmap, compression time is lessened. Thank you for your advice and library. – Kamol Mavlonov Aug 08 '14 at 02:43
  • @CommonsWare I have added my code as answer bellow. Does createScaledBitmap() part is makes sense? – Kamol Mavlonov Aug 08 '14 at 03:03
  • "is makes sense?" -- I have no idea. As I wrote, I have not used `createScaledBitmap()`. – CommonsWare Aug 08 '14 at 12:05
  • @CommonsWare anyway thank you very much for your [cwac-camera](https://github.com/commonsguy/cwac-camera) library. It is awesome! – Kamol Mavlonov Aug 08 '14 at 14:37

1 Answers1

0

Here is my own answer.

Fixed issues which CommonsWare mentioned and resize bitmap before compression by createScaledBitmap:

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
  }
}

Instead of standard bitmap use other library which build with JNI

In my case I am going to try Roid-WebP

Kamol Mavlonov
  • 365
  • 3
  • 9