簡體   English   中英

圍繞中心C#旋轉圖像

[英]Rotating image around center C#

嘗試在圖片框中旋轉圖像時出現小錯誤。 一切正常。 但是在旋轉時,它不能完全圍繞中心旋轉。 它略微偏離(不太明顯)但有點煩人。 這是我的代碼:

private readonly Bitmap _origPowerKnob = Properties.Resources.PowerKnob;

//CODE WHERE ROTATE METHOD IS CALLED//

using (Bitmap b = new Bitmap(_origPowerKnob))
                {
                    Bitmap newBmp = RotateImage(b, _powerAngle);
                    PowerKnob.BackgroundImage = newBmp;
                }

private Bitmap RotateImage(Bitmap b, float angle)
        {
            //Create a new empty bitmap to hold rotated image.
            Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
            //Make a graphics object from the empty bitmap.
            Graphics g = Graphics.FromImage(returnBitmap);
            //move rotation point to center of image.
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.TranslateTransform((float) b.Width / 2, (float)b.Height / 2);
            //Rotate.        
            g.RotateTransform(angle);
            //Move image back.
            g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
            //Draw passed in image onto graphics object.
            g.DrawImage(b, new Point(0, 0));
            return returnBitmap;
        }

圖片顯示我的意思:

沒有旋轉。

180轉。

它不能完美旋轉。 有針對這個的解決方法嗎? 我沒有為我的picturebox屬性設置的東西? 我試過了很多。

謝謝。

我找到了一個解決方案,從中心獲取旋轉的圖像

[我的測試條件]

我正在測試這個以下的考慮因素,如果它適合你它的確定:3

1.-我使用的源圖像是一個完美的正方形[LxL],取自png文件,無論是正方形的大小,只需要是LxL; //(寬度==高度)=真;

2.-我正在旋轉的png源圖像文件是透明和方形的,我是從插畫家那里得到的

3.-我測試了大小為417x417,520x520和1024x1024的文件

[我可以分享給你的代碼]

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace YourNamespace
{
    public static class TheClassinWhichYouWantToPlaceTheFunction
    {
        public static Bitmap RotateImageN(Bitmap b, float angle)
        {
            //Create a new empty bitmap to hold rotated image.
            Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
            //Make a graphics object from the empty bitmap.
            Graphics g = Graphics.FromImage(returnBitmap);
            //move rotation point to center of image.
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            g.TranslateTransform((float)b.Width / 2, (float)b.Height / 2);
            //Rotate.        
            g.RotateTransform(angle);
            //Move image back.
            g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
            //Draw passed in image onto graphics object.
            //Found ERROR 1: Many people do g.DwarImage(b,0,0); The problem is that you re giving just the position
            //Found ERROR 2: Many people do g.DrawImage(b, new Point(0,0)); The size still not present hehe :3

            g.DrawImage(b, 0,0,b.Width, b.Height);  //My Final Solution :3
            return returnBitmap;
        }
   }
}

我只是給這個函數命名為“RotateImageN”,因為這是我嘗試的第五個解決方案:3我希望對你有所幫助

對不起我的英語和/或語法呵呵:3

這是一個簡單的測試表格可以幫助你很多的地方。

獲取此代碼並將其放入新的WinForms項目的Form1.cs文件中。

