Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/328.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何保持图像';在C#中旋转后的s质量?_C#_Image_Rotation - Fatal编程技术网

如何保持图像';在C#中旋转后的s质量?

如何保持图像';在C#中旋转后的s质量?,c#,image,rotation,C#,Image,Rotation,我的讲师要求我编写一个程序,可以旋转图像,而无需C#library提供任何转换函数,这意味着我可以使用C#library提供的方法。我的问题是,旋转后,图像的质量变得非常差,如下图所示 这是我的代码,第一部分是为旋转后的图像创建一个新位图: double sin = Math.Abs(Math.Sin(ratio * (Math.PI / 180.0))); double cos = Math.Abs(Math.Cos(ratio * (Math

我的讲师要求我编写一个程序,可以旋转图像,而无需C#library提供任何转换函数,这意味着我可以使用C#library提供的方法。我的问题是,旋转后,图像的质量变得非常差,如下图所示

这是我的代码,第一部分是为旋转后的图像创建一个新位图:

            double sin = Math.Abs(Math.Sin(ratio * (Math.PI / 180.0)));
            double cos = Math.Abs(Math.Cos(ratio * (Math.PI / 180.0)));
            bmpOut = new Bitmap((int)(sin * bmpIn.Width + cos * bmpIn.Height), (int)(sin * bmpIn.Height + cos * bmpIn.Width));
这是旋转图像的代码

        int intHeight = bitmapOri.Height;
        int intWidth = bitmapOri.Width;

        double x_cen = intWidth / 2.0;
        double y_cen = intHeight / 2.0;

        unsafe
        {
            for (int j = 0; j < intWidth; j++)
            {
                for (int i = 0; i < intHeight; i++)
                {
                    double x_new = x_cen + (double)((j - x_cen) * Math.Cos(ratio) - (i - y_cen) * Math.Sin(ratio));
                    double y_new = y_cen + (double)((j - x_cen) * Math.Sin(ratio) + (i - y_cen) * Math.Cos(ratio));
                    if (x_new < 0 || y_new < 0 || x_new >= bitmapRes.Width || y_new >= bitmapRes.Height)
                        continue;
                    bitmapRes.SetPixel((int)x_new, (int)y_new, bitmapOri.GetPixel(j, i));
                }
            }
        }
int intHeight=bitmapOri.Height;
int intWidth=bitmapOri.Width;
双x_cen=intWidth/2.0;
双y_cen=八分之一/2.0;
不安全的
{
对于(intj=0;j=位图宽度| y|u new>=位图高度)
继续;
bitmapRes.SetPixel((int)x_new,(int)y_new,bitmapOri.GetPixel(j,i));
}
}
}
您能告诉我我的代码中有什么欺诈,有什么问题吗?非常感谢您的帮助。

问题 double to int操作可能会导致某些像素设置多次,而某些像素未设置

解决方案 反其道而行之

  • 旋转图像中的每个像素
  • 计算它们在原始图像中的位置
  • 如果位置不是整数,则按距离平均约四个像素
  • 细节 如何计算原始图像中的位置

  • 假设旋转轴为O,将点A视为目标图像中的一个像素

  • OA可以写成t*rotate(alpha,OXOX是从点O开始的标准化向量。这意味着OA向量可以被视为(或通过)从OA旋转alpha角度,并且它可以具有特殊长度(t)。而OA实际值将是(t*cos(alpha),t*sin(alpha))

  • 假设OA实际上是旋转的OB,因为它在从原始图像旋转的目标图像中,所以OB可以写为t*rotate(alpha+beta,X)。这意味着OA是一种不同于OB的旋转手术。有点奇怪。但它是正确和有用的

  • 让我们现在做真正的工作OB实际值为(t*cos(α+β),t*sin(α+β))

  • 让我们关注X坐标,它等于t*cos(alpha)*sin(beta)+t*sin(alpha)+t*cos(beta),然后返回到观察OA坐标。它推断X(OB)=sin(beta)*X(OA)+cos(beta)*Y(OA)。Y坐标是相同的


  • 旋转时,需要考虑高宽比。如果您将一个4宽3高的图像旋转90度而不进行调整,则最终会将4挤压成3,并将3扩展成4。因此,要么调整旋转的方式,要么找出旋转图像所在对象的方式,而不是图像本身。问题的根源在于你的铸造。当您围绕原点旋转一个点时,该点在绝大多数情况下都会产生一个十进制数,但当您将坐标转换为(int)时,您将丢弃该信息。这会导致某些像素多次设置,而其他像素则根本没有设置。简单的解决方案是舍入而不是截断,但ZenWu的答案中有一个更稳健的解决方案。作为旁注,您也在
    不安全的
    块中操作,但您的代码都不要求如此。另一个问题。当图像没有通过其中心旋转时,我的旋转函数会发生什么情况?第三步的技术术语是“双线性插值”。哪一个公式可以帮助我在第二步中找到原始图像上的位置?@iamatsundere181只是公式的反向函数,可能你自己尝试一下,因为这是一个练习另一个问题。当图像没有通过其中心旋转时,我的旋转函数会发生什么情况?@iamatsundere181很抱歉,我没有真正检查你的旋转公式。我编辑了答案并添加了一些关于步骤2的细节。还提到了旋转枢轴