0

こんにちは。Get/Set Pixel と RotateTransfom のパフォーマンスの低下と風変わりな動作にうんざりした後、2D ビットマップ イメージの回転に LockBits を使用することにしました。これが私が思いついたコードです。私の推測では、完全に機能するはずです。そうではありません。

private static void InternalRotateImage(Bitmap originalBitmap, Bitmap rotatedBitmap, PointF centerPoint, float theta)
    {
        BitmapData originalData = originalBitmap.LockBits(
            new Rectangle(0, 0, originalBitmap.Width, originalBitmap.Height),
            ImageLockMode.ReadOnly,
            originalBitmap.PixelFormat);

        BitmapData rotatedData = rotatedBitmap.LockBits(
            new Rectangle(0, 0, rotatedBitmap.Width, rotatedBitmap.Height),
            ImageLockMode.WriteOnly,
            rotatedBitmap.PixelFormat);

        unsafe
        {
            byte[,] A = new byte[originalData.Height * 2, originalBitmap.Width * 2];
            byte[,] R = new byte[originalData.Height * 2, originalBitmap.Width * 2];
            byte[,] G = new byte[originalData.Height * 2, originalBitmap.Width * 2];
            byte[,] B = new byte[originalData.Height * 2, originalBitmap.Width * 2];

            for (int y = 0; y < originalData.Height; y++)
            {
                byte* row = (byte*)originalData.Scan0 + (y * originalData.Stride);
                for (int x = 0; x < originalData.Width; x++)
                {
                    B[y, x] = row[x * 4];
                    G[y, x] = row[x * 4 + 1];
                    R[y, x] = row[x * 4 + 2];
                    A[y, x] = row[x * 4 + 3];
                }
            }

            for (int y = 0; y < rotatedData.Height; y++)
            {
                byte* row = (byte*)rotatedData.Scan0 + (y * rotatedData.Stride);
                for (int x = 0; x < rotatedData.Width; x++)
                {
                    int newy = (int)Math.Abs((Math.Cos(theta) * (x - centerPoint.X) - Math.Sin(theta) * (y - centerPoint.Y) + centerPoint.X));
                    int newx = (int)Math.Abs((Math.Sin(theta) * (x - centerPoint.X) + Math.Cos(theta) * (y - centerPoint.Y) + centerPoint.Y));

                    row[x * 4] = B[newy, newx];
                    row[x * 4 + 1] = G[newy, newx];
                    row[x * 4 + 2] = R[newy, newx];
                    row[x * 4 + 3] = A[newy, newx];
                }
            }

        }
            originalBitmap.UnlockBits(originalData);
            rotatedBitmap.UnlockBits(rotatedData);
        }

誰かアイデアはありますか?私は新鮮です。前もって感謝します!

編集:これは私が最終的に使用したものです(Hans Passantに感謝します):

private Image RotateImage(Image img, float rotationAngle)
    {
        Image image = new Bitmap(img.Width * 2, img.Height * 2);
        Graphics gfx = Graphics.FromImage(image);

        int center = (int)Math.Sqrt(img.Width * img.Width + img.Height * img.Height) / 2;
        gfx.TranslateTransform(center, center);
        gfx.RotateTransform(rotationAngle);
        gfx.DrawImage(img, -img.Width / 2, -img.Height / 2);

        return image;
    }

フォームとは対照的に、画像ごとに、彼と同じものです。

4

1 に答える 1

2

あなたは自分自身に深い穴を掘っています。これは早い段階でうまくいきません。回転したビットマップのサイズは、幅 x 高さではありません。また、非常に非効率的です。RotateTransform を開始する必要があります。TranslateTransform も使用して、正しい画像描画場所を選択することが重要です。

次に示すのは、中心点を中心にビットマップを回転させる Windows フォーム アプリのサンプルです。オフセットは、回転時にフォームの内側の端に触れるだけです。フォームにタイマーをドロップし、[プロジェクト + プロパティ] の [リソース] タブで画像リソースを追加します。SampleImage という名前を付けます。正方形である必要はありません。コードを次のようにします。

public partial class Form1 : Form {
    private float mDegrees;
    private Image mBmp;
    public Form1() {
        InitializeComponent();
        mBmp = Properties.Resources.SampleImage;
        timer1.Enabled = true;
        timer1.Interval = 50;
        timer1.Tick += new System.EventHandler(this.timer1_Tick);
        this.DoubleBuffered = true;
    }
    private void timer1_Tick(object sender, EventArgs e) {
        mDegrees += 3.0F;
        this.Invalidate();
    }
    protected override void OnPaint(PaintEventArgs e) {
        int center = (int)Math.Sqrt(mBmp.Width * mBmp.Width + mBmp.Height * mBmp.Height) / 2;
        e.Graphics.TranslateTransform(center, center);
        e.Graphics.RotateTransform(mDegrees);
        e.Graphics.DrawImage(mBmp, -mBmp.Width/2, -mBmp.Height/2);
    }
}

32bppPArgb 形式でビットマップを作成すると、描画を大幅に高速化できます。この手順はスキップしました。

于 2010-10-05T03:34:47.720 に答える