fix #17, improve photo saving rotation

This commit is contained in:
tibbi
2017-03-25 17:59:25 +01:00
parent 5e9e1798c5
commit 726ab0acd2
6 changed files with 46 additions and 24 deletions

View File

@ -32,7 +32,7 @@ android {
} }
dependencies { dependencies {
compile 'com.simplemobiletools:commons:2.13.9' compile 'com.simplemobiletools:commons:2.14.6'
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
} }

View File

@ -1,12 +1,18 @@
package com.simplemobiletools.camera package com.simplemobiletools.camera
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.media.ExifInterface
import android.net.Uri import android.net.Uri
import android.os.AsyncTask import android.os.AsyncTask
import android.os.Environment import android.os.Environment
import android.util.Log import android.util.Log
import com.simplemobiletools.camera.Preview.Companion.config import com.simplemobiletools.camera.Preview.Companion.config
import com.simplemobiletools.camera.activities.MainActivity import com.simplemobiletools.camera.activities.MainActivity
import com.simplemobiletools.camera.extensions.compensateDeviceRotation
import com.simplemobiletools.camera.extensions.getOutputMediaFile import com.simplemobiletools.camera.extensions.getOutputMediaFile
import com.simplemobiletools.camera.extensions.getPreviewRotation
import com.simplemobiletools.commons.extensions.getFileDocument import com.simplemobiletools.commons.extensions.getFileDocument
import com.simplemobiletools.commons.extensions.needsStupidWritePermissions import com.simplemobiletools.commons.extensions.needsStupidWritePermissions
import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.extensions.toast
@ -16,7 +22,7 @@ import java.io.IOException
import java.io.OutputStream import java.io.OutputStream
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
class PhotoProcessor(val activity: MainActivity, val uri: Uri?) : AsyncTask<ByteArray, Void, String>() { class PhotoProcessor(val activity: MainActivity, val uri: Uri?, val currCameraId: Int) : AsyncTask<ByteArray, Void, String>() {
companion object { companion object {
private val TAG = PhotoProcessor::class.java.simpleName private val TAG = PhotoProcessor::class.java.simpleName
private var mActivity: WeakReference<MainActivity>? = null private var mActivity: WeakReference<MainActivity>? = null
@ -40,6 +46,7 @@ class PhotoProcessor(val activity: MainActivity, val uri: Uri?) : AsyncTask<Byte
return "" return ""
} }
val data = params[0]
val photoFile = File(path) val photoFile = File(path)
if (activity.needsStupidWritePermissions(path)) { if (activity.needsStupidWritePermissions(path)) {
if (config.treeUri.isEmpty()) { if (config.treeUri.isEmpty()) {
@ -56,8 +63,20 @@ class PhotoProcessor(val activity: MainActivity, val uri: Uri?) : AsyncTask<Byte
fos = FileOutputStream(photoFile) fos = FileOutputStream(photoFile)
} }
val data = params[0] var image = BitmapFactory.decodeByteArray(data, 0, data.size)
fos?.write(data) val exif = ExifInterface(photoFile.toString())
val deviceRot = MainActivity.mOrientation.compensateDeviceRotation(currCameraId)
val previewRot = activity.getPreviewRotation(currCameraId)
val imageRot = when (exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_UNDEFINED)) {
ExifInterface.ORIENTATION_ROTATE_90 -> 90
ExifInterface.ORIENTATION_ROTATE_180 -> 180
ExifInterface.ORIENTATION_ROTATE_270 -> 270
else -> 0
}
image = rotate(image, imageRot + deviceRot + previewRot)
image.compress(Bitmap.CompressFormat.JPEG, 80, fos)
fos?.close() fos?.close()
return photoFile.absolutePath return photoFile.absolutePath
} catch (e: Exception) { } catch (e: Exception) {
@ -73,8 +92,18 @@ class PhotoProcessor(val activity: MainActivity, val uri: Uri?) : AsyncTask<Byte
return "" return ""
} }
fun rotate(bitmap: Bitmap, degree: Int): Bitmap {
val width = bitmap.width
val height = bitmap.height
val matrix = Matrix()
matrix.setRotate(degree.toFloat())
return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true)
}
override fun onPostExecute(path: String) { override fun onPostExecute(path: String) {
super.onPostExecute(path) super.onPostExecute(path)
mActivity?.get()?.mediaSaved(path) mActivity?.get()?.mediaSaved(path)
} }

View File

