summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/com/android/camera/Camera.java20
-rw-r--r--src/com/android/camera/Exif.java136
-rw-r--r--src/com/android/camera/Storage.java19
3 files changed, 140 insertions, 35 deletions
diff --git a/src/com/android/camera/Camera.java b/src/com/android/camera/Camera.java
index de4ae629..dc7d3657 100644
--- a/src/com/android/camera/Camera.java
+++ b/src/com/android/camera/Camera.java
@@ -1229,22 +1229,6 @@ public class Camera extends NoSearchActivity implements View.OnClickListener,
}
}
- private Bitmap createCaptureBitmap(byte[] data) {
- // This is really stupid...we just want to read the orientation in
- // the jpeg header.
- String filepath = ImageManager.getTempJpegPath();
- int degree = 0;
- if (saveDataToFile(filepath, data)) {
- degree = ImageManager.getExifOrientation(filepath);
- new File(filepath).delete();
- }
-
- // Limit to 50k pixels so we can return it in the intent.
- Bitmap bitmap = Util.makeBitmap(data, 50 * 1024);
- bitmap = Util.rotate(bitmap, degree);
- return bitmap;
- }
-
private void doAttach() {
if (mPausing) {
return;
@@ -1272,7 +1256,9 @@ public class Camera extends NoSearchActivity implements View.OnClickListener,
Util.closeSilently(outputStream);
}
} else {
- Bitmap bitmap = createCaptureBitmap(data);
+ int orientation = Exif.getOrientation(data);
+ Bitmap bitmap = Util.makeBitmap(data, 50 * 1024);
+ bitmap = Util.rotate(bitmap, orientation);
setResult(RESULT_OK,
new Intent("inline-data").putExtra("data", bitmap));
finish();
diff --git a/src/com/android/camera/Exif.java b/src/com/android/camera/Exif.java
new file mode 100644
index 00000000..d1df3e35
--- /dev/null
+++ b/src/com/android/camera/Exif.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.camera;
+
+import android.util.Log;
+
+class Exif {
+ private static final String TAG = "CameraExif";
+
+ public static int getOrientation(byte[] jpeg) {
+ if (jpeg == null) {
+ return 0;
+ }
+
+ int offset = 0;
+ int length = 0;
+
+ // ISO/IEC 10918-1:1993(E)
+ while (offset + 3 < jpeg.length && (jpeg[offset++] & 0xFF) == 0xFF) {
+ int marker = jpeg[offset] & 0xFF;
+
+ // Check if the marker is a padding.
+ if (marker == 0xFF) {
+ continue;
+ }
+ offset++;
+
+ // Check if the marker is SOI or TEM.
+ if (marker == 0xD8 || marker == 0x01) {
+ continue;
+ }
+ // Check if the marker is EOI or SOS.
+ if (marker == 0xD9 || marker == 0xDA) {
+ break;
+ }
+
+ // Get the length and check if it is reasonable.
+ length = pack(jpeg, offset, 2, false);
+ if (length < 2 || offset + length > jpeg.length) {
+ Log.e(TAG, "Invalid length");
+ return 0;
+ }
+
+ // Break if the marker is EXIF in APP1.
+ if (marker == 0xE1 && length >= 8 &&
+ pack(jpeg, offset + 2, 4, false) == 0x45786966 &&
+ pack(jpeg, offset + 6, 2, false) == 0) {
+ offset += 8;
+ length -= 8;
+ break;
+ }
+
+ // Skip other markers.
+ offset += length;
+ length = 0;
+ }
+
+ // JEITA CP-3451 Exif Version 2.2
+ if (length > 8) {
+ // Identify the byte order.
+ int tag = pack(jpeg, offset, 4, false);
+ if (tag != 0x49492A00 && tag != 0x4D4D002A) {
+ Log.e(TAG, "Invalid byte order");
+ return 0;
+ }
+ boolean littleEndian = (tag == 0x49492A00);
+
+ // Get the offset and check if it is reasonable.
+ int count = pack(jpeg, offset + 4, 4, littleEndian) + 2;
+ if (count < 10 || count > length) {
+ Log.e(TAG, "Invalid offset");
+ return 0;
+ }
+ offset += count;
+ length -= count;
+
+ // Get the count and go through all the elements.
+ count = pack(jpeg, offset - 2, 2, littleEndian);
+ while (count-- > 0 && length >= 12) {
+ // Get the tag and check if it is orientation.
+ tag = pack(jpeg, offset, 2, littleEndian);
+ if (tag == 0x0112) {
+ // We do not really care about type and count, do we?
+ int orientation = pack(jpeg, offset + 8, 2, littleEndian);
+ switch (orientation) {
+ case 1:
+ return 0;
+ case 3:
+ return 180;
+ case 6:
+ return 90;
+ case 8:
+ return 270;
+ }
+ Log.i(TAG, "Unsupported orientation");
+ return 0;
+ }
+ offset += 12;
+ length -= 12;
+ }
+ }
+
+ Log.i(TAG, "Orientation not found");
+ return 0;
+ }
+
+ private static int pack(byte[] bytes, int offset, int length,
+ boolean littleEndian) {
+ int step = 1;
+ if (littleEndian) {
+ offset += length - 1;
+ step = -1;
+ }
+
+ int value = 0;
+ while (length-- > 0) {
+ value = (value << 8) | (bytes[offset] & 0xFF);
+ offset += step;
+ }
+ return value;
+ }
+}
diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java
index 69fd534a..ea2ee8e0 100644
--- a/src/com/android/camera/Storage.java
+++ b/src/com/android/camera/Storage.java
@@ -24,7 +24,6 @@ import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.location.Location;
-import android.media.ExifInterface;
import android.net.Uri;
import android.os.Environment;
import android.os.StatFs;
@@ -173,23 +172,7 @@ class Storage {
}
// Get the orientation.
- int orientation = 0;
- try {
- ExifInterface exif = new ExifInterface(path);
- switch (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, -1)) {
- case ExifInterface.ORIENTATION_ROTATE_90:
- orientation = 90;
- break;
- case ExifInterface.ORIENTATION_ROTATE_180:
- orientation = 180;
- break;
- case ExifInterface.ORIENTATION_ROTATE_270:
- orientation = 270;
- break;
- }
- } catch (Exception e) {
- Log.w(TAG, "Failed to read exif", e);
- }
+ int orientation = Exif.getOrientation(jpeg);
// Insert a row through ContentResolver.
ContentValues values = new ContentValues(9);