c# - 旋转后在图像中找到原始点c#

标签 c# image rotation point

下面的图片说明了我正在尝试做的事情。

http://tinypic.com/r/nvbehh/5

我正在用 C# 旋转图像(白色矩形)。 问题是无论旋转如何,我都需要将绿色方 block (另一个图像)放在相对于矩形的同一点上。绿色方 block 不能随矩形一起旋转。

如您所见,在旋转白色矩形后,我每次都会得到不同尺寸的 Canvas 。

在创建新的旋转图像后,我试图找到放置绿色方 block 的确切点。

OK 下面是一些旋转图像并将点放在正确位置的代码。 现在的问题是,如果我在 RotateImage 方法中应用转换,我会看到所有的矩形,但显然我的红点在错误的位置。 我应该强调我需要知道点的点,而不仅仅是把它放在正确的位置。

public class IconController : Controller
{
    //
    // GET: /Icon/

    public ActionResult Index()
    {
        return View();
    }

    ////Icon/Icon?connected=true&heading=320&type=logo45
    public ActionResult Icon(bool connected, float heading, string type)
    {
        var dir = Server.MapPath("/images");
        //RED SQUARE IM TRYING TO PLACE ON THE BLUE RECTANGLE.
        var path = Path.Combine(dir, "mapicons/center.png");

        //GREEN RECTANGLE WITH FIXED YELLOW (Actual center) AND BLUE (point im really trying to find)
        var path2 = Path.Combine(dir, "mapicons/connected-marker.png");

        Image innerIcon = Image.FromFile(path);
        Image marker = Image.FromFile(path2);

        using (marker)
        {

            Point orginalCenter = new Point((marker.Width / 2), (marker.Height / 2));
            Bitmap markerbitmap = RotateImage(new Bitmap(marker), heading);

            marker = (Image)markerbitmap;
            using (var bitmap = new Bitmap(marker.Width, marker.Height))
            {
                using (var canvas = Graphics.FromImage(bitmap))
                {
                    PointF newCenter = RotatePoint(orginalCenter, 80, 120, heading, marker.Width, marker.Height);
                    canvas.DrawRectangle(new Pen(Color.Black), 0, 0, bitmap.Width, bitmap.Height);
                    canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    canvas.DrawImage(marker, new Rectangle(0, 0, marker.Width, marker.Height), new Rectangle(0, 0, marker.Width, marker.Height), GraphicsUnit.Pixel);
                    canvas.DrawImage(innerIcon, newCenter.X - (innerIcon.Width / 2), newCenter.Y - (innerIcon.Height / 2));

                    canvas.Save();
                }
                try
                {
                    bitmap.Save(Path.Combine(dir, "result.png"), ImageFormat.Png);
                    path = Path.Combine(dir, "result.png");
                }
                catch (Exception ex) { }
            }
        }


        return base.File(path, "image/png");
    }

