如何在c#中旋转图像x度?

Ric*_*rdP 12 c# graphics drawing image

我做了一些搜索,我找不到任何功能,做我想做的事情.

我有一个带有文本的扫描文档的图像文件,但是文档旋转了一些度数,因此我想旋转它以使文本彼此内联.

在一个完美的世界中,它应该是一个自动执行此功能的功能,但我无法找到任何东西和我理解的自动工作,它需要对图像进行一些分析,我认为它是大事.

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

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

我发现的功能几乎就像我的作品一样:

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; }
Run Code Online (Sandbox Code Playgroud)

但这不会改变图像文件的高度和宽度,因此图像文件的大小相同,但图像"对象"已缩放和旋转.

知道我怎么能做到这一点好吗?

回答 我找到了解决方案,该解决方案适用于我的图像,其分辨率为300,旧答案在这里.

Vis*_*lon 33

如果我已经正确理解了你的问题,你基本上想要在旋转后计算出图像的新尺寸,以及如何将旋转后的图像定位在它的新位图中.

在此输入图像描述

该图有望帮助明确解决方案.这是一些伪代码:

sinVal = abs(sin(angle))
cosVal = abs(cos(angle))
newImgWidth = sinVal * oldImgHeight + cosVal * oldImgWidth
newImgHeight = sinVal * oldImgWidth + cosVal * oldImgHeight
originX = 0
originY = sinVal * oldImgWidth
Run Code Online (Sandbox Code Playgroud)

您想要从newImgWidth和newImgHeight创建新图像,然后围绕原点(originX,originY)执行旋转,然后将图像渲染到此点.如果角度(以度为单位)不在-90度和0度之间(如图所示),则会出现这种情况.如果它介于0和90度之间,那么您只需更改原点:

originX = sinVal * oldImgHeight
originY = 0
Run Code Online (Sandbox Code Playgroud)

如果它在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;
}
Run Code Online (Sandbox Code Playgroud)

注意trig函数的Degrees to Radians Conversion(180 Degrees == Pi Radians)

编辑:大问题是负的罪恶值,我在计算原点x/y时得到宽度/高度混淆 - 这应该现在正常工作(测试)

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