You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by mu...@apache.org on 2015/05/26 21:40:58 UTC

cordova-plugin-camera git commit: CB-8883 fix picture rotation issue

Repository: cordova-plugin-camera
Updated Branches:
  refs/heads/master b3430e6f8 -> a6cc9271a


CB-8883 fix picture rotation issue


Project: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/commit/a6cc9271
Tree: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/tree/a6cc9271
Diff: http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/diff/a6cc9271

Branch: refs/heads/master
Commit: a6cc9271a05348cdef36abe1767af728e4b912a2
Parents: b3430e6
Author: Murat Sutunc <su...@gmail.com>
Authored: Thu May 14 10:35:53 2015 -0700
Committer: Murat Sutunc <su...@gmail.com>
Committed: Tue May 26 12:32:53 2015 -0700

----------------------------------------------------------------------
 src/windows/CameraProxy.js | 140 +++++++++++++++++++++++++++-------------
 1 file changed, 94 insertions(+), 46 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-plugin-camera/blob/a6cc9271/src/windows/CameraProxy.js
----------------------------------------------------------------------
diff --git a/src/windows/CameraProxy.js b/src/windows/CameraProxy.js
index 841a077..d03a180 100644
--- a/src/windows/CameraProxy.js
+++ b/src/windows/CameraProxy.js
@@ -38,7 +38,6 @@ var webUIApp = Windows.UI.WebUI.WebUIApplication;
 var fileIO = Windows.Storage.FileIO;
 var pickerLocId = Windows.Storage.Pickers.PickerLocationId;
 
-
 module.exports = {
 
     // args will contain :
@@ -198,8 +197,6 @@ function takePictureFromFileWP(successCallback, errorCallback, args) {
                         else {
                             successCallback(URL.createObjectURL(storageFile));
                         }
-
-                        
                     }, function () {
                         errorCallback("Can't access localStorage folder.");
                     });
@@ -313,18 +310,8 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
         captureCancelButton = null,
         capture = null,
         captureSettings = null,
