#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

mt19937 mrand(random_device{} ()); 

int rnd(int x) {
  return mrand() % x;
}

typedef long double ld;
typedef long long ll;

#ifdef DEBUG
#define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define pb push_back
#define mp make_pair
#define sz(x) ((int) (x).size())
#define TASK "text"

const int inf = (int) 1.01e9;
const ld eps = 1e-9;
const ld pi = acos((ld) -1.0);

void precalc() {
}

const int mod = (int) 1e9 + 7;

int mult(int x, int y) {
  return (long long) x * y % mod;
}

const int maxn = 200 + 10;

int n, m;
char s[maxn][maxn];

int read() {
  if (scanf("%d%d", &n, &m) < 2) {
    return 0;
  }
  for (int i = 0; i < n; ++i) {
    scanf("%s", s[i]);
  }
  return 1;
}

const int maxv = maxn * 2, maxk = (maxv + 31) / 32;
unsigned a[maxv][maxk];

int xs[maxv];
int used[maxv];

void solve() {
  int k = (n + m + 31) / 32;
  assert(k <= maxk);

  int cnt = 0;
  for (int i = 0; i < n + m; ++i) {
    used[i] = 0;
  }

  int res = 1;
  for (int i = 0; i <= n - i - 1; ++i) {
    for (int j = 0; j <= m - j - 1; ++j) {
      static vector<char> chs;
      chs.clear();
      for (int it1 = 0; it1 < 2; ++it1) {
        int ri = !it1 ? i : (n - i - 1);
        if (it1 && ri == i) {
          continue;
        }
        for (int it2 = 0; it2 < 2; ++it2) {
          int rj = !it2 ? j : (m - j - 1);
          if (it2 && rj == j) {
            continue;
          }
          chs.pb(s[ri][rj]);
        }
      }
      sort(chs.begin(), chs.end());
      int perm = 1;
      int ccnt = 0;
      for (int i = 0; i < sz(chs);) {
        int i0 = i;
        while (i < sz(chs) && chs[i] == chs[i0]) {
          ++i;
        }
        for (int j = 0; j < i - i0; ++j) {
          perm *= i - j;
          perm /= j + 1;
        }
        ++ccnt;
      }
      //eprintf("perm = %d, res = %d\n", perm, res);

      if (ccnt == 1 || ccnt != sz(chs)) {
        res = mult(res, perm);
      } else {
        assert(!(perm & 1));
        res = mult(res, perm / 2);
        memset(a[cnt], 0, sizeof(a[cnt]));
        if (j < m - 1 - j) {
          a[cnt][i >> 5] |= (1u << (i & 31));
          a[cnt][(n - 1 - i) >> 5] |= (1u << ((n - 1 - i) & 31));
        }
        if (i < n - 1 - i) {
          a[cnt][(n + j) >> 5] |= (1u << ((n + j) & 31));
          a[cnt][(n + m - 1 - j) >> 5] |= (1u << ((n + m - 1 - j) & 31));
        }
        for (int i = 0; i < cnt; ++i) {
          if (1 & (a[cnt][xs[i] >> 5] >> (xs[i] & 31))) {
            for (int j = 0; j < k; ++j) {
              a[cnt][j] ^= a[i][j];
            }
          }
        }
        for (int c = 0; c < n + m; ++c) {
          if (used[c] || !(1 & (a[cnt][c >> 5] >> (c & 31)))) {
            continue;
          }
          used[c] = 1;
          res = mult(res, 2);
          xs[cnt] = c;

          for (int i = 0; i < cnt; ++i) {
            if (!(1 & (a[i][c >> 5] >> (c & 31)))) {
              continue;
            }
            for (int j = 0; j < k; ++j) {
              a[i][j] ^= a[cnt][j];
            }
          }
          ++cnt;
          break;
        }
      }
    }
  }
  printf("%d\n", res);
}

int main() {
  precalc();
#ifdef LOCAL
  freopen(TASK ".out", "w", stdout);
  assert(freopen(TASK ".in", "r", stdin));
#endif

  while (1) {
    if (!read()) {
      break;
    }
    solve();
#ifdef DEBUG
    eprintf("Time %.2f\n", (double) clock() / CLOCKS_PER_SEC);
#endif
  }
  return 0;
}


Measured memory_bytes: 384