Нарисуйте вращаемое изображение синуса - PullRequest
1 голос
/ 07 марта 2011

Я работаю с 2D-преобразованиями Фурье, и у меня есть метод, который выведет следующий результат: Original Image

Код выглядит так:

    private Bitmap PaintSin(int s, int n)
    {
        Data = new int[Width, Height];
        Bitmap buffer = new Bitmap(Width, Height);

        double inner = (2 * Math.PI * s) / n;
        BitmapData originalData = buffer.LockBits(
           new Rectangle(0, 0, buffer.Width, buffer.Height),
           ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);

        for (int i = 0; i < buffer.Width; i++)
        {
            for (int j = 0; j < buffer.Height; j++)
            {
                double val;
                int c = 0;

                if (j == 0)
                {
                    val = Math.Sin(inner * i);
                    val += 1;
                    val *= 128;
                    val = val > 255 ? 255 : val;
                    c = (int)val;

                    Color col = Color.FromArgb(c, c, c);
                    SetPixel(originalData, i, j, col);
                }
                else
                    SetPixel(originalData, i, j, GetColor(originalData, i, 0));

                Data[i, j] = c;
            }
        }
        buffer.UnlockBits(originalData);

        return buffer;
    }

Теперь я пытаюсь придумать формулу, которая будет принимать угол и выводит изображение, где сплошные линии находятся под заданным углом.

Например, если я введу 45 градусов, результат будет:

Rotated image

Спасибо за любую помощь!

Вот код SetPixel, если это необходимо:

    private unsafe void SetPixel(BitmapData originalData, int x, int y, Color color)
    {
        //set the number of bytes per pixel
        int pixelSize = 3;

        //get the data from the original image
        byte* oRow = (byte*)originalData.Scan0 + (y * originalData.Stride);

        //set the new image's pixel to the grayscale version
        oRow[x * pixelSize] = color.B; //B
        oRow[x * pixelSize + 1] = color.G; //G
        oRow[x * pixelSize + 2] = color.R; //R
    }

Ответы [ 2 ]

2 голосов
/ 07 марта 2011

Это должно быть возможно при использовании повернутой системы координат. Преобразование i и j выглядит следующим образом:

x = i * cos(angle) - j * sin(angle);
y = j * cos(angle) + i * sin(angle);

Примечание: я не уверен в градусах / радианах, поэтому настройте angle так, чтобы он соответствовал единице, которая нужна cos и sin. Кроме того, вам, возможно, придется отрицать угол в зависимости от желаемого направления вращения.

На самом деле вам нужен только x, который заменяет использование i. Мы предварительно вычислим sin(angle) и cos(angle), потому что это довольно дорогие операции, которые нам не нужны во внутренних циклах. Кроме того, ваша оптимизация удалена, поскольку мы не можем нарисовать только одну линию и повторить ее:

    [...]
    // double angle = ...
    double cos_angle = cos(angle);
    double sin_angle = sin(angle);
    for (int i = 0; i < buffer.Width; i++)
    {
        for (int j = 0; j < buffer.Height; j++)
        {
            double val;
            double x;
            int c = 0;

            x = i * cos_angle - j * sin_angle;
            val = Math.Sin(inner * x);
            val += 1;
            val *= 128;
            val = val > 255 ? 255 : val;
            c = (int)val;

            Color col = Color.FromArgb(c, c, c);
            SetPixel(originalData, i, j, col);

            Data[i, j] = c;
        }
    }
0 голосов
/ 07 марта 2011

Вы можете написать простую функцию rotate (x, y, angle) и использовать ее результат в SetPixel.Вы можете погуглить для матрицы вращения.Вызов с углом = 0 должен привести к выводу по умолчанию.

...