Rotate an image in Silverlight without cropping

I am currently working on a simple Silverlight application that will allow people to upload an image, crop, resize and rotate it, and then upload through a web service to the CMS.

Cropping and resizing done, however rotation causes some problems. The image becomes cropped and is out of center after rotation.

WriteableBitmap wb = new WriteableBitmap(destWidth, destHeight);

RotateTransform rt = new RotateTransform();
rt.Angle = 90;
rt.CenterX = width/2;
rt.CenterY = height/2;

//Draw to the Writeable Bitmap
Image tempImage2 = new Image();
tempImage2.Width = width;
tempImage2.Height = height;
tempImage2.Source = rawImage;

wb.Render(tempImage2,rt);
wb.Invalidate();
rawImage = wb;

message.Text = "h:" + rawImage.PixelHeight.ToString();
message.Text += ":w:" + rawImage.PixelWidth.ToString();

//Finally set the Image back
MyImage.Source = wb;
MyImage.Width = destWidth;
MyImage.Height = destHeight;

At the moment, only the code should rotate 90 °, so I set destWidthand destHeightin accordance with the height and width of the original image.

+3
source share
4 answers

, , . 90 , :

WriteableBitmap wb = new WriteableBitmap(destHeight, destWidth);

, , . , :

rt.CenterX = rt.CenterY = Math.Min(width / 2, height / 2);

, , .

+7

, ... . , , .

        int width = currentImage.PixelWidth;
        int height = currentImage.PixelHeight;
        int full = Math.Max(width, height);

        Image tempImage2 = new Image();
        tempImage2.Width = full;
        tempImage2.Height = full;
        tempImage2.Source = currentImage;

        // New bitmap has swapped width/height
        WriteableBitmap wb1 = new WriteableBitmap(height,width);


        TransformGroup transformGroup = new TransformGroup();

        // Rotate around centre
        RotateTransform rotate = new RotateTransform();
        rotate.Angle = 90;
        rotate.CenterX = full/2;
        rotate.CenterY = full/2;
        transformGroup.Children.Add(rotate);

        // and transform back to top left corner of new image
        TranslateTransform translate = new TranslateTransform();
        translate.X = -(full - height) / 2;
        translate.Y = -(full - width) / 2;
        transformGroup.Children.Add(translate);



        wb1.Render(tempImage2, transformGroup);
        wb1.Invalidate();
+2

, .

, , , , , .

    //Draw to the Writeable Bitmap
    Image tempImage2 = new Image();
    tempImage2.Width = Math.Max(width, height);
    tempImage2.Height = Math.Max(width, height);
    tempImage2.Source = rawImage;
0

, .

, , 2 , , . , .

, ( ):

enter image description here

double CalculateConstraintScale(double rotation, int pixelWidth, int pixelHeight)

( # ):

  • ""
  • BR
  • BL
  • ( ABS)
  • /2/x,
  • /2/y,

- , .

** Note. Although many mathematical operations can be performed using matrix operations, calculations are not enough for this. I also thought that this would be the best example of the first principles. *

C # code:

    /// <summary>
    /// Calculate the scaling required to fit a rectangle into a rotation of that same rectangle
    /// </summary>
    /// <param name="rotation">Rotation in degrees</param>
    /// <param name="pixelWidth">Width in pixels</param>
    /// <param name="pixelHeight">Height in pixels</param>
    /// <returns>A scaling value between 1 and 0</returns>
    /// <remarks>Released to the public domain 2011 - David Johnston (HiTech Magic Ltd)</remarks>
    private double CalculateConstraintScale(double rotation, int pixelWidth, int pixelHeight)
    {
        // Convert angle to radians for the math lib
        double rotationRadians = rotation * PiDiv180;

        // Centre is half the width and height
        double width = pixelWidth / 2.0;
        double height = pixelHeight / 2.0;
        double radius = Math.Sqrt(width * width + height * height);

        // Convert BR corner into polar coordinates
        double angle = Math.Atan(height / width);

        // Now create the matching BL corner in polar coordinates
        double angle2 = Math.Atan(height / -width);

        // Apply the rotation to the points
        angle += rotationRadians;
        angle2 += rotationRadians;

        // Convert back to rectangular coordinate
        double x = Math.Abs(radius * Math.Cos(angle));
        double y = Math.Abs(radius * Math.Sin(angle));
        double x2 = Math.Abs(radius * Math.Cos(angle2));
        double y2 = Math.Abs(radius * Math.Sin(angle2));

        // Find the largest extents in X & Y
        x = Math.Max(x, x2);
        y = Math.Max(y, y2);

        // Find the largest change (pixel, not ratio)
        double deltaX = x - width;
        double deltaY = y - height;

        // Return the ratio that will bring the largest change into the region
        return (deltaX > deltaY) ? width / x : height / y;
    }

Usage example:

    private WriteableBitmap GenerateConstrainedBitmap(BitmapImage sourceImage, int pixelWidth, int pixelHeight, double rotation)
    {
        double scale = CalculateConstraintScale(rotation, pixelWidth, pixelHeight);

        // Create a transform to render the image rotated and scaled
        var transform = new TransformGroup();
        var rt = new RotateTransform()
            {
                Angle = rotation,
                CenterX = (pixelWidth / 2.0),
                CenterY = (pixelHeight / 2.0)
            };
        transform.Children.Add(rt);
        var st = new ScaleTransform()
            {
                ScaleX = scale,
                ScaleY = scale,
                CenterX = (pixelWidth / 2.0),
                CenterY = (pixelHeight / 2.0)
            };
        transform.Children.Add(st);

        // Resize to specified target size
        var tempImage = new Image()
            {
                Stretch = Stretch.Fill,
                Width = pixelWidth,
                Height = pixelHeight,
                Source = sourceImage,
            };
        tempImage.UpdateLayout();

        // Render to a writeable bitmap
        var writeableBitmap = new WriteableBitmap(pixelWidth, pixelHeight);
        writeableBitmap.Render(tempImage, transform);
        writeableBitmap.Invalidate();
        return writeableBitmap;
    }

I released a test layer of code on my website so you can actually try it - click to try

PS Yes, this is my answer from another question, which is repeated exactly, but the question requires the same answer as the one that will be complete.

0
source

Source: https://habr.com/ru/post/1738309/


All Articles