-        CaptureNS = Windows.Media.Capture;
-
-    function cameraPreviewOrientation() {
-        // Rotate the cam since WP8.1 MediaCapture outputs video stream rotated 90° CCW
-        if (screen.msOrientation === "portrait-primary" || screen.msOrientation === "portrait-secondary") {
-            capture.setPreviewRotation(CaptureNS.VideoRotation.clockwise90Degrees);
-        } else if (screen.msOrientation === "landscape-secondary") {
-            capture.setPreviewRotation(CaptureNS.VideoRotation.clockwise180Degrees);
-        } else {
-            capture.setPreviewRotation(CaptureNS.VideoRotation.none);
-        }
-    }
+        CaptureNS = Windows.Media.Capture,
+        sensor = null;
 
     var createCameraUI = function () {
         // Create fullscreen preview
@@ -350,7 +337,7 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
         // This is necessary to detect which camera (front or back) we should use
         var DeviceEnum = Windows.Devices.Enumeration;
         var expectedPanel = cameraDirection === 1 ? DeviceEnum.Panel.front : DeviceEnum.Panel.back;
-        
+
         DeviceEnum.DeviceInformation.findAllAsync(DeviceEnum.DeviceClass.videoCapture).then(function (devices) {
             if (devices.length <= 0) {
                 destroyCameraPreview();
@@ -373,18 +360,24 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
             capturePreview.src = URL.createObjectURL(capture);
             capturePreview.play();
 
-            // Insert preview frame and controls into page
-            document.body.appendChild(capturePreview);
-            document.body.appendChild(captureCancelButton);
-
             // Bind events to controls
-            window.addEventListener('deviceorientation', cameraPreviewOrientation, false);
+            sensor = Windows.Devices.Sensors.SimpleOrientationSensor.getDefault();
+            if (sensor !== null) {
+                sensor.addEventListener("orientationchanged", onOrientationChange);
+            }
             capturePreview.addEventListener('click', captureAction);
             captureCancelButton.addEventListener('click', function () {
                 destroyCameraPreview();
                 errorCallback('Cancelled');
             }, false);
 
+            // Change default orientation
+            if (sensor) {
+                setPreviewRotation(sensor.getCurrentOrientation());
+            } else {
+                setPreviewRotation(Windows.Graphics.Display.DisplayInformation.getForCurrentView().currentOrientation);
+            }
+
             // Get available aspect ratios
             var aspectRatios = getAspectRatios(capture);
 
@@ -395,6 +388,10 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
                 return;
             }
 
+            // Insert preview frame and controls into page
+            document.body.appendChild(capturePreview);
+            document.body.appendChild(captureCancelButton);
+
             if (aspectRatios.indexOf(DEFAULT_ASPECT_RATIO) > -1) {
                 return setAspectRatio(capture, DEFAULT_ASPECT_RATIO);
             } else {
@@ -408,7 +405,9 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
     };
 
     var destroyCameraPreview = function () {
-        window.removeEventListener('deviceorientation', cameraPreviewOrientation, false);
+        if (sensor !== null) {
+            sensor.removeEventListener('orientationchanged', onOrientationChange);
+        }
         capturePreview.pause();
         capturePreview.src = null;
         [capturePreview, captureCancelButton].forEach(function(elem) {
@@ -439,31 +438,34 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
         tempFolder.createFileAsync(fileName, OptUnique)
             .then(function(tempCapturedFile) {
                 return new WinJS.Promise(function (complete) {
-                    var imgStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
-                    capture.capturePhotoToStreamAsync(encodingProperties, imgStream)
+                    var photoStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
+                    var finalStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
+                    capture.capturePhotoToStreamAsync(encodingProperties, photoStream)
                     .then(function() {
-                        return Windows.Graphics.Imaging.BitmapDecoder.createAsync(imgStream);
+                        return Windows.Graphics.Imaging.BitmapDecoder.createAsync(photoStream);
                     })
                     .then(function(dec) {
-                        return Windows.Graphics.Imaging.BitmapEncoder.createForTranscodingAsync(imgStream, dec);
+                        finalStream.size = 0; // BitmapEncoder requires the output stream to be empty
+                        return Windows.Graphics.Imaging.BitmapEncoder.createForTranscodingAsync(finalStream, dec);
                     })
                     .then(function(enc) {
-                        // We need to rotate the photo 90° CW because by default wp8.1 takes 90° CCW rotated photos.
-                        enc.bitmapTransform.rotation = Windows.Graphics.Imaging.BitmapRotation.clockwise90Degrees;
+                        // We need to rotate the photo wrt sensor orientation
+                        enc.bitmapTransform.rotation = orientationToRotation(sensor.getCurrentOrientation());
                         return enc.flushAsync();
                     })
                     .then(function() {
                         return tempCapturedFile.openAsync(Windows.Storage.FileAccessMode.readWrite);
                     })
                     .then(function(fileStream) {
-                        imgStream.seek(0); // required for win8.1 emulator
-                        return Windows.Storage.Streams.RandomAccessStream.copyAsync(imgStream, fileStream);
+                        return Windows.Storage.Streams.RandomAccessStream.copyAsync(finalStream, fileStream);
                     })
                     .done(function() {
-                        imgStream.close();
+                        photoStream.close();
+                        finalStream.close();
                         complete(tempCapturedFile);
                     }, function() {
-                        imgStream.close();
+                        photoStream.close();
+                        finalStream.close();
                         throw new Error("An error has occured while capturing the photo.");
                     });
                 });
@@ -484,16 +486,16 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
     };
 
     var getAspectRatios = function (capture) {
-        var getMSProps = capture.videoDeviceController.getAvailableMediaStreamProperties;
-        var photoAspectRatios = getMSProps(CapMSType.photo).map(function (element) {
+        var videoDeviceController = capture.videoDeviceController;
+        var photoAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.photo).map(function (element) {
             return (element.width / element.height).toFixed(1);
         }).filter(function (element, index, array) { return (index === array.indexOf(element)); });
 
-        var videoAspectRatios = getMSProps(CapMSType.videoRecord).map(function (element) {
+        var videoAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoRecord).map(function (element) {
             return (element.width / element.height).toFixed(1);
         }).filter(function (element, index, array) { return (index === array.indexOf(element)); });
 
-        var videoPreviewAspectRatios = getMSProps(CapMSType.videoPreview).map(function (element) {
+        var videoPreviewAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoPreview).map(function (element) {
             return (element.width / element.height).toFixed(1);
         }).filter(function (element, index, array) { return (index === array.indexOf(element)); });
 
@@ -514,8 +516,8 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
 
     var setAspectRatio = function (capture, aspect) {
         // Max photo resolution with desired aspect ratio
-        var getMSProps = capture.videoDeviceController.getAvailableMediaStreamProperties;
-        var photoResolution = getMSProps(CapMSType.photo)
+        var videoDeviceController = capture.videoDeviceController;
+        var photoResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.photo)
             .filter(function (elem) {
                 return ((elem.width / elem.height).toFixed(1) === aspect);
             })
@@ -524,7 +526,7 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
             });
 
         // Max video resolution with desired aspect ratio
-        var videoRecordResolution = getMSProps(CapMSType.videoRecord)
+        var videoRecordResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoRecord)
             .filter(function (elem) {
                 return ((elem.width / elem.height).toFixed(1) === aspect);
             })
@@ -533,7 +535,7 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
             });
 
         // Max video preview resolution with desired aspect ratio
-        var videoPreviewResolution = getMSProps(CapMSType.videoPreview)
+        var videoPreviewResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoPreview)
             .filter(function (elem) {
                 return ((elem.width / elem.height).toFixed(1) === aspect);
             })
@@ -541,17 +543,63 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
                 return (prop1.width * prop1.height) > (prop2.width * prop2.height) ? prop1 : prop2;
             });
 
-        var setMSPropsAsync = capture.videoDeviceController.setMediaStreamPropertiesAsync;
-
-        return setMSPropsAsync(CapMSType.photo, photoResolution)
+        return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.photo, photoResolution)
             .then(function () {
-                return setMSPropsAsync(CapMSType.videoPreview, videoPreviewResolution);
+                return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.videoPreview, videoPreviewResolution);
             })
             .then(function () {
-                return setMSPropsAsync(CapMSType.videoRecord, videoRecordResolution);
+                return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.videoRecord, videoRecordResolution);
             });
     };
 
