#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int H, W, a[12][12], c[12][12], col[39], color[39], cnt[39], cnts, cntv; vector<pair<int, int>>vec; vector<int> X[39];
int V[12][12]; bool used[12][12], bet[12][12], T1[12][12], T2[12][12];

void dfs(int pos, int rem) {
	if (col[pos] >= 1) return;
	col[pos] = cnts; color[pos] = rem; cnt[cnts]++;
	for (int i = 0; i < X[pos].size(); i++) dfs(X[pos][i], rem ^ 1);
}

int dx[4] = { 0, -1, 0, 1 }, dy[4] = { 1, 0, -1, 0 };

void dfs2(int px, int py) {
	bet[px][py] = true; cntv++;
	for (int i = 0; i < 4; i++) {
		int sx = px + dx[i], sy = py + dy[i];
		if (used[sx][sy] == false || bet[sx][sy] == true) continue;
		dfs2(sx, sy);
	}
}

bool finalcheck() {
	int sx1 = 100, sy1 = 100, sx2 = 100, sy2 = 100, tx1 = 0, ty1 = 0, tx2 = 0, ty2 = 0;
	for (int i = 1; i <= H; i++) {
		for (int j = 1; j <= W; j++) {
			if (V[i][j] == 1) { sx1 = min(sx1, i); sy1 = min(sy1, j); tx1 = max(tx1, i); ty1 = max(ty1, j); }
			if (V[i][j] == 2) { sx2 = min(sx2, i); sy2 = min(sy2, j); tx2 = max(tx2, i); ty2 = max(ty2, j); }
		}
	}
	for (int i = 0; i < 144; i++) { T1[i / 12][i % 12] = false; T2[i / 12][i % 12] = false; }
	for (int i = 1; i <= H; i++) {
		for (int j = 1; j <= W; j++) {
			if (V[i][j] == 1) T1[i - sx1][j - sy1] = true;
			if (V[i][j] == 2) T2[i - sx2][j - sy2] = true;
		}
	}

	int VH = tx1 - sx1 + 1, VW = ty1 - sy1 + 1;

	for (int i = 0; i < 8; i++) {
		// 反転
		if (i == 4) {
			for (int j = 0; j < VH; j++) {
				for (int k = 0; k < VW; k++) {
					if (k < VW - 1 - k) swap(T1[j][k], T1[j][VW - 1 - k]);
				}
			}
		}
		// 判定
		bool flag2 = true;
		for (int j = 0; j < VH; j++) {
			for (int k = 0; k < VW; k++) {
				if (T1[j][k] != T2[j][k]) flag2 = false;
			}
		}
		if (flag2 == true) return true;

		// 回転
		bool T3[12][12]; for (int j = 0; j < 144; j++) T3[j / 12][j % 12] = false;
		for (int j = 0; j < VH; j++) {
			for (int k = 0; k < VW; k++) {
				if (T1[j][k] == true) T3[VW - 1 - k][j] = true;
			}
		}
		for (int j = 0; j < 144; j++) T1[j / 12][j % 12] = false;
		swap(VH, VW);
		for (int j = 0; j < VH; j++) { for (int k = 0; k < VW; k++) T1[j][k] = T3[j][k]; }
	}
	return false;
}

bool check() {
	for (int t = 0; t < (1 << (cnts - 1)); t++) {
		int bit[18]; for (int j = 0; j < cnts; j++) { if ((t&(1 << j)) == 0) bit[j] = 0; else bit[j] = 1; }

		pair<int, int>S1 = make_pair(0, 0), S2 = make_pair(0, 0);

		for (int i = 1; i <= H; i++) {
			for (int j = 1; j <= W; j++) {
				if (c[i][j] == -1) V[i][j] = 0;
				else V[i][j] = 1 + (bit[col[c[i][j]] - 1] ^ color[c[i][j]]);

				if (V[i][j] == 1 && S1 == make_pair(0, 0)) S1 = make_pair(i, j);
				if (V[i][j] == 2 && S2 == make_pair(0, 0)) S2 = make_pair(i, j);
			}
		}
		bool ok = true;

		for (int j = 1; j <= H; j++) { for (int k = 1; k <= W; k++) { used[j][k] = false; bet[j][k] = false; } }
		for (int j = 1; j <= H; j++) {
			for (int k = 1; k <= W; k++) { if (V[j][k] == 1) used[j][k] = true; }
		}
		cntv = 0; dfs2(S1.first, S1.second); if (cntv != vec.size() / 2) ok = false;

		for (int j = 1; j <= H; j++) { for (int k = 1; k <= W; k++) { used[j][k] = false; bet[j][k] = false; } }
		for (int j = 1; j <= H; j++) {
			for (int k = 1; k <= W; k++) { if (V[j][k] == 2) used[j][k] = true; }
		}
		cntv = 0; dfs2(S2.first, S2.second); if (cntv != vec.size() / 2) ok = false;

		if (ok == true) {
			// 最後の合同判定
			bool ans = finalcheck();
			if (ans == true) {
				return true;
			}
		}
	}
	return false;
}

int main() {
	while (true) {
		cin >> W >> H; if (H == 0 && W == 0) break; vec.clear();
		for (int i = 1; i <= H; i++) {
			for (int j = 1; j <= W; j++) {
				cin >> a[i][j];
				if (a[i][j] == 1) { c[i][j] = vec.size(); vec.push_back(make_pair(i, j)); }
				else c[i][j] = -1;
			}
		}

		if (vec.size() % 2 == 1) {
			cout << "NO" << endl;
			continue;
		}

		bool flag = false;

		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < vec.size(); j++) {
				for (int k = j + 1; k < vec.size(); k++) {
					// ここからシミュレーション
					for (int l = 0; l <= 36; l++) { X[l].clear(); col[l] = 0; cnt[l] = 0; cnts = 0; color[l] = 0; }

					for (int px = 1; px <= H; px++) {
						for (int py = 1; py <= W; py++) {
							if (c[px][py] == -1) continue;
							int vx = px - vec[j].first, vy = py - vec[j].second;
							for (int l = 0; l < (i % 4); l++) { int ux = -vy, uy = vx; vx = ux; vy = uy; }
							if (i >= 4) { vx *= -1; }

							int sx = vec[k].first + vx, sy = vec[k].second + vy;
							if (sx <= 0 || sy <= 0 || sx > H || sy > W || c[sx][sy] == -1) continue;
							X[c[px][py]].push_back(c[sx][sy]);
							X[c[sx][sy]].push_back(c[px][py]);
						}
					}

					for (int l = 0; l < vec.size(); l++) {
						if (col[l] >= 1) continue;
						cnts++; dfs(l, 0);
					}

					bool ok = true;
					for (int l = 1; l <= cnts; l++) { if (cnt[l] % 2 == 1) ok = false; }

					if (ok == false) continue;

					bool T = check();
					if (T == true) {
						cout << "YES" << endl;
						flag = true;
						break;
					}
				}
				if (flag == true) break;
			}
			if (flag == true) break;
		}
		if (flag == false) cout << "NO" << endl;
	}
	return 0;
}


Measured memory_bytes: 3124