using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace RotateImage {
    public partial class Form1 : Form {
        private readonly Graphics gfx;
        private readonly Bitmap originalBitmap;
        private readonly Bitmap redrawnBitmap;
        private readonly Stopwatch sw;

        private Timer timer;
        public Form1() {
            InitializeComponent();
            BackColor = Color.White;

            timer = new Timer();
            timer.Interval = 16;
            timer.Enabled = true;
            timer.Tick += timer_Tick;
            sw = new Stopwatch();
            sw.Start();

            gfx = CreateGraphics();

            originalBitmap = new Bitmap(256, 256);
            redrawnBitmap = new Bitmap(256, 256);
            using (var bmpGfx = Graphics.FromImage(originalBitmap)) {
                DrawCross(bmpGfx, new Point(128, 128), 128D, 0D);
            }
        }

        private void timer_Tick(object sender, EventArgs e) {
            // Rotate a full 90 degrees every 4 seconds.
            var angle = sw.Elapsed.TotalSeconds * 22.5D;

            var newBitmap = RotateImage(originalBitmap, (float)angle);

            // Clear the result of the last draw.
            gfx.FillRectangle(Brushes.White, new Rectangle(0, 0, 256, 256));

            gfx.DrawImageUnscaled(newBitmap, 0, 0);
            gfx.DrawEllipse(Pens.Blue, new Rectangle(124, 124, 8, 8));

            using (var redrawGfx = Graphics.FromImage(redrawnBitmap)) {
                // Clear what we have, we are redrawing on the same surface.
                redrawGfx.Clear(Color.White);
                DrawCross(redrawGfx, new Point(128, 128), 128D, angle);
            }
            gfx.DrawImageUnscaled(redrawnBitmap, 256, 0);
            gfx.DrawEllipse(Pens.Blue, new Rectangle(256+124, 124, 8, 8));
        }

        private void DrawCross(Graphics drawGfx, Point center, double radius, double angle) {
            // Turn our angle from degrees to radians.
            angle *= Math.PI / 180;

            // NOTE: Using PointF to lazily "fix" rounding errors and casting (flooring) double to int. When the result of the math below is say 127.9999999...
            // then it would get rounded down to 127. There is always Math.Round, which can round to nearest whole (away from .5) integer!
            // Draw one line of our cross.
            drawGfx.DrawLine(
                Pens.Red,
                new PointF((float)(Math.Cos(angle) * radius + center.X), (float)(Math.Sin(angle) * radius + center.Y)),
                new PointF((float)(Math.Cos(angle - Math.PI) * radius + center.X), (float)(Math.Sin(angle - Math.PI) * radius + center.Y)));

            // Rotate our angle 90 degrees.
            angle += Math.PI / 2D;

            // Draw the other line of our cross.
            drawGfx.DrawLine(
                Pens.Red,
                new PointF((float)(Math.Cos(angle) * radius + center.X), (float)(Math.Sin(angle) * radius + center.Y)),
                new PointF((float)(Math.Cos(angle - Math.PI) * radius + center.X), (float)(Math.Sin(angle - Math.PI) * radius + center.Y)));
        }

        // Your method, not mine.
        private Bitmap RotateImage(Bitmap b, float angle)
        {
            //Create a new empty bitmap to hold rotated image.
            Bitmap returnBitmap = new Bitmap(b.Width, b.Height);
            //Make a graphics object from the empty bitmap.
            Graphics g = Graphics.FromImage(returnBitmap);
            //move rotation point to center of image.
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.TranslateTransform((float) b.Width / 2, (float)b.Height / 2);
            //Rotate.        
            g.RotateTransform(angle);
            //Move image back.
            g.TranslateTransform(-(float)b.Width / 2, -(float)b.Height / 2);
            //Draw passed in image onto graphics object.
            g.DrawImage(b, new Point(0, 0));
            return returnBitmap;
        }
    }
}

觀察兩個十字架圍繞它們的中心旋轉就好了。 左邊的一個是用你的方法旋轉的位圖,右邊的每一幀都重繪一次。 也就是說,您的旋轉代碼沒有任何問題,但是您的源位圖或顯示容器可能存在問題。

當您使用透明的png時,只有一部分圖像填充了顏色 - 代碼將旋轉只轉換png中包含數據的部分...

我試圖在png的頂部中心得到一個點,圍繞圖像的中心(500x500像素)旋轉,它只是識別出被着色的部分,因此它變成了反彈效果。

我嘗試使用全彩色500x500像素圖像,並且正常工作..

希望它有點幫助!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM