C# 在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

我当前在WPF中使用
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度),与您的问题相同
以下是我改变的解释:

  • 界面高度
    是通过从窗口高度减去图像高度来计算的,差值是其他所有内容的聚集大小
  • 我使用的不是
    MonitorInfo
    ,而是考虑了Windows任务栏的大小和位置
  • 我计算了两个比例比率:
    normalRatio
    ,用于图像未旋转或垂直翻转(180°)时,以及
    rotatedRatio
    ,用于图像在任一方向旋转90°时。我通过交换
    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