如何以c#旋转图像x度?

如何以c#旋转图像x度?,c#,image,graphics,drawing,C#,Image,Graphics,Drawing,我已经做了一些搜索,但我找不到任何正在做我想做的事情的函数 我有一个带文本的扫描文档的图像文件,但是文档旋转了几度,所以我不想旋转它,这样文本就可以互相内联了 在一个完美的世界里,它应该是一个自动运行的函数,但我找不到任何东西,我理解如何让它自动运行需要对图像进行一些分析,我认为这是一件大事 但是,我已经做了一个工具来手动旋转网站上的图像,但现在我需要一个功能来保存图像文件的旋转 这似乎是一些不同的方法,但没有人我测试做我想做的 我发现的功能与i whant几乎一样: public static

我已经做了一些搜索,但我找不到任何正在做我想做的事情的函数

我有一个带文本的扫描文档的图像文件,但是文档旋转了几度,所以我不想旋转它,这样文本就可以互相内联了

在一个完美的世界里,它应该是一个自动运行的函数,但我找不到任何东西,我理解如何让它自动运行需要对图像进行一些分析,我认为这是一件大事

但是,我已经做了一个工具来手动旋转网站上的图像,但现在我需要一个功能来保存图像文件的旋转

这似乎是一些不同的方法,但没有人我测试做我想做的

我发现的功能与i whant几乎一样:

public static Bitmap RotateImg(Bitmap bmp, float angle, Color bkColor) {
int w = bmp.Width;
int h = bmp.Height;
PixelFormat pf = default(PixelFormat);
if (bkColor == Color.Transparent)
{
    pf = PixelFormat.Format32bppArgb;
}
else
{
    pf = bmp.PixelFormat;
}

Bitmap tempImg = new Bitmap(w, h, pf);
Graphics g = Graphics.FromImage(tempImg);
g.Clear(bkColor);
g.DrawImageUnscaled(bmp, 1, 1);
g.Dispose();

GraphicsPath path = new GraphicsPath();
path.AddRectangle(new RectangleF(0f, 0f, w, h));
Matrix mtrx = new Matrix();
//Using System.Drawing.Drawing2D.Matrix class 
mtrx.Rotate(angle);
RectangleF rct = path.GetBounds(mtrx);
Bitmap newImg = new Bitmap(Convert.ToInt32(rct.Width), Convert.ToInt32(rct.Height), pf);
g = Graphics.FromImage(newImg);
g.Clear(bkColor);
g.TranslateTransform(-rct.X, -rct.Y);
g.RotateTransform(angle);
g.InterpolationMode = InterpolationMode.HighQualityBilinear;
g.DrawImageUnscaled(tempImg, 0, 0);
g.Dispose();
tempImg.Dispose();
return newImg; }
但这不会更改图像文件的高度和宽度,因此图像文件的大小相同,但图像“对象”已缩放和旋转

你知道我该怎么做吗

回答
我找到了一个解决方案,该解决方案适用于分辨率为300的图像。

如果我正确理解了您的问题,您基本上需要计算旋转后图像的新大小,以及如何在新位图中定位旋转后的图像

希望该图有助于明确解决方案。下面是一段伪代码:

sinVal = abs(sin(angle))
cosVal = abs(cos(angle))
newImgWidth = sinVal * oldImgHeight + cosVal * oldImgWidth
newImgHeight = sinVal * oldImgWidth + cosVal * oldImgHeight
originX = 0
originY = sinVal * oldImgWidth
您希望从newImgWidth和newImgHeight生成新图像,然后围绕原点(原点、原点)执行旋转,然后将图像渲染到此点。如果角度(以度为单位)不在-90度和0度之间(如图所示),则会发生这种情况。如果在0到90度之间,则只需更改原点:

originX = sinVal * oldImgHeight
originY = 0
如果它在90度到270度(-90度)的范围内,那么它是一个小把戏(参见下面的示例代码)

您的代码重新编写(经过短暂测试)-虽然有点不可靠,但似乎可以工作:

