【问题标题】:Scaling an image using the mouse in a WinForms application?在 WinForms 应用程序中使用鼠标缩放图像?
【发布时间】:2011-02-03 15:06:47
【问题描述】:

我正在尝试使用鼠标的位置来计算缩放图像的缩放因子。基本上,你离图像中心越远,它就越大;越靠近中心,它就越小。到目前为止我有一些代码,但它的行为真的很奇怪,我完全没有更多的想法。首先我要告诉你,我想做的一件事是平均 5 个距离以获得更平滑的调整大小动画。这是我的代码:

private void pictureBoxScale_MouseMove(object sender, MouseEventArgs e)
{
    if (rotateScaleMode && isDraggingToScale)
    {
        // For Scaling              
        int sourceWidth = pictureBox1.Image.Width;
        int sourceHeight = pictureBox1.Image.Height;
        float dCurrCent = 0; // distance between the current mouse pos and the center of the image
        float dPrevCent = 0; // distance between the previous mouse pos and the center of the image

        System.Drawing.Point imgCenter = new System.Drawing.Point();

        imgCenter.X = pictureBox1.Location.X + (sourceWidth / 2);
        imgCenter.Y = pictureBox1.Location.Y + (sourceHeight / 2);

        // Calculating the distance between the current mouse location and the center of the image
        dCurrCent = (float)Math.Sqrt(Math.Pow(e.X - imgCenter.X, 2) + Math.Pow(e.Y - imgCenter.Y, 2));

        // Calculating the distance between the previous mouse location and the center of the image
        dPrevCent = (float)Math.Sqrt(Math.Pow(prevMouseLoc.X - imgCenter.X, 2) + Math.Pow(prevMouseLoc.Y - imgCenter.Y, 2));

        if (smoothScaleCount < 5)
        {
            dCurrCentSmooth[smoothScaleCount] = dCurrCent;
            dPrevCentSmooth[smoothScaleCount] = dPrevCent;
        }


        if (smoothScaleCount == 4)
        {
            float currCentSum = 0;
            float prevCentSum = 0;
            for (int i = 0; i < 4; i++)
            {
                currCentSum += dCurrCentSmooth[i];
            }
            for (int i = 0; i < 4; i++)
            {
                prevCentSum += dPrevCentSmooth[i];
            }

            float scaleAvg = (currCentSum / 5) / (prevCentSum / 5);


            int destWidth = (int)(sourceWidth * scaleAvg);
            int destHeight = (int)(sourceHeight * scaleAvg);

            // If statement is for limiting the size of the image
            if (destWidth > (currentRotatedImage.Width / 2) && destWidth < (currentRotatedImage.Width * 3) && destHeight > (currentRotatedImage.Height / 2) && destWidth < (currentRotatedImage.Width * 3))
            {
                AForge.Imaging.Filters.ResizeBilinear resizeFilter = new AForge.Imaging.Filters.ResizeBilinear(destWidth, destHeight);
                pictureBox1.Image = resizeFilter.Apply((Bitmap)currentRotatedImage);
                pictureBox1.Size = pictureBox1.Image.Size;
                pictureBox1.Refresh();
            }

            smoothScaleCount = -1;
        }
        prevMouseLoc = e.Location;
        currentScaledImage = pictureBox1.Image;
        smoothScaleCount++;

    }
}

编辑:感谢 Ben Voigt 和 Ray,现在一切正常。唯一的问题是,按照我的做法,图像并没有保持它的比例。但我稍后会解决这个问题。以下是我为那些想知道的人提供的:

private void pictureBoxScale_MouseMove(object sender, MouseEventArgs e)
    {
        if (rotateScaleMode && isDraggingToScale)
        {
            // For Scaling              
            int sourceWidth = pictureBox1.Image.Width;
            int sourceHeight = pictureBox1.Image.Height;
            int scale = e.X + p0.X; //p0 is the location of the mouse when the button first came down
            int destWidth = (int)(sourceWidth + (scale/10)); //I divide it by 10 to make it slower
            int destHeight = (int)(sourceHeight + (scale/10));

            if (destWidth > 20 && destWidth < 1000 && destHeight > 20 && destWidth < 1000)
            {
                AForge.Imaging.Filters.ResizeBilinear resizeFilter = new AForge.Imaging.Filters.ResizeBilinear(destWidth, destHeight);
                pictureBox1.Image = resizeFilter.Apply((Bitmap)currentRotatedImage);
                pictureBox1.Size = pictureBox1.Image.Size;
                pictureBox1.Refresh();
            }
            currentScaledImage = pictureBox1.Image; // This is only so I can rotate the scaled image in another part of my program

        }
    }

【问题讨论】:

  • @Aaronaught:“为什么这会表现得很奇怪?”
  • 我建议使用调试器进行单元测试和/或单步执行。我也会尝试不使用“平滑缩放”,因为有些部分看起来很可疑。

标签: c# image resize mouse scale


【解决方案1】:

如果您使用图像的中心,您的缩放将不会平滑。相反,使用初始鼠标向下点(称为 p0)。此外,与其使用从该点到当前拖动点 (e) 的距离,不如沿一个轴取差值(例如 exp(e.Y - p0.Y))。

【讨论】:

  • 我不知道你为什么建议用 exp 来计算无穷范数。你的意思是 max(abs(x1-x2), abs(y1-y2)) 吗?
  • 对我来说很有意义,我喜欢它。
  • @Ben。你不想要一个规范。您需要 +/- 值。 exp 只是从 +/- 值获取缩放值的某种方式。
【解决方案2】:

在我看来(来自 scaleAvg 计算)就像您正在重新缩放已经缩放的图像。这是一个非常糟糕的主意,因为缩放是有损的,并且错误会累积。相反,保留一份清晰的原始图像并将原始图像直接缩放到当前大小。

另外,我建议使用不同的范数,也许是曼哈顿距离,而不是当前的笛卡尔距离,这是一个二范数。

如果您确实继续使用二范数,请考虑摆脱 Math.Pow 调用。它们可能只是整体缩放复杂性的一小部分,因此无关紧要,但乘以自身应该比 Math.Pow 对数字求平方要快得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-04-05
    • 2021-01-30
    • 2012-11-30
    • 1970-01-01
    • 2013-11-07
    • 1970-01-01
    • 2015-06-01
    • 2019-01-01
    相关资源
    最近更新 更多