You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#旋转图像后尺寸缩小问题及代码优化求助

解决C#图像旋转后多次缩放消失的问题

你的代码问题在于每次旋转都基于原图像的斜边创建超大画布,并且将原图缩小绘制到画布中心;多次旋转时,每次都以上一次的大画布为基础再次放大画布、缩小图像,最终导致图像消失。以下是两种解决方案:

方案一:基于原始图像累积旋转角度(推荐)

始终从原始图像生成旋转后的结果,记录总旋转角度,避免累积缩放和质量损失:

首先保存原始图像的引用:

private Bitmap _originalNavigator; // 初始化时赋值为你的导航器原始图像
private float _totalRotationAngle = 0f;

然后实现旋转方法:

// 调用此方法传入每次要追加的旋转角度
private Bitmap RotateNavigator(float addAngle)
{
    _totalRotationAngle += addAngle;
    // 保持角度在0-360范围内
    _totalRotationAngle %= 360;
    if (_totalRotationAngle < 0) _totalRotationAngle += 360;

    return RotateFromOriginal(_originalNavigator, _totalRotationAngle);
}

private Bitmap RotateFromOriginal(Bitmap original, float angle)
{
    float radians = angle * (float)Math.PI / 180f;
    float cos = Math.Abs((float)Math.Cos(radians));
    float sin = Math.Abs((float)Math.Sin(radians));

    // 计算能容纳旋转后图像的最小画布尺寸
    int newWidth = (int)Math.Round(original.Width * cos + original.Height * sin);
    int newHeight = (int)Math.Round(original.Width * sin + original.Height * cos);

    Bitmap rotatedBmp = new Bitmap(newWidth, newHeight);
    using (Graphics g = Graphics.FromImage(rotatedBmp))
    {
        // 开启高质量渲染,避免旋转模糊
        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

        // 设置旋转中心为新画布的中心
        g.TranslateTransform(newWidth / 2f, newHeight / 2f);
        g.RotateTransform(angle);
        // 平移回原始图像的中心,确保旋转后图像居中
        g.TranslateTransform(-original.Width / 2f, -original.Height / 2f);

        // 绘制原始图像,不做任何缩放
        g.DrawImage(original, 0, 0);
    }
    return rotatedBmp;
}

方案二:基于上一次旋转后的图像旋转(不推荐,易损失画质)

如果必须基于上一次的旋转结果继续旋转,需计算精准的画布尺寸,避免不必要的缩放:

private Bitmap RotateImageWithoutScaling(Bitmap currentBmp, float angle)
{
    float radians = angle * (float)Math.PI / 180f;
    float cos = Math.Abs((float)Math.Cos(radians));
    float sin = Math.Abs((float)Math.Sin(radians));

    // 计算旋转后所需的最小画布尺寸
    int newWidth = (int)Math.Round(currentBmp.Width * cos + currentBmp.Height * sin);
    int newHeight = (int)Math.Round(currentBmp.Width * sin + currentBmp.Height * cos);

    Bitmap rotatedBmp = new Bitmap(newWidth, newHeight);
    using (Graphics g = Graphics.FromImage(rotatedBmp))
    {
        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
        g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;

        g.TranslateTransform(newWidth / 2f, newHeight / 2f);
        g.RotateTransform(angle);
        g.TranslateTransform(-currentBmp.Width / 2f, -currentBmp.Height / 2f);

        // 绘制当前图像,保持原始尺寸
        g.DrawImage(currentBmp, 0, 0);
    }
    return rotatedBmp;
}

原代码问题说明

  1. 原代码使用图像斜边作为画布尺寸,远大于实际需要的最小尺寸,导致原图被缩小绘制到画布中心。
  2. 多次旋转时,每次传入的是上一次的大画布,再次计算斜边会生成更大的画布,图像被持续缩小,最终消失。

内容的提问来源于stack exchange,提问作者ali demir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 09:01:30