Merge "Import revised translations. DO NOT MERGE" into ics-mr1
diff --git a/src/com/android/camera/Storage.java b/src/com/android/camera/Storage.java
index 38a6d48..ea281a9 100644
--- a/src/com/android/camera/Storage.java
+++ b/src/com/android/camera/Storage.java
@@ -52,7 +52,7 @@
public static Uri addImage(ContentResolver resolver, String title, long date,
Location location, int orientation, byte[] jpeg, int width, int height) {
// Save the image.
- String path = DIRECTORY + '/' + title + ".jpg";
+ String path = generateFilepath(title);
FileOutputStream out = null;
try {
out = new FileOutputStream(path);
@@ -98,6 +98,10 @@
return uri;
}
+ public static String generateFilepath(String title) {
+ return DIRECTORY + '/' + title + ".jpg";
+ }
+
public static long getAvailableSpace() {
String state = Environment.getExternalStorageState();
Log.d(TAG, "External storage state=" + state);
diff --git a/src/com/android/camera/Util.java b/src/com/android/camera/Util.java
index ba8a4f7..d6ebb0a 100644
--- a/src/com/android/camera/Util.java
+++ b/src/com/android/camera/Util.java
@@ -350,6 +350,12 @@
return result;
}
+ public static int getCameraOrientation(int cameraId) {
+ Camera.CameraInfo info = new Camera.CameraInfo();
+ Camera.getCameraInfo(cameraId, info);
+ return info.orientation;
+ }
+
public static int roundOrientation(int orientation, int orientationHistory) {
boolean changeOrientation = false;
if (orientationHistory == OrientationEventListener.ORIENTATION_UNKNOWN) {
diff --git a/src/com/android/camera/VideoCamera.java b/src/com/android/camera/VideoCamera.java
index 1e90544..80a9a4c 100755
--- a/src/com/android/camera/VideoCamera.java
+++ b/src/com/android/camera/VideoCamera.java
@@ -192,6 +192,7 @@
private String mPrefVideoEffectDefault;
private boolean mResetEffect = true;
public static final String RESET_EFFECT_EXTRA = "reset_effect";
+ public static final String BACKGROUND_URI_GALLERY_EXTRA = "background_uri_gallery";
private boolean mMediaRecorderRecording = false;
private long mRecordingStartTime;
@@ -371,6 +372,9 @@
// Do not reset the effect if users are switching between back and front
// cameras.
mResetEffect = getIntent().getBooleanExtra(RESET_EFFECT_EXTRA, true);
+ // If background replacement was on when the camera was switched, the
+ // background uri will be sent via the intent.
+ mEffectUriFromGallery = getIntent().getStringExtra(BACKGROUND_URI_GALLERY_EXTRA);
resetEffect();
/*
@@ -2112,14 +2116,19 @@
// Restart the activity to have a crossfade animation.
// TODO: Use SurfaceTexture to implement a better and faster
// animation.
+ Intent intent;
if (mIsVideoCaptureIntent) {
// If the intent is video capture, stay in video capture mode.
- Intent intent = getIntent();
- intent.putExtra(RESET_EFFECT_EXTRA, false);
- MenuHelper.gotoVideoMode(this, intent);
+ intent = getIntent();
} else {
- MenuHelper.gotoVideoMode(this, false);
+ intent = new Intent(MediaStore.INTENT_ACTION_VIDEO_CAMERA);
}
+ // To maintain the same background in background replacer, we
+ // need to send the background video uri via the Intent (apart
+ // from the condition that the effects should not be reset).
+ intent.putExtra(BACKGROUND_URI_GALLERY_EXTRA, mEffectUriFromGallery);
+ intent.putExtra(RESET_EFFECT_EXTRA, false);
+ MenuHelper.gotoVideoMode(this, intent);
finish();
} else {
readVideoPreferences();
diff --git a/src/com/android/camera/panorama/PanoramaActivity.java b/src/com/android/camera/panorama/PanoramaActivity.java
index e4c8d98..67f187b 100755
--- a/src/com/android/camera/panorama/PanoramaActivity.java
+++ b/src/com/android/camera/panorama/PanoramaActivity.java
@@ -52,6 +52,7 @@
import android.hardware.Camera.Sound;
import android.hardware.Sensor;
import android.hardware.SensorManager;
+import android.media.ExifInterface;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
@@ -70,6 +71,7 @@
import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.IOException;
import java.util.List;
/**
@@ -172,6 +174,8 @@
// The value could be 0, 90, 180, 270 for the 4 different orientations measured in clockwise
// respectively.
private int mDeviceOrientation;
+ private int mDeviceOrientationAtCapture;
+ private int mCameraOrientation;
private int mOrientationCompensation;
private RotateDialogController mRotateDialog;
@@ -338,7 +342,9 @@
private void openCamera() {
try {
- mCameraDevice = Util.openCamera(this, CameraHolder.instance().getBackCameraId());
+ int backCameraId = CameraHolder.instance().getBackCameraId();
+ mCameraDevice = Util.openCamera(this, backCameraId);
+ mCameraOrientation = Util.getCameraOrientation(backCameraId);
} catch (CameraHardwareException e) {
Util.showErrorAndFinish(this, R.string.cannot_connect_camera);
return;
@@ -568,6 +574,7 @@
mPanoProgressBar.setIndicatorWidth(20);
mPanoProgressBar.setMaxProgress(DEFAULT_SWEEP_ANGLE);
mPanoProgressBar.setVisibility(View.VISIBLE);
+ mDeviceOrientationAtCapture = mDeviceOrientation;
keepScreenOn();
}
@@ -799,7 +806,13 @@
} else if (!jpeg.isValid) { // Error when generating mosaic.
mMainHandler.sendEmptyMessage(MSG_GENERATE_FINAL_MOSAIC_ERROR);
} else {
- int orientation = Exif.getOrientation(jpeg.data);
+ // The panorama image returned from the library is orientated based on the
+ // natural orientation of a camera. We need to set an orientation for the image
+ // in its EXIF header, so the image can be displayed correctly.
+ // The orientation is calculated from compensating the
+ // device orientation at capture and the camera orientation respective to
+ // the natural orientation of the device.
+ int orientation = (mDeviceOrientationAtCapture + mCameraOrientation) % 360;
Uri uri = savePanorama(jpeg.data, jpeg.width, jpeg.height, orientation);
if (uri != null) {
// Create a thumbnail whose width or height is equal or bigger
@@ -812,6 +825,7 @@
Math.max(widthRatio, heightRatio));
mThumbnail = Thumbnail.createThumbnail(
jpeg.data, orientation, inSampleSize, uri);
+ Util.broadcastNewPicture(PanoramaActivity.this, uri);
}
mMainHandler.sendMessage(
mMainHandler.obtainMessage(MSG_RESET_TO_PREVIEW_WITH_THUMBNAIL));
@@ -889,14 +903,42 @@
private Uri savePanorama(byte[] jpegData, int width, int height, int orientation) {
if (jpegData != null) {
- String imagePath = PanoUtil.createName(
+ String filename = PanoUtil.createName(
getResources().getString(R.string.pano_file_name_format), mTimeTaken);
- return Storage.addImage(getContentResolver(), imagePath, mTimeTaken, null,
+ Uri uri = Storage.addImage(getContentResolver(), filename, mTimeTaken, null,
orientation, jpegData, width, height);
+ if (uri != null && orientation != 0) {
+ String filepath = Storage.generateFilepath(filename);
+ try {
+ // Save the orientation in EXIF.
+ ExifInterface exif = new ExifInterface(filepath);
+ exif.setAttribute(ExifInterface.TAG_ORIENTATION,
+ getExifOrientation(orientation));
+ exif.saveAttributes();
+ } catch (IOException e) {
+ Log.e(TAG, "cannot set exif data: " + filepath);
+ }
+ }
+ return uri;
}
return null;
}
+ private static String getExifOrientation(int orientation) {
+ switch (orientation) {
+ case 0:
+ return String.valueOf(ExifInterface.ORIENTATION_NORMAL);
+ case 90:
+ return String.valueOf(ExifInterface.ORIENTATION_ROTATE_90);
+ case 180:
+ return String.valueOf(ExifInterface.ORIENTATION_ROTATE_180);
+ case 270:
+ return String.valueOf(ExifInterface.ORIENTATION_ROTATE_270);
+ default:
+ throw new AssertionError("invalid: " + orientation);
+ }
+ }
+
private void clearMosaicFrameProcessorIfNeeded() {
if (!mPausing || mThreadRunning) return;
mMosaicFrameProcessor.clear();
diff --git a/src/com/android/camera/ui/IndicatorControlBar.java b/src/com/android/camera/ui/IndicatorControlBar.java
index 197c594..615a5ba 100644
--- a/src/com/android/camera/ui/IndicatorControlBar.java
+++ b/src/com/android/camera/ui/IndicatorControlBar.java
@@ -57,7 +57,9 @@
// Add CameraPicker control.
initializeCameraPicker();
- mCameraPicker.setBackgroundResource(R.drawable.bg_pressed);
+ if (mCameraPicker != null) {
+ mCameraPicker.setBackgroundResource(R.drawable.bg_pressed);
+ }
// Add the ZoomControl if supported.
if (zoomSupported) {
diff --git a/src/com/android/camera/ui/IndicatorControlWheel.java b/src/com/android/camera/ui/IndicatorControlWheel.java
index 90d8ba8..0948346 100644
--- a/src/com/android/camera/ui/IndicatorControlWheel.java
+++ b/src/com/android/camera/ui/IndicatorControlWheel.java
@@ -204,32 +204,36 @@
if (mInAnimation) return -1;
int count = getChildCountByLevel(mCurrentLevel);
if (count == 0) return -1;
- int startIndex = 0;
int sectors = count - 1;
+ int startIndex = (mCurrentLevel == 0) ? 0 : mSecondLevelStartIndex;
+ int endIndex;
+ if (mCurrentLevel == 0) {
+ // Skip the first component if it is zoom control, as we will
+ // deal with it specifically.
+ if (mZoomControl != null) startIndex++;
+ endIndex = mSecondLevelStartIndex - 1;
+ } else {
+ endIndex = getChildCount() - 1;
+ }
// Check which indicator is touched.
- if ((delta >= (mStartVisibleRadians[mCurrentLevel] - HIGHLIGHT_RADIANS / 2)) &&
- (delta <= (mEndVisibleRadians[mCurrentLevel] + HIGHLIGHT_RADIANS / 2))) {
+ double halfTouchSectorRadians = mTouchSectorRadians[mCurrentLevel];
+ if ((delta >= (mChildRadians[startIndex] - halfTouchSectorRadians)) &&
+ (delta <= (mChildRadians[endIndex] + halfTouchSectorRadians))) {
int index = 0;
- if (mCurrentLevel == 0) {
- // Skip the first component if it is zoom control, as we will
- // deal with it specifically.
- if (mZoomControl != null) startIndex++;
- } else {
- startIndex = mSecondLevelStartIndex;
- index = (int) ((delta - mStartVisibleRadians[mCurrentLevel])
+ if (mCurrentLevel == 1) {
+ index = (int) ((delta - mChildRadians[startIndex])
/ mSectorRadians[mCurrentLevel]);
// greater than the center of ending indicator
if (index > sectors) return (startIndex + sectors);
// less than the center of starting indicator
if (index < 0) return startIndex;
}
-
if (delta <= (mChildRadians[startIndex + index]
- + mTouchSectorRadians[mCurrentLevel] / 2)) {
+ + halfTouchSectorRadians)) {
return (startIndex + index);
}
if (delta >= (mChildRadians[startIndex + index + 1]
- - mTouchSectorRadians[mCurrentLevel] / 2)) {
+ - halfTouchSectorRadians)) {
return (startIndex + index + 1);
}