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