    public static Bitmap RotateImage(Bitmap b, float Angle)
    {
        // The original bitmap needs to be drawn onto a new bitmap which will probably be bigger 
        // because the corners of the original will move outside the original rectangle.
        // An easy way (OK slightly 'brute force') is to calculate the new bounding box is to calculate the positions of the 
        // corners after rotation and get the difference between the maximum and minimum x and y coordinates.
        float wOver2 = b.Width / 2.0F;
        float hOver2 = b.Height / 2.0F;
        float radians = -(float)(Angle / 180.0 * Math.PI);
        // Get the coordinates of the corners, taking the origin to be the centre of the bitmap.
        PointF[] corners = new PointF[]{
        new PointF(-wOver2, -hOver2),
        new PointF(+wOver2, -hOver2),
        new PointF(+wOver2, +hOver2),
        new PointF(-wOver2, +hOver2)
        };

        for (int i = 0; i < 4; i++)
        {
            PointF p = corners[i];
            PointF newP = new PointF((float)(p.X * Math.Cos(radians) - p.Y * Math.Sin(radians)), (float)(p.X * Math.Sin(radians) + p.Y * Math.Cos(radians)));
            corners[i] = newP;
        }

        // Find the min and max x and y coordinates.
        float minX = corners[0].X;
        float maxX = minX;
        float minY = corners[0].Y;
        float maxY = minY;
        for (int i = 1; i < 4; i++)
        {
            PointF p = corners[i];
            minX = Math.Min(minX, p.X);
            maxX = Math.Max(maxX, p.X);
            minY = Math.Min(minY, p.Y);
            maxY = Math.Max(maxY, p.Y);
        }

        // Get the size of the new bitmap.
        SizeF newSize = new SizeF(maxX - minX, maxY - minY);
        // ...and create it.
        Bitmap returnBitmap = new Bitmap((int)Math.Ceiling(newSize.Width), (int)Math.Ceiling(newSize.Height));
        // Now draw the old bitmap on it.
        using (Graphics g = Graphics.FromImage(returnBitmap))
        {
            g.TranslateTransform(newSize.Width / 2.0f, newSize.Height / 2.0f);
            g.RotateTransform(Angle);

        g.TranslateTransform(-b.Width / 2.0f, -b.Height / 2.0f);

            g.DrawImage(b, 0, 0);
        }

        return returnBitmap;
    }


    public static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees)
    {
        double angleInRadians = angleInDegrees * (Math.PI / 180);
        double cosTheta = Math.Cos(angleInRadians);
        double sinTheta = Math.Sin(angleInRadians);

        Point pt = new Point();
        pt.X = (int)(cosTheta * (pointToRotate.X-centerPoint.X) - sinTheta * (pointToRotate.Y-centerPoint.Y) + centerPoint.X);

        pt.Y = (int)(sinTheta * (pointToRotate.X - centerPoint.X) + cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y);
        //p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy

        return pt;

    }
}

所以现在我需要能够取消注释 RotateImage 方法中的 TranslateTransform,以便我看到正确的矩形并修改 RotatePoint 方法,以便获得正确的新位置

最佳答案

