簡體   English   中英

Silverlight旋轉和縮放位圖圖像以適合矩形而無需裁剪

[英]Silverlight Rotate & Scale a bitmap image to fit within rectangle without cropping

我需要旋轉一個WriteableBitmap並對其進行縮放,然后再進行裁剪。

我當前的代碼將旋轉,但是如果高度大於寬度,則會裁切邊緣。

我認為我需要擴展?

 public WriteableBitmap Rotate(WriteableBitmap Source, double Angle)
        {
            RotateTransform rt = new RotateTransform();
            rt.Angle = Angle;

            TransformGroup transform = new TransformGroup();
            transform.Children.Add(rt);

            Image tempImage2 = new Image();
            WriteableBitmap wb;
            rt.CenterX = Source.PixelWidth / 2;
            rt.CenterY = Source.PixelHeight / 2;
            tempImage2.Width = Source.PixelWidth;
            tempImage2.Height = Source.PixelHeight;
            wb = new WriteableBitmap((int)(Source.PixelWidth), Source.PixelHeight);
            tempImage2.Source = Source;
            tempImage2.UpdateLayout();

            wb.Render(tempImage2, transform);
            wb.Invalidate();

            return wb;

        }

如何縮小圖像以使其不被裁剪? 還是有另一種方法?

您需要根據角相對於中心的旋轉來計算縮放比例。

如果圖像是正方形,則僅需要一個角,但是對於矩形,則需要檢查2個角,以查看垂直邊緣或水平邊緣是否重疊。 此檢查是對矩形的高度和寬度超出多少的線性比較。

單擊此處以為此答案創建的可運行的測試平台應用程序(下圖):

在此處輸入圖片說明

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

偽代碼如下(最后是實際的C#代碼):

  • 將旋轉角度轉換為弧度
  • 計算從矩形中心到拐角的“半徑”
  • 將BR角位置轉換為極坐標
  • 將BL角位置轉換為極坐標
  • 將旋轉應用於兩個極坐標
  • 將新位置轉換回笛卡爾坐標(ABS值)
  • 找到2個水平位置中的最大位置
  • 找到2個垂直位置中的最大位置
  • 計算水平尺寸的增量變化
  • 計算垂直尺寸的增量變化
  • 返回寬度/ 2 / x(如果水平變化更大)
  • 如果垂直變化較大,則返回高度/ 2 / y

結果是一個乘法器,該縮放器將縮小圖像以適合原始矩形,而與旋轉無關。

**注意:雖然可以使用矩陣運算來進行很多數學運算,但是沒有足夠的計算來保證這一點。 我還認為這將成為一本更好的榜樣。*

C#代碼:

    /// <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;
    }

使用示例:

    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;
    }

我在我的網站上發布了該代碼的測試平台,因此您可以實際嘗試-單擊以嘗試

暫無
暫無

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

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