Какой самый быстрый способ поворота изображения без обрезки его краев с помощью GDI +? - PullRequest
3 голосов
/ 21 сентября 2010

Для этого есть несколько неопрятных и голодных алгоритмов, но пока я не придумал и не нашел ничего особенно быстрого.

Ответы [ 5 ]

5 голосов
/ 28 сентября 2010

Самый быстрый способ для этого - использовать небезопасные вызовы для непосредственной манипуляции с памятью изображений, используя LockBits. Звучит страшно, но довольно просто. Если вы ищете LockBits, вы найдете множество примеров, таких как здесь .

Интересный бит:

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

Когда у вас есть BitmapData, вы можете передать пиксели и отобразить их в новом изображении (снова используя LockBits). Это значительно быстрее, чем при использовании Graphics API.

4 голосов
/ 28 сентября 2010

Вот что я закончил (после продолжительного исследования и полезной ссылки, предоставленной 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;
    }

Приветствия!

0 голосов
/ 11 мая 2018
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);
0 голосов
/ 02 ноября 2014

Этот ответ возвращает как смещение, на котором он должен быть нарисован, так и изображение, которое было повернуто. Он работает путем воссоздания нового изображения до размера, в котором оно должно быть, без ограничения углов. Первоначально написано Хисенбургом из чата # C # IRC и 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);
    }
0 голосов
/ 21 сентября 2010
void Graphics.RotateTransform(float angle);

Это должно повернуть изображение в C #. Что он делает вместо этого?

Я не слишком много экспериментировал с GDI +. Не забудьте изменить направление вращения после прорисовки изображения.

...