diff --git a/src/windows/CameraProxy.js b/src/windows/CameraProxy.js index 19d26e2..54019a8 100644 --- a/src/windows/CameraProxy.js +++ b/src/windows/CameraProxy.js @@ -289,6 +289,17 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) { captureSettings = null, CaptureNS = Windows.Media.Capture; + function cameraPreviewOrientation(arg) { + // Rotate the cam since WP8.1 MediaCapture outputs video stream rotated 90° CCW + if (screen.msOrientation === "portrait-primary" || screen.msOrientation === "portrait-secondary") { + capture.setPreviewRotation(Windows.Media.Capture.VideoRotation.clockwise90Degrees); + } else if (screen.msOrientation === "landscape-secondary") { + capture.setPreviewRotation(Windows.Media.Capture.VideoRotation.clockwise180Degrees); + } else { + capture.setPreviewRotation(Windows.Media.Capture.VideoRotation.none); + } + } + var createCameraUI = function () { // Create fullscreen preview capturePreview = document.createElement("video"); @@ -327,9 +338,6 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) { }); capture.initializeAsync(captureSettings).done(function () { - // This is necessary since WP8.1 MediaCapture outputs video stream rotated 90 degrees CCW - // TODO: This can be not consistent across devices, need additional testing on various devices - capture.setPreviewRotation(Windows.Media.Capture.VideoRotation.clockwise90Degrees); // msdn.microsoft.com/en-us/library/windows/apps/hh452807.aspx capturePreview.msZoom = true; capturePreview.src = URL.createObjectURL(capture); @@ -340,6 +348,7 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) { document.body.appendChild(captureCancelButton); // Bind events to controls + window.addEventListener('deviceorientation', cameraPreviewOrientation, false); capturePreview.addEventListener('click', captureAction); captureCancelButton.addEventListener('click', function () { destroyCameraPreview(); @@ -353,6 +362,7 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) { }; var destroyCameraPreview = function () { + window.removeEventListener('deviceorientation', cameraPreviewOrientation, false); capturePreview.pause(); capturePreview.src = null; [capturePreview, captureCancelButton].forEach(function(elem) { @@ -371,8 +381,7 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) { var encodingProperties, fileName, generateUniqueCollisionOption = Windows.Storage.CreationCollisionOption.generateUniqueName, - tempFolder = Windows.Storage.ApplicationData.current.temporaryFolder, - capturedFile; + tempFolder = Windows.Storage.ApplicationData.current.temporaryFolder; if (encodingType == Camera.EncodingType.PNG) { fileName = 'photo.png'; @@ -384,29 +393,55 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) { tempFolder.createFileAsync(fileName, generateUniqueCollisionOption) .then(function(tempCapturedFile) { - capturedFile = tempCapturedFile; - return capture.capturePhotoToStorageFileAsync(encodingProperties, capturedFile); + return new WinJS.Promise(function (complete) { + var imgStream = new Windows.Storage.Streams.InMemoryRandomAccessStream(); + capture.capturePhotoToStreamAsync(encodingProperties, imgStream) + .then(function() { + return Windows.Graphics.Imaging.BitmapDecoder.createAsync(imgStream); + }) + .then(function(dec) { + return Windows.Graphics.Imaging.BitmapEncoder.createForTranscodingAsync(imgStream, 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; + return enc.flushAsync(); + }) + .then(function() { + return tempCapturedFile.openAsync(Windows.Storage.FileAccessMode.readWrite); + }) + .then(function(fileStream) { + return Windows.Storage.Streams.RandomAccessStream.copyAsync(imgStream, fileStream); + }) + .done(function() { + imgStream.close(); + complete(tempCapturedFile); + }, function() { + imgStream.close(); + throw new Error("An error has occured while capturing the photo."); + }); + }) }) - .done(function() { + .done(function(capturedFile) { destroyCameraPreview(); // success callback for capture operation - var success = function(capturedfile) { + var success = function(capturedPhoto) { if (destinationType == Camera.DestinationType.FILE_URI || destinationType == Camera.DestinationType.NATIVE_URI) { if (targetHeight > 0 && targetWidth > 0) { - resizeImage(successCallback, errorCallback, capturedFile, targetWidth, targetHeight, encodingType); + resizeImage(successCallback, errorCallback, capturedPhoto, targetWidth, targetHeight, encodingType); } else { - capturedfile.copyAsync(Windows.Storage.ApplicationData.current.localFolder, capturedfile.name, generateUniqueCollisionOption).done(function(copiedfile) { + capturedPhoto.copyAsync(Windows.Storage.ApplicationData.current.localFolder, capturedPhoto.name, generateUniqueCollisionOption).done(function(copiedfile) { successCallback("ms-appdata:///local/" + copiedfile.name); }, errorCallback); } } else { if (targetHeight > 0 && targetWidth > 0) { - resizeImageBase64(successCallback, errorCallback, capturedfile, targetWidth, targetHeight); + resizeImageBase64(successCallback, errorCallback, capturedPhoto, targetWidth, targetHeight); } else { - Windows.Storage.FileIO.readBufferAsync(capturedfile).done(function(buffer) { + Windows.Storage.FileIO.readBufferAsync(capturedPhoto).done(function(buffer) { var strBase64 = Windows.Security.Cryptography.CryptographicBuffer.encodeToBase64String(buffer); - capturedfile.deleteAsync().done(function() { + capturedPhoto.deleteAsync().done(function() { successCallback(strBase64); }, function(err) { errorCallback(err);