public static Bitmap RotateImg(Bitmap bmp, float angle, Color bkColor)
{
    angle = angle % 360;
    if (angle > 180)
        angle -= 360;

    System.Drawing.Imaging.PixelFormat pf = default(System.Drawing.Imaging.PixelFormat);
    if (bkColor == Color.Transparent)
    {
        pf = System.Drawing.Imaging.PixelFormat.Format32bppArgb;
    }
    else
    {
        pf = bmp.PixelFormat;
    }

    float sin = (float)Math.Abs(Math.Sin(angle * Math.PI / 180.0)); // this function takes radians
    float cos = (float)Math.Abs(Math.Cos(angle * Math.PI / 180.0)); // this one too
    float newImgWidth = sin * bmp.Height + cos * bmp.Width;
    float newImgHeight = sin * bmp.Width + cos * bmp.Height;
    float originX = 0f;
    float originY = 0f;

    if (angle > 0)
    {
        if (angle <= 90)
            originX = sin * bmp.Height;
        else
        {
            originX = newImgWidth;
            originY = newImgHeight - sin * bmp.Width;
        }
    }
    else
    {
        if (angle >= -90)
        originY = sin * bmp.Width;
        else
        {
            originX = newImgWidth - sin * bmp.Height;
            originY = newImgHeight;
        }
    }

    Bitmap newImg = new Bitmap((int)newImgWidth, (int)newImgHeight, pf);
    Graphics g = Graphics.FromImage(newImg);
    g.Clear(bkColor);
    g.TranslateTransform(originX, originY); // offset the origin to our calculated values
    g.RotateTransform(angle); // set up rotate
    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
    g.DrawImageUnscaled(bmp, 0, 0); // draw the image at 0, 0
    g.Dispose();

    return newImg;
}
公共静态位图旋转img(位图bmp、浮动角度、颜色bkColor)
{
角度=角度%360;
如果(角度>180)
角度-=360;
System.Drawing.Imaging.PixelFormat pf=默认值(System.Drawing.Imaging.PixelFormat);
if(bkColor==Color.Transparent)
{
pf=System.Drawing.Imaging.PixelFormat.Format32bppArgb;
}
其他的
{
pf=bmp.PixelFormat;
}
float sin=(float)Math.Abs(Math.sin(angle*Math.PI/180.0));//此函数采用弧度
float cos=(float)Math.Abs(Math.cos(angle*Math.PI/180.0));//这个也是
float newImgWidth=sin*bmp.Height+cos*bmp.Width;
float newImgHeight=sin*bmp.Width+cos*bmp.Height;
浮动原点x=0f;
浮动初始值=0f;
如果(角度>0)
{
如果(角度=-90)
originY=sin*bmp.宽度;
其他的
{
originX=newImgWidth-sin*bmp.高度;
originY=newImgHeight;
}
}
位图newImg=新位图((int)newImgWidth,(int)newImgHeight,pf);
Graphics g=Graphics.FromImage(newImg);
g、 清晰(黑色);
g、 TranslateTransform(originX,originY);//将原点偏移到计算值
g、 旋转变换(角度);//设置旋转
g、 插值模式=System.Drawing.Drawing2D.InterpolationMode.HighQuality双线性;
g、 DrawImageUnscaled(bmp,0,0);//在0,0处绘制图像
g、 处置();
返回newImg;
}
注意trig函数的度到弧度转换(180度==π弧度)

编辑:最大的问题是负sin值,在计算原点x/y时,我对宽度/高度感到困惑-现在应该可以正常工作了(已测试)


编辑:修改代码以处理任何角度

这严格来说是对上面VisualMelon的漂亮答案的评论,但我不允许添加评论

代码中有两个小错误

a) 模量后的第一次检查应分为两部分,或更改为:

if (180<Math.Abs(angle)) angle -= 360*Math.Sign(angle);
如果省略,如果源不是96 dpi,则图像将缩放


…和分割棒,尺寸和偏移的中间计算应该保持在两倍,并且只减少到最后浮动

你的问题标题有点误导,你真正要问的是如何计算图像旋转后的新宽度/高度,这是一个比编程问题更大的问题。在我自己的答案中可以看到我的函数结果。@RickardP你能再试一次吗,我犯了两个愚蠢的错误,现在它工作了(我愚蠢地测试了它将是一个近似正方形的图像,这没有帮助!)与最新代码相同的结果,可能是我在角度上有错误的值吗?你尊重什么?我从jquery插件得到的示例是,我应该将其旋转3.5度或-3.5度,这样我就可以将其作为值发送,这是错误的吗?新代码将以任何角度(度)显示,我一直在观察它在我的计算机上旋转(并工作)。我会确保有效代码是相同的,以防我复制不正确。代码到底有什么问题?好的,发现函数与VisualMelon几乎相同,但有一些变化,它对我的分辨率很高,谢谢,这些都是很好的评论,我回答中的代码在任何级别上都不是很好,正如RickardP在评论中提到的,此答案是代码的更实用版本:。也许有一天我会整理我的答案,我认为代码的目的更多的是为了证明基础数学是有效的,而不是提供一个好的参考!
newImg.SetResolution(bmp.HorizontalResolution, bmp.VerticalResolution);