简体   繁体   中英

Bitmap Compression and Speed Optimization In Android

I'm dealing with an AR application in Android that draws on the camera output. I'm working on a portion of the code to save three image files: the raw picture, the screen overlay and the composite picture with overlay drawn on (possibly superfluous, given the other two). The native image size for my camera is 2592x1944.

Right now my save operation is taking longer than I'd like. I'm doing the picture saving using an AsyncTask, but the actual save part boils down to the following:

public void onPictureTaken(byte[] data, Camera camera){
  Size sz = camera.getParameters().getPictureSize();

  TimingLogger tl = new TimingLogger("CodeTiming", "Start Saving");
  String fileName = getNameFromTime();

  tl.addSplit("Start Pic Save");
  // The Picture itself 
  ImageFile photo = new ImageFile(fileName+"_image.jpg");
  photo.write(data);

  tl.addSplit("Start Overlay Save");
  // The overlay with blank background
  Bitmap bmp = Bitmap.createBitmap(sz.width,sz.height,Bitmap.Config.ARGB_8888);
  Canvas canvas = new Canvas(bmp);
  DrawStuffOnCanvas(canvas);
  ImageFile overlay = new ImageFile(fileName+"_overlay.png");
  overlay.write(bitmapToByteArray(bmp,Bitmap.CompressFormat.PNG));

  tl.addSplit("Start Overlay Onto Pic Save");
  // The picture with the overlay drawn on
  Options options = new Options();
  options.inDither = false;
  options.inPreferredConfig = Bitmap.Config.ARGB_8888;
  Bitmap picture = BitmapFactory.decodeByteArray(data, 0, data.length, options);
  picture = picture.copy(Bitmap.Config.ARGB_8888, true);
  Canvas canvas2 = new Canvas(picture);
  DrawStuffOnCanvas(canvas2);
  ImageFile overlay2 = new ImageFile(fileName+"_combo.jpg");
  overlay2.write(bitmapToByteArray(picture,Bitmap.CompressFormat.JPEG));

  tl.addSplit("Start Metadata Save");
  //Save picture metadata, not relevant to question

  tl.addSplit("Done");
  tl.dumpToLog();
}

Converting the Bitmap to the byte[] is being done by:

byte[] bitmapToByteArray(Bitmap b,Bitmap.CompressFormat fmt){
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  b.compress(fmt, 100, baos);
  return baos.toByteArray();
}

Note that all of the file objects (eg ImageFile) are custom, but the relevant information needed is that they handle the writing of a byte[] using a FileOutputStream. Here's a recent timing dump for this run.

Start Saving: begin
Start Saving:      4 ms, Start Pic Save
Start Saving:      86 ms, Start Overlay Save
Start Saving:      3576 ms, Start Overlay Onto Pic Save
Start Saving:      2066 ms, Start Metadata Save
Start Saving:      15 ms, Done
Start Saving: end, 5747 ms

There's quite a bit of variability, anywhere from about 5-15 seconds per save. The overlay (essentially lines drawn on the screen) is currently being saved as a PNG for the transparency, and because of artifacts at the sharp line edges caused by the JPEG compression. Following the logic of this question , I saw that if I switch the overlay to a JPEG, I cut my time for that step in half. As you can see, I did implement that change for the composite picture (sharp edges are already blurred by the image itself), which saved about 20 seconds on that compression step.

So my question is this. Is there anything I can do to save time on my compression of the overlay, but keep the PNG output? Or, alternatively, is there something else I'm doing here that's wasting a lot of time that could speed up the overall save operation? Then I wouldn't need to worry about PNG vs. JPEG quite as much.

  1. PNG compression is much slower than JPEG compression, especially when your bitmap size is high.
  2. Use RGB_565 instead of ARGB_8888 if you don't care of transparency.

More info here: https://stackoverflow.com/a/33299613/4747587

Dramatic speed up mechanism:

Use RGB_565 instead of ARGB_8888 whereas possible (eg no transparent pixel)

Also, the "copy" operation takes more time than drawing that Bitmap on the Canvas. You can simply create an empty bitmap and draw the original image.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM