3

マウスの位置を使用して、画像をスケーリングするための倍率を計算しようとしています。基本的に、画像の中心から離れるほど大きくなります。中心に近づくほど小さくなります。私はこれまでにいくつかのコードを持っていますが、それは本当に奇妙に動作しており、これ以上のアイデアはまったくありません. 最初にお知らせしますが、私がやろうとしていたことの 1 つは、よりスムーズなサイズ変更アニメーションを得るために 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

        }
    }
4

2 に答える 2

1

すでにスケーリングされた画像を再スケーリングしているように(scaleAvg計算から)私には見えます。スケーリングには損失が多く、エラーが蓄積されるため、これは非常に悪い考えです。代わりに、鮮明な元の画像のコピーを保持し、元の画像を現在のサイズに直接スケーリングします。

また、2ノルムである現在のデカルト距離の代わりに、別のノルム、おそらくマンハッタン距離を使用することをお勧めします。

2 ノルムを引き続き使用する場合は、Math.Pow 呼び出しを取り除くことを検討してください。それらはおそらく全体的なスケーリングの複雑さの非常に小さな部分であるため、問題にはなりませんが、それ自体で乗算することは、数値を 2 乗するための Math.Pow よりもはるかに高速である必要があります。

于 2010-04-02T05:20:00.043 に答える
1

画像の中心を使用すると、スケーリングがスムーズになりません。代わりに、最初のマウス ダウン ポイントを使用します (p0 と呼びます)。また、そのポイントから現在のドラッグ ポイントまでの距離 (e) を使用するのではなく、1 つの軸に沿って差をとります (例: exp(eY - p0.Y))。

于 2010-04-02T05:29:54.263 に答える