2017年5月8日月曜日

ジグザグスキャン

 ジグザグスキャンの回し方とか考えてみた。あんまり動作チェックしてないので間違ってたらごめんね。

 戻り値がIEnumerable<Point>なので、Pointを受け取るforeachで回せる。ZigZagScan.ScanのArg1に幅、Arg2に高さを与え、Arg3がtrueなら左上からスキャンを開始し、Arg4がtrueならまず右側に移動する。
 Arg3はJPEGで言うとDC成分をスキャンするかしないかを指定する。Arg4は開始する向きが右か下かを指定し、JPEGならfalseを指定することになるハズ。
 JPEGの場合は8x8の固定サイズなわけだが、コレは長方形にも対応している。ただし、幅高さともに2以上を指定すること。どちらかが1以下の場合は正常に動作しない。



struct ZigZagScan
{
    private static void Next(int Width, int Height, ref int X, ref int Y, ref int aX, ref int aY)
    {
        X += aX;
        Y += aY;

        if (false) { }
        else if (Y >= Height) { Y--; X += aX == -1 ? 2 : 1; aX = +1; aY = -1; }
        else if (X >= Width) { X--; Y += aY == -1 ? 2 : 1; aX = -1; aY = +1; }
        else if (aX == +1 && aY == +0) { aX = -1; aY = +1; }
        else if (aX == +0 && aY == +1) { aX = +1; aY = -1; }
        else if (aX == -1 && X == +0) { aX = +0; aY = +1; }
        else if (aY == -1 && Y == +0) { aX = +1; aY = +0; }
    }

    public static IEnumerable<Point> Scan(int Width, int Height, bool ZeroStart = true, bool FirstRight = true)
    {
        int X = 0;
        int Y = 0;
        int aX = 0;
        int aY = 0;

        if (FirstRight)
        {
            aX = 1; aY = 0;
        }
        else
        {
            aX = 0; aY = 1;
        }

        if (!ZeroStart)
        {
            Next(Width, Height, ref X, ref Y, ref aX, ref aY);
        }

        while (X < Width && Y < Height)
        {
            yield return (new Point(X, Y));
            Next(Width, Height, ref X, ref Y, ref aX, ref aY);
        }
    }
}

0 件のコメント:

コメントを投稿