@ -252,12 +252,8 @@ class Preview : ViewGroup, SurfaceHolder.Callback, MediaScannerConnection.OnScan
fun takePicture() { fun takePicture() {
if (mCanTakePicture) { if (mCanTakePicture) {
var rotation = mActivity.getMediaRotation(mCurrCameraId)
rotation += mCallback.getCurrentOrientation().compensateDeviceRotation(mCurrCameraId)
val selectedResolution = getSelectedResolution() val selectedResolution = getSelectedResolution()
mParameters!!.setPictureSize(selectedResolution.width, selectedResolution.height); mParameters!!.setPictureSize(selectedResolution.width, selectedResolution.height);
mParameters!!.setRotation(rotation % 360)
if (config.isSoundEnabled) { if (config.isSoundEnabled) {
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
@ -287,7 +283,7 @@ class Preview : ViewGroup, SurfaceHolder.Callback, MediaScannerConnection.OnScan
resumePreview() resumePreview()
} }
PhotoProcessor(mActivity, mTargetUri).execute(data) PhotoProcessor(mActivity, mTargetUri, mCurrCameraId).execute(data)
} }
private fun resumePreview() { private fun resumePreview() {
@ -534,13 +530,12 @@ class Preview : ViewGroup, SurfaceHolder.Callback, MediaScannerConnection.OnScan
} catch (e: Exception) { } catch (e: Exception) {
setupFailed(e) setupFailed(e)
} }
} else { } else {
mRecorder!!.setOutputFile(mCurrVideoPath) mRecorder!!.setOutputFile(mCurrVideoPath)
} }
mRecorder!!.setPreviewDisplay(mSurfaceHolder.surface) mRecorder!!.setPreviewDisplay(mSurfaceHolder.surface)
val rotation = mActivity.getFinalRotation(mCurrCameraId, mCallback.getCurrentOrientation()) val rotation = mActivity.getMediaRotation(mCurrCameraId)
mInitVideoRotation = rotation mInitVideoRotation = rotation
mRecorder!!.setOrientationHint(rotation) mRecorder!!.setOrientationHint(rotation)
@ -571,7 +566,7 @@ class Preview : ViewGroup, SurfaceHolder.Callback, MediaScannerConnection.OnScan
} }
private fun startRecording() { private fun startRecording() {
if (mInitVideoRotation != mActivity.getFinalRotation(mCurrCameraId, mCallback.getCurrentOrientation())) { if (mInitVideoRotation != mActivity.getFinalRotation(mCurrCameraId, MainActivity.mOrientation)) {
cleanupRecorder() cleanupRecorder()
initRecorder() initRecorder()
} }
@ -659,8 +654,6 @@ class Preview : ViewGroup, SurfaceHolder.Callback, MediaScannerConnection.OnScan
fun setIsCameraAvailable(available: Boolean) fun setIsCameraAvailable(available: Boolean)
fun getCurrentOrientation(): Int
fun videoSaved(uri: Uri) fun videoSaved(uri: Uri)
fun drawFocusRect(x: Int, y: Int) fun drawFocusRect(x: Int, y: Int)

View File

@ -52,9 +52,9 @@ class MainActivity : SimpleActivity(), SensorEventListener, PreviewListener, Pho
private var mIsVideoCaptureIntent = false private var mIsVideoCaptureIntent = false
private var mIsHardwareShutterHandled = false private var mIsHardwareShutterHandled = false
private var mCurrVideoRecTimer = 0 private var mCurrVideoRecTimer = 0
private var mOrientation = 0
private var mCurrCameraId = 0 private var mCurrCameraId = 0
private var mLastHandledOrientation = 0 private var mLastHandledOrientation = 0
var mOrientation = 0
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -531,8 +531,6 @@ class MainActivity : SimpleActivity(), SensorEventListener, PreviewListener, Pho
mIsCameraAvailable = available mIsCameraAvailable = available
} }
override fun getCurrentOrientation() = mOrientation
override fun videoSaved(uri: Uri) { override fun videoSaved(uri: Uri) {
setupPreviewImage(mIsInPhotoMode) setupPreviewImage(mIsInPhotoMode)
if (mIsVideoCaptureIntent) { if (mIsVideoCaptureIntent) {

View File

@ -6,7 +6,7 @@ import android.view.Surface
fun Activity.getPreviewRotation(cameraId: Int): Int { fun Activity.getPreviewRotation(cameraId: Int): Int {
val info = getCameraInfo(cameraId) val info = getCameraInfo(cameraId)
val degrees = getRotationDegrees(this) val degrees = getDeviceRotationDegrees()
var result: Int var result: Int
if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
@ -20,7 +20,7 @@ fun Activity.getPreviewRotation(cameraId: Int): Int {
} }
fun Activity.getMediaRotation(cameraId: Int): Int { fun Activity.getMediaRotation(cameraId: Int): Int {
val degrees = getRotationDegrees(this) val degrees = getDeviceRotationDegrees()
val info = getCameraInfo(cameraId) val info = getCameraInfo(cameraId)
return if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { return if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
(360 + info.orientation + degrees) % 360 (360 + info.orientation + degrees) % 360
@ -30,11 +30,10 @@ fun Activity.getMediaRotation(cameraId: Int): Int {
fun Activity.getFinalRotation(currCameraId: Int, deviceOrientation: Int): Int { fun Activity.getFinalRotation(currCameraId: Int, deviceOrientation: Int): Int {
var rotation = getMediaRotation(currCameraId) var rotation = getMediaRotation(currCameraId)
rotation += deviceOrientation.compensateDeviceRotation(currCameraId)
return rotation % 360 return rotation % 360
} }
private fun getRotationDegrees(activity: Activity) = when (activity.windowManager.defaultDisplay.rotation) { fun Activity.getDeviceRotationDegrees() = when (windowManager.defaultDisplay.rotation) {
Surface.ROTATION_90 -> 90 Surface.ROTATION_90 -> 90
Surface.ROTATION_180 -> 180 Surface.ROTATION_180 -> 180
Surface.ROTATION_270 -> 270 Surface.ROTATION_270 -> 270

View File

@ -7,9 +7,12 @@ import com.simplemobiletools.camera.ORIENT_LANDSCAPE_RIGHT
fun Int.compensateDeviceRotation(currCameraId: Int): Int { fun Int.compensateDeviceRotation(currCameraId: Int): Int {
val isFrontCamera = currCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT val isFrontCamera = currCameraId == Camera.CameraInfo.CAMERA_FACING_FRONT
return if (this == ORIENT_LANDSCAPE_LEFT) { return if (this == ORIENT_LANDSCAPE_LEFT) {
if (isFrontCamera) 90 else 270 270
} else if (this == ORIENT_LANDSCAPE_RIGHT) { } else if (this == ORIENT_LANDSCAPE_RIGHT) {
if (isFrontCamera) 270 else 90 90
} else } else if (isFrontCamera) {
180
} else {
0 0
}
} }