要正确显示取景器,您需要两个信息:
- 方向:相对于页面方向的预览图片方向
- Scale:预览图片大小和 xaml 控件之间的因子。
首先,您需要一个以画笔为背景的画布
<Canvas x:Name="viewfinderCanvas" Width="480" Height="800" >
<Canvas.Background>
<VideoBrush x:Name="viewfinderBrush" Stretch="None" />
</Canvas.Background>
</Canvas>
您必须使用Stretch="None"否则 XAML 将在视图画笔上应用缩放。现在您需要 viewfinderBrush 转换才能正确显示它。默认情况下,画布中心对应于预览图片中心,因此我们需要计算一个角度、一个比例因子,并将画布中心作为变换中心。
要计算您需要的角度:
代码 :
double ComputeAngle(PageOrientation orientation)
{
if ((orientation & PageOrientation.Portrait) == PageOrientation.Portrait)
{
return m_captureDevice.SensorRotationInDegrees;
}
else if ((orientation & PageOrientation.LandscapeLeft) == PageOrientation.LandscapeLeft)
{
return m_captureDevice.SensorRotationInDegrees - 90;
}
else //PageOrientation.LandscapeRight
{
return m_captureDevice.SensorRotationInDegrees + 90;
}
}
比例只是画布尺寸和预览图片尺寸之间的因素:
//orient preview picture size from the computed anle.
var tmp = new CompositeTransform(){Rotation = ComputeAngle(currentPageOrientation)};
var previewSize = tmp.TransformBounds (new Rect(new Point(), new Size(m_captureDevice.PreviewResolution.Width, m_captureDevice.PreviewResolution.Height))).Size;
double s1 = viewfinderCanvas.Width/ (double)previewSize.Width;
double s2 = viewfinderCanvas.Height/ (double)previewSize.Height;
- 如果使用最大因子,则进行拟合 => scale = Math.Max(s1, s2)
- 如果你使用最小因子,你会做一个 Fit In => scale = Math.Min(s1, s2)
前后摄像头的视线方向相反。因此,要正确显示前置摄像头,您需要在一维中应用一面镜子。在 WP8 上,传感器方向通常为 90°,因此 Y 尺寸相反。
if (sensorLocation == CameraSensorLocation.Back)
{
viewfinderBrush.Transform = new CompositeTransform() {
Rotation = ComputeAngle(currentPageOrientation),
CenterX = viewfinderCanvas.Width / 2,
CenterY = viewfinderCanvas.Height / 2,
ScaleX = scale,
ScaleY = scale };
}
else
{
viewfinderBrush.Transform = new CompositeTransform() {
Rotation = ComputeAngle(currentPageOrientation),
CenterX = viewfinderCanvas.Width / 2,
CenterY = viewfinderCanvas.Height / 2,
ScaleX = scale,
ScaleY = -1 * scale };//Y mirror
}
您可以在 github 上找到示例的最新版本:https ://github.com/yan-verdavaine/wp8-sample/tree/master/Imaging/ViewFinder