+    /**
+     * When the phone orientation change, get the event and change camera preview rotation
+     * @param  {Object} e - SimpleOrientationSensorOrientationChangedEventArgs
+     */
+    var onOrientationChange = function (e) {
+        setPreviewRotation(e.orientation);
+    };
+
+    /**
+     * Converts SimpleOrientation to a VideoRotation to remove difference between camera sensor orientation
+     * and video orientation
+     * @param  {number} orientation - Windows.Devices.Sensors.SimpleOrientation
+     * @return {number} - Windows.Media.Capture.VideoRotation
+     */
+    var orientationToRotation = function (orientation) {
+        // VideoRotation enumerable and BitmapRotation enumerable have the same values
+        // https://msdn.microsoft.com/en-us/library/windows/apps/windows.media.capture.videorotation.aspx
+        // https://msdn.microsoft.com/en-us/library/windows/apps/windows.graphics.imaging.bitmaprotation.aspx
+
+        switch (orientation) {
+            // portrait
+            case Windows.Devices.Sensors.SimpleOrientation.notRotated:
+                return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
+            // landscape
+            case Windows.Devices.Sensors.SimpleOrientation.rotated90DegreesCounterclockwise:
+                return Windows.Media.Capture.VideoRotation.none;
+            // portrait-flipped (not supported by WinPhone Apps)
+            case Windows.Devices.Sensors.SimpleOrientation.rotated180DegreesCounterclockwise:
+                // Falling back to portrait default
+                return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
+            // landscape-flipped
+            case Windows.Devices.Sensors.SimpleOrientation.rotated270DegreesCounterclockwise:
+                return Windows.Media.Capture.VideoRotation.clockwise180Degrees;
+            // faceup & facedown
+            default:
+                // Falling back to portrait default
+                return Windows.Media.Capture.VideoRotation.clockwise90Degrees;
+        }
+    };
+
+    /**
+     * Rotates the current MediaCapture's video
+     * @param {number} orientation - Windows.Devices.Sensors.SimpleOrientation
+     */
+    var setPreviewRotation = function(orientation) {
+        capture.setPreviewRotation(orientationToRotation(orientation));
+    };
+
     try {
         createCameraUI();
         startCameraPreview();
@@ -569,7 +617,7 @@ function takePictureFromCameraWindows(successCallback, errorCallback, args) {
         saveToPhotoAlbum = args[9],
         WMCapture = Windows.Media.Capture,
         cameraCaptureUI = new WMCapture.CameraCaptureUI();
-        
+
     cameraCaptureUI.photoSettings.allowCropping = allowCrop;
 
     if (encodingType == Camera.EncodingType.PNG) {


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@cordova.apache.org
For additional commands, e-mail: commits-help@cordova.apache.org