mirror of
https://github.com/apache/cordova-plugin-camera.git
synced 2025-01-31 12:42:50 +08:00
CB-8883 fix picture rotation issue
This commit is contained in:
parent
b3430e6f80
commit
a6cc9271a0
@ -38,7 +38,6 @@ var webUIApp = Windows.UI.WebUI.WebUIApplication;
|
|||||||
var fileIO = Windows.Storage.FileIO;
|
var fileIO = Windows.Storage.FileIO;
|
||||||
var pickerLocId = Windows.Storage.Pickers.PickerLocationId;
|
var pickerLocId = Windows.Storage.Pickers.PickerLocationId;
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
||||||
// args will contain :
|
// args will contain :
|
||||||
@ -198,8 +197,6 @@ function takePictureFromFileWP(successCallback, errorCallback, args) {
|
|||||||
else {
|
else {
|
||||||
successCallback(URL.createObjectURL(storageFile));
|
successCallback(URL.createObjectURL(storageFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}, function () {
|
}, function () {
|
||||||
errorCallback("Can't access localStorage folder.");
|
errorCallback("Can't access localStorage folder.");
|
||||||
});
|
});
|
||||||
@ -313,18 +310,8 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
|
|||||||
captureCancelButton = null,
|
captureCancelButton = null,
|
||||||
capture = null,
|
capture = null,
|
||||||
captureSettings = null,
|
captureSettings = null,
|
||||||
CaptureNS = Windows.Media.Capture;
|
CaptureNS = Windows.Media.Capture,
|
||||||
|
sensor = null;
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var createCameraUI = function () {
|
var createCameraUI = function () {
|
||||||
// Create fullscreen preview
|
// Create fullscreen preview
|
||||||
@ -373,18 +360,24 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
|
|||||||
capturePreview.src = URL.createObjectURL(capture);
|
capturePreview.src = URL.createObjectURL(capture);
|
||||||
capturePreview.play();
|
capturePreview.play();
|
||||||
|
|
||||||
// Insert preview frame and controls into page
|
|
||||||
document.body.appendChild(capturePreview);
|
|
||||||
document.body.appendChild(captureCancelButton);
|
|
||||||
|
|
||||||
// Bind events to controls
|
// 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);
|
capturePreview.addEventListener('click', captureAction);
|
||||||
captureCancelButton.addEventListener('click', function () {
|
captureCancelButton.addEventListener('click', function () {
|
||||||
destroyCameraPreview();
|
destroyCameraPreview();
|
||||||
errorCallback('Cancelled');
|
errorCallback('Cancelled');
|
||||||
}, false);
|
}, false);
|
||||||
|
|
||||||
|
// Change default orientation
|
||||||
|
if (sensor) {
|
||||||
|
setPreviewRotation(sensor.getCurrentOrientation());
|
||||||
|
} else {
|
||||||
|
setPreviewRotation(Windows.Graphics.Display.DisplayInformation.getForCurrentView().currentOrientation);
|
||||||
|
}
|
||||||
|
|
||||||
// Get available aspect ratios
|
// Get available aspect ratios
|
||||||
var aspectRatios = getAspectRatios(capture);
|
var aspectRatios = getAspectRatios(capture);
|
||||||
|
|
||||||
@ -395,6 +388,10 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Insert preview frame and controls into page
|
||||||
|
document.body.appendChild(capturePreview);
|
||||||
|
document.body.appendChild(captureCancelButton);
|
||||||
|
|
||||||
if (aspectRatios.indexOf(DEFAULT_ASPECT_RATIO) > -1) {
|
if (aspectRatios.indexOf(DEFAULT_ASPECT_RATIO) > -1) {
|
||||||
return setAspectRatio(capture, DEFAULT_ASPECT_RATIO);
|
return setAspectRatio(capture, DEFAULT_ASPECT_RATIO);
|
||||||
} else {
|
} else {
|
||||||
@ -408,7 +405,9 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var destroyCameraPreview = function () {
|
var destroyCameraPreview = function () {
|
||||||
window.removeEventListener('deviceorientation', cameraPreviewOrientation, false);
|
if (sensor !== null) {
|
||||||
|
sensor.removeEventListener('orientationchanged', onOrientationChange);
|
||||||
|
}
|
||||||
capturePreview.pause();
|
capturePreview.pause();
|
||||||
capturePreview.src = null;
|
capturePreview.src = null;
|
||||||
[capturePreview, captureCancelButton].forEach(function(elem) {
|
[capturePreview, captureCancelButton].forEach(function(elem) {
|
||||||
@ -439,31 +438,34 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
|
|||||||
tempFolder.createFileAsync(fileName, OptUnique)
|
tempFolder.createFileAsync(fileName, OptUnique)
|
||||||
.then(function(tempCapturedFile) {
|
.then(function(tempCapturedFile) {
|
||||||
return new WinJS.Promise(function (complete) {
|
return new WinJS.Promise(function (complete) {
|
||||||
var imgStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
|
var photoStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
|
||||||
capture.capturePhotoToStreamAsync(encodingProperties, imgStream)
|
var finalStream = new Windows.Storage.Streams.InMemoryRandomAccessStream();
|
||||||
|
capture.capturePhotoToStreamAsync(encodingProperties, photoStream)
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return Windows.Graphics.Imaging.BitmapDecoder.createAsync(imgStream);
|
return Windows.Graphics.Imaging.BitmapDecoder.createAsync(photoStream);
|
||||||
})
|
})
|
||||||
.then(function(dec) {
|
.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) {
|
.then(function(enc) {
|
||||||
// We need to rotate the photo 90° CW because by default wp8.1 takes 90° CCW rotated photos.
|
// We need to rotate the photo wrt sensor orientation
|
||||||
enc.bitmapTransform.rotation = Windows.Graphics.Imaging.BitmapRotation.clockwise90Degrees;
|
enc.bitmapTransform.rotation = orientationToRotation(sensor.getCurrentOrientation());
|
||||||
return enc.flushAsync();
|
return enc.flushAsync();
|
||||||
})
|
})
|
||||||
.then(function() {
|
.then(function() {
|
||||||
return tempCapturedFile.openAsync(Windows.Storage.FileAccessMode.readWrite);
|
return tempCapturedFile.openAsync(Windows.Storage.FileAccessMode.readWrite);
|
||||||
})
|
})
|
||||||
.then(function(fileStream) {
|
.then(function(fileStream) {
|
||||||
imgStream.seek(0); // required for win8.1 emulator
|
return Windows.Storage.Streams.RandomAccessStream.copyAsync(finalStream, fileStream);
|
||||||
return Windows.Storage.Streams.RandomAccessStream.copyAsync(imgStream, fileStream);
|
|
||||||
})
|
})
|
||||||
.done(function() {
|
.done(function() {
|
||||||
imgStream.close();
|
photoStream.close();
|
||||||
|
finalStream.close();
|
||||||
complete(tempCapturedFile);
|
complete(tempCapturedFile);
|
||||||
}, function() {
|
}, function() {
|
||||||
imgStream.close();
|
photoStream.close();
|
||||||
|
finalStream.close();
|
||||||
throw new Error("An error has occured while capturing the photo.");
|
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 getAspectRatios = function (capture) {
|
||||||
var getMSProps = capture.videoDeviceController.getAvailableMediaStreamProperties;
|
var videoDeviceController = capture.videoDeviceController;
|
||||||
var photoAspectRatios = getMSProps(CapMSType.photo).map(function (element) {
|
var photoAspectRatios = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.photo).map(function (element) {
|
||||||
return (element.width / element.height).toFixed(1);
|
return (element.width / element.height).toFixed(1);
|
||||||
}).filter(function (element, index, array) { return (index === array.indexOf(element)); });
|
}).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);
|
return (element.width / element.height).toFixed(1);
|
||||||
}).filter(function (element, index, array) { return (index === array.indexOf(element)); });
|
}).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);
|
return (element.width / element.height).toFixed(1);
|
||||||
}).filter(function (element, index, array) { return (index === array.indexOf(element)); });
|
}).filter(function (element, index, array) { return (index === array.indexOf(element)); });
|
||||||
|
|
||||||
@ -514,8 +516,8 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
|
|||||||
|
|
||||||
var setAspectRatio = function (capture, aspect) {
|
var setAspectRatio = function (capture, aspect) {
|
||||||
// Max photo resolution with desired aspect ratio
|
// Max photo resolution with desired aspect ratio
|
||||||
var getMSProps = capture.videoDeviceController.getAvailableMediaStreamProperties;
|
var videoDeviceController = capture.videoDeviceController;
|
||||||
var photoResolution = getMSProps(CapMSType.photo)
|
var photoResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.photo)
|
||||||
.filter(function (elem) {
|
.filter(function (elem) {
|
||||||
return ((elem.width / elem.height).toFixed(1) === aspect);
|
return ((elem.width / elem.height).toFixed(1) === aspect);
|
||||||
})
|
})
|
||||||
@ -524,7 +526,7 @@ function takePictureFromCameraWP(successCallback, errorCallback, args) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Max video resolution with desired aspect ratio
|
// Max video resolution with desired aspect ratio
|
||||||
var videoRecordResolution = getMSProps(CapMSType.videoRecord)
|
var videoRecordResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoRecord)
|
||||||
.filter(function (elem) {
|
.filter(function (elem) {
|
||||||
return ((elem.width / elem.height).toFixed(1) === aspect);
|
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
|
// Max video preview resolution with desired aspect ratio
|
||||||
var videoPreviewResolution = getMSProps(CapMSType.videoPreview)
|
var videoPreviewResolution = videoDeviceController.getAvailableMediaStreamProperties(CapMSType.videoPreview)
|
||||||
.filter(function (elem) {
|
.filter(function (elem) {
|
||||||
return ((elem.width / elem.height).toFixed(1) === aspect);
|
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;
|
return (prop1.width * prop1.height) > (prop2.width * prop2.height) ? prop1 : prop2;
|
||||||
});
|
});
|
||||||
|
|
||||||
var setMSPropsAsync = capture.videoDeviceController.setMediaStreamPropertiesAsync;
|
return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.photo, photoResolution)
|
||||||
|
|
||||||
return setMSPropsAsync(CapMSType.photo, photoResolution)
|
|
||||||
.then(function () {
|
.then(function () {
|
||||||
return setMSPropsAsync(CapMSType.videoPreview, videoPreviewResolution);
|
return videoDeviceController.setMediaStreamPropertiesAsync(CapMSType.videoPreview, videoPreviewResolution);
|
||||||
})
|
})
|
||||||
.then(function () {
|
.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 {
|
try {
|
||||||
createCameraUI();
|
createCameraUI();
|
||||||
startCameraPreview();
|
startCameraPreview();
|
||||||
|
Loading…
Reference in New Issue
Block a user