在不使用 GDI 裁剪图像边缘的情况下旋转图像的最快方法是什么?

发布于 2024-09-24 09:41:59 字数 52 浏览 2 评论 0原文

有一些非常漫长且饥饿的算法可以做到这一点,但到目前为止我还没有想出或发现任何特别快的算法。

There are some looooong and hungry algorithms for doing so, but as of yet I haven't come up with or found anything particularly fast.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

莫相离 2024-10-01 09:41:59

最快的方法是使用 LockBits 直接使用不安全调用来操作图像内存。听起来很可怕,但其实很简单。如果您搜索 LockBits,您会发现大量示例,例如此处

有趣的是:

BitmapData originalData = originalBitmap.LockBits(
     new Rectangle(0, 0, originalWidth, originalHeight), 
     ImageLockMode.ReadOnly, 
     PixelFormat.Format32bppRgb);

一旦你有了 BitmapData,你就可以传递像素并将它们映射到新图像中(再次使用 LockBits)。这比使用Graphics API 要快得多。

The fastest way is to this is to use unsafe calls to manipulate the image memory directly using LockBits. It sounds scary but it's pretty straight forward. If you search for LockBits you'll find plently of examples such as here.

The interesting bit is:

BitmapData originalData = originalBitmap.LockBits(
     new Rectangle(0, 0, originalWidth, originalHeight), 
     ImageLockMode.ReadOnly, 
     PixelFormat.Format32bppRgb);

Once you have the BitmapData you can pass the pixels and map them into a new image (again using LockBits). This is significantly quicker than using the Graphics API.

转身以后 2024-10-01 09:41:59

这就是我最终所做的(经过大量的持续研究以及 TheCodeKing 提供的有用链接):

public Image RotateImage(Image img, float rotationAngle)
    {
        // When drawing the returned image to a form, modify your points by 
        // (-(img.Width / 2) - 1, -(img.Height / 2) - 1) to draw for actual co-ordinates.

        //create an empty Bitmap image 
        Bitmap bmp = new Bitmap((img.Width * 2), (img.Height *2));

        //turn the Bitmap into a Graphics object
        Graphics gfx = Graphics.FromImage(bmp);

        //set the point system origin to the center of our image
        gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);

        //now rotate the image
        gfx.RotateTransform(rotationAngle);

        //move the point system origin back to 0,0
        gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);

        //set the InterpolationMode to HighQualityBicubic so to ensure a high
        //quality image once it is transformed to the specified size
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

        //draw our new image onto the graphics object with its center on the center of rotation
        gfx.DrawImage(img, new PointF((img.Width / 2), (img.Height / 2)));

        //dispose of our Graphics object
        gfx.Dispose();

        //return the image
        return bmp;
    }

干杯!

Here's what I ended up doing (after an extensive amount of continued research, and the helpful link provided by TheCodeKing):

public Image RotateImage(Image img, float rotationAngle)
    {
        // When drawing the returned image to a form, modify your points by 
        // (-(img.Width / 2) - 1, -(img.Height / 2) - 1) to draw for actual co-ordinates.

        //create an empty Bitmap image 
        Bitmap bmp = new Bitmap((img.Width * 2), (img.Height *2));

        //turn the Bitmap into a Graphics object
        Graphics gfx = Graphics.FromImage(bmp);

        //set the point system origin to the center of our image
        gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);

        //now rotate the image
        gfx.RotateTransform(rotationAngle);

        //move the point system origin back to 0,0
        gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);

        //set the InterpolationMode to HighQualityBicubic so to ensure a high
        //quality image once it is transformed to the specified size
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;

        //draw our new image onto the graphics object with its center on the center of rotation
        gfx.DrawImage(img, new PointF((img.Width / 2), (img.Height / 2)));

        //dispose of our Graphics object
        gfx.Dispose();

        //return the image
        return bmp;
    }

Cheers!

风启觞 2024-10-01 09:41:59
void Graphics.RotateTransform(float angle);

这应该在 C# 中旋转图像。它在做什么?

我还没有对 GDI+ 做过太多实验。记得在绘制图像后反转旋转。

void Graphics.RotateTransform(float angle);

This should rotate the image in C#. What is it doing instead?

I haven't experimented too much with GDI+. Remember to reverse the rotation after the image is drawn.

∞觅青森が 2024-10-01 09:41:59

