戻り値が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 件のコメント:
コメントを投稿