C# 在WPF中旋转图像不考虑屏幕大小
我当前在WPF中使用C# 在WPF中旋转图像不考虑屏幕大小,c#,wpf,image-rotation,C#,Wpf,Image Rotation,我当前在WPF中使用RotateTransform和LayoutTransform旋转图像时遇到问题。当像素高度大小大于监视器高度并以90º或270º旋转的图像时,窗口大小将高于监视器屏幕分辨率大小 示例屏幕截图: 我正在使用下面的代码(简化),mainWindow.img是一个System.Windows.Control.Image: static void Rotate(int degrees) { var rt = new RotateTransform { Angle = de
RotateTransform
和LayoutTransform
旋转图像时遇到问题。当像素高度大小大于监视器高度并以90º或270º旋转的图像时,窗口大小将高于监视器屏幕分辨率大小
示例屏幕截图:
我正在使用下面的代码(简化),mainWindow.img是一个System.Windows.Control.Image
:
static void Rotate(int degrees)
{
var rt = new RotateTransform { Angle = degrees };
mainWindow.img.LayoutTransform = rt;
}
这是一个图片查看器项目,完整的源代码可在
我曾尝试移动图像的宽度和高度值,但它会产生不希望的结果(倾斜比例)
图像大小的大小计算基于用户的屏幕高度,使用以下修剪代码进行:
int interfaceHeight = 90;
double maxWidth = Math.Min(MonitorInfo.Width, width);
double maxHeight = Math.Min((MonitorInfo.Height - interfaceHeight), height);
double AspectRatio = Math.Min((maxWidth / width), (maxHeight / height));
mainWindow.img.Width = (width * AspectRatio);
mainWindow.img.Height = (height * AspectRatio);
height
和width
是图像的尺寸,MonitorInfo
是检索当前监视器分辨率的类
更新
下面是示例WPF应用程序的最低代码,说明了该问题:
MainWindow.xaml
问题的根源在于,当图像未旋转时,仅根据图像的大小计算缩放比。旋转图像后,
img.ActualHeight
有效地变为其宽度,img.ActualWidth
有效地变为其高度,并且图像未旋转时的计算不再正确
以下是我对您的代码所做的更改和添加:
private double normalRatio;
private double rotatedRatio;
private void MainWindow_ContentRendered(object sender, EventArgs e)
{
double interfaceHeight = this.ActualHeight - img.ActualHeight;
normalRatio = Math.Min(SystemParameters.WorkArea.Width / img.Source.Width, (SystemParameters.WorkArea.Height - interfaceHeight) / img.Source.Height);
rotatedRatio = Math.Min(SystemParameters.WorkArea.Width / img.Source.Height, (SystemParameters.WorkArea.Height - interfaceHeight) / img.Source.Width);
ScaleImage();
}
private void ScaleImage()
{
double ratio = Degrees == 0 || Degrees == 180 ? normalRatio : rotatedRatio;
img.Width = (img.Source.Width * ratio);
img.Height = (img.Source.Height * ratio);
}
void Rotate(bool right)
{
if (right)
{
Degrees -= 90;
if (Degrees < 0) { Degrees += 360; }
}
else
{
Degrees += 90;
if (Degrees >= 360) { Degrees -= 360; }
}
ScaleImage();
Rotate(Degrees);
}
//I left the other methods, including Rotate(int degrees), the same as in your question
私有双正态比率;
私人双旋转空间;
私有void主窗口\u ContentRendered(对象发送方,事件参数e)
{
双界面高度=此.ActualHeight-img.ActualHeight;
normalRatio=Math.Min(SystemParameters.WorkArea.Width/img.Source.Width,(SystemParameters.WorkArea.Height-interfaceHeight)/img.Source.Height);
rotatedRatio=Math.Min(SystemParameters.WorkArea.Width/img.Source.Height,(SystemParameters.WorkArea.Height-InterfaceHight)/img.Source.Width);
ScaleImage();
}
私有void ScaleImage()
{
双倍比率=度==0 | |度==180?正常比率:旋转比率;
img.Width=(img.Source.Width*比率);
img.Height=(img.Source.Height*比率);
}
空心旋转(布尔右)
{
如果(右)
{
度数-=90;
如果(度<0){Degrees+=360;}
}
其他的
{
度数+=90;
如果(度>=360){Degrees-=360;}
}
ScaleImage();
旋转(度);
}
//我留下了其他方法,包括旋转(int度),与您的问题相同
以下是我改变的解释:
是通过从窗口高度减去图像高度来计算的,差值是其他所有内容的聚集大小界面高度
- 我使用的不是
,而是考虑了Windows任务栏的大小和位置MonitorInfo
- 我计算了两个比例比率:
,用于图像未旋转或垂直翻转(180°)时,以及normalRatio
,用于图像在任一方向旋转90°时。我通过交换rotatedRatio
和img.Source.Height
来计算后者img.Source.Width
- 我添加了一个
方法来根据预期的旋转进行实际的图像缩放,因此我可以从两个不同的位置调用它ScaleImage()
- 我简化了
以使用数学计算新角度,而不是列出每个可能的旋转Rotate(bool right)
Math.Min(normalRatio,rotatedRatio)
请注意,仅当您调用
Rotate(bool right)
时,上述操作才有效,而直接调用Rotate(int degrees)
时则无效。这是因为使用两个比率的逻辑只起作用,因为图像只有两种可能的大小(纵向和横向),只有将旋转限制为90°的增量时才会出现这种情况。如果要将角度设置为其他值,如20°,计算图像有效大小的数学变得有点复杂,您需要开始根据角度动态计算它。问题的根源在于,您仅根据图像未旋转时的大小计算缩放比。旋转图像后,img.ActualHeight
有效地变为其宽度,img.ActualWidth
有效地变为其高度,并且图像未旋转时的计算不再正确
以下是我对您的代码所做的更改和添加:
private double normalRatio;
private double rotatedRatio;
private void MainWindow_ContentRendered(object sender, EventArgs e)
{
double interfaceHeight = this.ActualHeight - img.ActualHeight;
normalRatio = Math.Min(SystemParameters.WorkArea.Width / img.Source.Width, (SystemParameters.WorkArea.Height - interfaceHeight) / img.Source.Height);
rotatedRatio = Math.Min(SystemParameters.WorkArea.Width / img.Source.Height, (SystemParameters.WorkArea.Height - interfaceHeight) / img.Source.Width);
ScaleImage();
}
private void ScaleImage()
{
double ratio = Degrees == 0 || Degrees == 180 ? normalRatio : rotatedRatio;
img.Width = (img.Source.Width * ratio);
img.Height = (img.Source.Height * ratio);
}
void Rotate(bool right)
{
if (right)
{
Degrees -= 90;
if (Degrees < 0) { Degrees += 360; }
}
else
{
Degrees += 90;
if (Degrees >= 360) { Degrees -= 360; }
}
ScaleImage();
Rotate(Degrees);
}
//I left the other methods, including Rotate(int degrees), the same as in your question
私有双正态比率;
私人双旋转空间;
私有void主窗口\u ContentRendered(对象发送方,事件参数e)
{
双界面高度=此.ActualHeight-img.ActualHeight;
normalRatio=Math.Min(SystemParameters.WorkArea.Width/img.Source.Width,(SystemParameters.WorkArea.Height-interfaceHeight)/img.Source.Height);
rotatedRatio=Math.Min(SystemParameters.WorkArea.Width/img.Source.Height,(SystemParameters.WorkArea.Height-InterfaceHight)/img.Source.Width);
ScaleImage();
}
私有void ScaleImage()
{
双倍比率=度==0 | |度==180?正常比率:旋转比率;
img.Width=(img.Source.Width*比率);
img.Height=(img.Source.Height*比率);
}
空心旋转(布尔右)
{
如果(右)
{
度数-=90;
如果(度<0){Degrees+=360;}
}
其他的
{
度数+=90;
如果(度>=360){Degrees-=360;}
}
ScaleImage();
旋转(度);
}
//我保留了其他方法,包括旋转(int度),与中相同
private double normalRatio;
private double rotatedRatio;
private void MainWindow_ContentRendered(object sender, EventArgs e)
{
double interfaceHeight = this.ActualHeight - img.ActualHeight;
normalRatio = Math.Min(SystemParameters.WorkArea.Width / img.Source.Width, (SystemParameters.WorkArea.Height - interfaceHeight) / img.Source.Height);
rotatedRatio = Math.Min(SystemParameters.WorkArea.Width / img.Source.Height, (SystemParameters.WorkArea.Height - interfaceHeight) / img.Source.Width);
ScaleImage();
}
private void ScaleImage()
{
double ratio = Degrees == 0 || Degrees == 180 ? normalRatio : rotatedRatio;
img.Width = (img.Source.Width * ratio);
img.Height = (img.Source.Height * ratio);
}
void Rotate(bool right)
{
if (right)
{
Degrees -= 90;
if (Degrees < 0) { Degrees += 360; }
}
else
{
Degrees += 90;
if (Degrees >= 360) { Degrees -= 360; }
}
ScaleImage();
Rotate(Degrees);
}
//I left the other methods, including Rotate(int degrees), the same as in your question