这个答案返回它应该绘制的偏移量和已经旋转的图像。它的工作原理是在不剪裁角度的情况下将新图像重新创建到它应该的大小。最初由 #C# IRC 聊天室和 Bloodyaugust 的 Hisenburg 编写。

   public static double NormalizeAngle(double angle)
    {
        double division = angle / (Math.PI / 2);
        double fraction = Math.Ceiling(division) - division;

        return (fraction * Math.PI / 2);
    }


    public static Tuple<Image,Size> RotateImage(Image img, double rotationAngle)
    {

        double normalizedRotationAngle = NormalizeAngle(rotationAngle);

        double widthD = img.Width, heightD = img.Height;
        double newWidthD, newHeightD;



        newWidthD = Math.Cos(normalizedRotationAngle) * widthD + Math.Sin(normalizedRotationAngle) * heightD;
        newHeightD = Math.Cos(normalizedRotationAngle) * heightD + Math.Sin(normalizedRotationAngle) * widthD;

        int newWidth, newHeight;
        newWidth = (int)Math.Ceiling(newWidthD);
        newHeight = (int)Math.Ceiling(newHeightD);

        Size offset = new Size((newWidth - img.Width) / 2,(newHeight - img.Height) / 2);

        Bitmap bmp = new Bitmap(newWidth, newHeight);
        Graphics gfx = Graphics.FromImage(bmp);
        //gfx.Clear(Color.Blue);
        gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);
        gfx.RotateTransform((float)(rotationAngle / Math.PI * 180));
        gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
        gfx.DrawImage(img, new PointF((bmp.Width / 2 - img.Width / 2), (bmp.Height / 2 - img.Height / 2)));
        gfx.Dispose();  
        return new Tuple<Image,Size>(bmp,offset);
    }

This answer returns both the offset it should be drawn on and the image which has been rotated.It works by recreating the new image to the size it should be without clipping the angles. Originally written by Hisenburg from the #C# IRC chatroom and Bloodyaugust.

   public static double NormalizeAngle(double angle)
    {
        double division = angle / (Math.PI / 2);
        double fraction = Math.Ceiling(division) - division;

        return (fraction * Math.PI / 2);
    }


    public static Tuple<Image,Size> RotateImage(Image img, double rotationAngle)
    {

        double normalizedRotationAngle = NormalizeAngle(rotationAngle);

        double widthD = img.Width, heightD = img.Height;
        double newWidthD, newHeightD;



        newWidthD = Math.Cos(normalizedRotationAngle) * widthD + Math.Sin(normalizedRotationAngle) * heightD;
        newHeightD = Math.Cos(normalizedRotationAngle) * heightD + Math.Sin(normalizedRotationAngle) * widthD;

        int newWidth, newHeight;
        newWidth = (int)Math.Ceiling(newWidthD);
        newHeight = (int)Math.Ceiling(newHeightD);

        Size offset = new Size((newWidth - img.Width) / 2,(newHeight - img.Height) / 2);

        Bitmap bmp = new Bitmap(newWidth, newHeight);
        Graphics gfx = Graphics.FromImage(bmp);
        //gfx.Clear(Color.Blue);
        gfx.TranslateTransform((float)bmp.Width / 2, (float)bmp.Height / 2);
        gfx.RotateTransform((float)(rotationAngle / Math.PI * 180));
        gfx.TranslateTransform(-(float)bmp.Width / 2, -(float)bmp.Height / 2);
        gfx.InterpolationMode = InterpolationMode.HighQualityBicubic;
        gfx.DrawImage(img, new PointF((bmp.Width / 2 - img.Width / 2), (bmp.Height / 2 - img.Height / 2)));
        gfx.Dispose();  
        return new Tuple<Image,Size>(bmp,offset);
    }
假情假意假温柔 2024-10-01 09:41:59
System.Drawing.Image imageToRotate = System.Drawing.Image.FromFile(imagePath);
switch (rotationAngle.Value)
{
    case "90":
        imageToRotate.RotateFlip(RotateFlipType.Rotate90FlipNone);
        break;
    case "180":
        imageToRotate.RotateFlip(RotateFlipType.Rotate180FlipNone);
        break;
    case "270":
        imageToRotate.RotateFlip(RotateFlipType.Rotate270FlipNone);
        break;
    default:
        throw new Exception("Rotation angle not supported.");
}
imageToRotate.Save(imagePath, ImageFormat.Jpeg);
System.Drawing.Image imageToRotate = System.Drawing.Image.FromFile(imagePath);
switch (rotationAngle.Value)
{
    case "90":
        imageToRotate.RotateFlip(RotateFlipType.Rotate90FlipNone);
        break;
    case "180":
        imageToRotate.RotateFlip(RotateFlipType.Rotate180FlipNone);
        break;
    case "270":
        imageToRotate.RotateFlip(RotateFlipType.Rotate270FlipNone);
        break;
    default:
        throw new Exception("Rotation angle not supported.");
}
imageToRotate.Save(imagePath, ImageFormat.Jpeg);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文