这里是工作 Controller 。
公共(public)类 IconController: Controller { // //获取:/图标/

    public ActionResult Index()
    {
        return View();
    }

    ////Icon/Icon?connected=true&heading=320&type=logo45
    public ActionResult Icon(bool connected, float heading, string type)
    {
        var dir = Server.MapPath("/images");
        //RED SQUARE IM TRYING TO PLACE ON THE BLUE RECTANGLE.
        var path = Path.Combine(dir, "mapicons/center.png");

        //GREEN RECTANGLE WITH FIXED YELLOW (Actual center) AND BLUE (point im really trying to find)
        var path2 = Path.Combine(dir, "mapicons/connected-marker.png");

        Image innerIcon = Image.FromFile(path);
        Image marker = Image.FromFile(path2);

        using (marker)
        {

            Point orginalCenter = new Point((marker.Width / 2), (marker.Height / 2));
            Bitmap markerbitmap = RotateImage(new Bitmap(marker), heading);

            marker = (Image)markerbitmap;
            using (var bitmap = new Bitmap(marker.Width, marker.Height))
            {
                using (var canvas = Graphics.FromImage(bitmap))
                {
                    PointF newCenter = RotatePoint(orginalCenter, 80, 120, heading, marker.Width, marker.Height);
                    canvas.DrawRectangle(new Pen(Color.Black), 0, 0, bitmap.Width, bitmap.Height);
                    canvas.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    canvas.DrawImage(marker, new Rectangle(0, 0, marker.Width, marker.Height), new Rectangle(0, 0, marker.Width, marker.Height), GraphicsUnit.Pixel);
                    canvas.DrawImage(innerIcon, newCenter.X - (innerIcon.Width / 2), newCenter.Y - (innerIcon.Height / 2));

                    canvas.Save();
                }
                try
                {
                    bitmap.Save(Path.Combine(dir, "result.png"), ImageFormat.Png);
                    path = Path.Combine(dir, "result.png");
                }
                catch (Exception ex) { }
            }
        }


        return base.File(path, "image/png");
    }

    public static Bitmap RotateImage(Bitmap b, float Angle)
    {
        // The original bitmap needs to be drawn onto a new bitmap which will probably be bigger 
        // because the corners of the original will move outside the original rectangle.
        // An easy way (OK slightly 'brute force') is to calculate the new bounding box is to calculate the positions of the 
        // corners after rotation and get the difference between the maximum and minimum x and y coordinates.
        float wOver2 = b.Width / 2.0F;
        float hOver2 = b.Height / 2.0F;
        float radians = -(float)(Angle / 180.0 * Math.PI);
        // Get the coordinates of the corners, taking the origin to be the centre of the bitmap.
        PointF[] corners = new PointF[]{
        new PointF(-wOver2, -hOver2),
        new PointF(+wOver2, -hOver2),
        new PointF(+wOver2, +hOver2),
        new PointF(-wOver2, +hOver2)
        };

        for (int i = 0; i < 4; i++)
        {
            PointF p = corners[i];
            PointF newP = new PointF((float)(p.X * Math.Cos(radians) - p.Y * Math.Sin(radians)), (float)(p.X * Math.Sin(radians) + p.Y * Math.Cos(radians)));
            corners[i] = newP;
        }

        // Find the min and max x and y coordinates.
        float minX = corners[0].X;
        float maxX = minX;
        float minY = corners[0].Y;
        float maxY = minY;
        for (int i = 1; i < 4; i++)
        {
            PointF p = corners[i];
            minX = Math.Min(minX, p.X);
            maxX = Math.Max(maxX, p.X);
            minY = Math.Min(minY, p.Y);
            maxY = Math.Max(maxY, p.Y);
        }

        // Get the size of the new bitmap.
        SizeF newSize = new SizeF(maxX - minX, maxY - minY);
        // ...and create it.
        Bitmap returnBitmap = new Bitmap((int)Math.Ceiling(newSize.Width), (int)Math.Ceiling(newSize.Height));
        // Now draw the old bitmap on it.
        using (Graphics g = Graphics.FromImage(returnBitmap))
        {
            g.TranslateTransform(newSize.Width / 2.0f, newSize.Height / 2.0f);
            g.RotateTransform(Angle);

        g.TranslateTransform(-b.Width / 2.0f, -b.Height / 2.0f);

            g.DrawImage(b, 0, 0);
        }

        return returnBitmap;
    }


    public static Point RotatePoint(Point pointToRotate, Point centerPoint, double angleInDegrees)
    {
        double angleInRadians = angleInDegrees * (Math.PI / 180);
        double cosTheta = Math.Cos(angleInRadians);
        double sinTheta = Math.Sin(angleInRadians);

        Point pt = new Point();
        pt.X = (int)(cosTheta * (pointToRotate.X-centerPoint.X) - sinTheta * (pointToRotate.Y-centerPoint.Y) + centerPoint.X);

        pt.Y = (int)(sinTheta * (pointToRotate.X - centerPoint.X) + cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y);
        //p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy

        return pt;

    }
}

关于c# - 旋转后在图像中找到原始点c#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17584277/

相关文章:

c# - 我应该使用哪个 C# 集合来进行可变和可重复的任务管理?

jquery - 使用 jquery 对图像重新排序

asp.net - 无法从数据库检索图像?

node.js - 无法在 Heroku 服务器上上传图片

javascript - 如果鼠标指针太近则停止旋转图像

c# - 如何在 C# 中从 XML 文件创建 DOM 树?

c# - 禁用和启用后 WPF 文本框焦点 "sticking"

c# - 如何通过 C# 检索所有可能的服务器名称

css - 从旋转的 div 旋转背景图像

jquery - 如何在鼠标单击时重复旋转变换?