I'm writing an app with a simple camera function. I take a picture in my main activity, and start a new thread which rotates the image, adds a transparent watermark and saves it as a .PNG.
This app runs great on my samsung galaxy S3 running a custom rom: AOKP, Android 4.4.2. The total time the execution of the code given below takes, is about 2 seconds. My app uses about 9 Mb of memory according to the task manager.
When I ran this app on my galaxy S4, running stock (rooted) Android 4.4.2, the execution time was over 27 seconds. The app uses about 124 Mb of memory according to the task manager (way too much). Occasionally the app crashes and throws an OutOfMemory error, this does not happen on the S3.
Here is the piece of code responsible for saving the image in my SaveThread:
TimingLogger tl = new TimingLogger("MyTag", "Saving");
String name = new SimpleDateFormat("dd-MM-yyyy_HH-mm-ss")
.format(new Date());
File myNewFolder = new File(path);
myNewFolder.mkdir();
File file = new File(path, name + ".JPEG");
OutputStream imageFileOS;
// Get EXIF rotation from byte array
int rotation = getOrientation(data);
tl.addSplit("Rotation calculated");
// Convert byte array to bitmap, and watermark bitmap
Bitmap pictureObject = BitmapFactory.decodeByteArray(data, 0,
data.length);
tl.addSplit("Decoded ByteArray to Bitmap");
// Rotate bitmap image according to EXIF data
pictureObject = rotateBitmap(rotation, pictureObject);
tl.addSplit("Bitmap rotated");
// Add watermark to rotated bitmap
Bitmap waterMarkedBitmap = addWaterMarkText(pictureObject);
tl.addSplit("Bitmap watermarked");
try {
imageFileOS = new FileOutputStream(file);
waterMarkedBitmap.compress(Bitmap.CompressFormat.PNG, 100,
imageFileOS);
tl.addSplit("Bitmap compressed");
imageFileOS.flush();
imageFileOS.close();
} catch (Exception e) {
e.printStackTrace();
}
As you can see, I added a timing logger to find out what takes so long. The following LogCat return shows that compressing the Bitmap to .PNG takes very long. I think this may have something to do with the garbage collector. My Logcat returns the following during execution:
02-04 13:57:08.166: I/Choreographer(30003): Skipped 73 frames! The
application may be doing too much work on its main thread.
02-04 13:57:10.528: D/dalvikvm(30003): GC_FOR_ALLOC freed 552K, 19% free 24803K/30324K, paused 48ms, total 49ms
02-04 13:57:10.628: I/dalvikvm-heap(30003): Grow heap (frag case) to 76.336MB for 51121168-byte allocation
02-04 13:57:10.918: D/dalvikvm(30003): GC_FOR_ALLOC freed 4K, 7% free 74723K/80248K, paused 23ms, total 23ms
02-04 13:57:11.019: I/dalvikvm-heap(30003): Grow heap (frag case) to 125.086MB for 51121168-byte allocation
02-04 13:57:11.859: D/dalvikvm(30003): GC_FOR_ALLOC freed 49923K, 43% free 74723K/130172K, paused 25ms, total 26ms
02-04 13:57:11.869: I/dalvikvm-heap(30003): Grow heap (frag case) to 125.086MB for 51121168-byte allocation
02-04 13:57:39.967: D/MyTag(30003): Saving: begin
02-04 13:57:39.967: D/MyTag(30003): Saving: 3 ms, Rotation calculated
02-04 13:57:39.967: D/MyTag(30003): Saving: 418 ms, Decoded ByteArray to Bitmap
02-04 13:57:39.967: D/MediaScannerConnection(30003): Scanning file 7klwibgf7fvntblfd7(7KhzCbvfib7(,6()6)(*._*+6./6*(5QHFG
02-04 13:57:39.967: D/MyTag(30003): Saving: 939 ms, Bitmap rotated
02-04 13:57:39.967: D/MyTag(30003): Saving: 96 ms, Bitmap watermarked
02-04 13:57:39.967: D/MyTag(30003): Saving: 28023 ms, Bitmap compressed
02-04 13:57:39.967: D/MyTag(30003): Saving: 0 ms, Done saving
02-04 13:57:39.967: D/MyTag(30003): Saving: 8 ms, Media scanned
02-04 13:57:39.967: D/MyTag(30003): Saving: end, 29487 ms
I am not sure this is related, but the LogCat line:
D/MediaScannerConnection(30003): Scanning file 7klwibgf7fvntblfd7(7KhzCbvfib7(,6()6)(*._*+6./6*(5QHFG
clearly does not show the path of the scanned file (though it does work). When I connect my S3 to Eclipse, this line does show the scanned file path.
I tried changing the compression quality but it didn't make a significant change in speed or memory usage. I can't figure out what is causing the huge difference in RAM usage and the execution time. What can cause this difference and what can I do to fix it?
EDIT: To be complete, this is how fast the compression works on the galaxy S3:
02-04 15:40:47.980: D/MyTag(25536): Saving: 6 ms, Rotation calculated
02-04 15:40:47.980: D/MyTag(25536): Saving: 53 ms, Decoded ByteArray to Bitmap
02-04 15:40:47.980: D/MyTag(25536): Saving: 94 ms, Bitmap rotated
02-04 15:40:47.980: D/MyTag(25536): Saving: 19 ms, Bitmap watermarked
02-04 15:40:47.980: D/MyTag(25536): Saving: 210 ms, Bitmap compressed
02-04 15:40:47.980: D/MyTag(25536): Saving: 0 ms, Done saving
02-04 15:40:47.980: D/MyTag(25536): Saving: 3 ms, Media scanned
02-04 15:40:47.980: D/MyTag(25536): Saving: end, 385 ms
When I take a picture with the front camera on the S3, the compression takes a lot longer (I really don't get why...):
02-04 20:24:31.245: D/MyTag(29496): Saving: begin
02-04 20:24:31.245: D/MyTag(29496): Saving: 2 ms, Rotation calculated
02-04 20:24:31.245: D/MyTag(29496): Saving: 95 ms, Decoded ByteArray to Bitmap
02-04 20:24:31.245: D/MyTag(29496): Saving: 160 ms, Bitmap rotated
02-04 20:24:31.245: D/MyTag(29496): Saving: 25 ms, Bitmap watermarked
02-04 20:24:31.245: D/MyTag(29496): Saving: 4548 ms, Bitmap compressed
02-04 20:24:31.245: D/MyTag(29496): Saving: 0 ms, Done saving
02-04 20:24:31.245: D/MyTag(29496): Saving: 3 ms, Media scanned
02-04 20:24:31.245: D/MyTag(29496): Saving: end, 4833 ms