using System;
using System.Text;
using System.Collections.Generic;
class Solve{
    int H,W;
    char[,] S;
    public Solve(){}
    StringBuilder sb;
    public static int Main(){
        new Solve().Run();
        return 0;
    }
    void Run(){
        sb = new StringBuilder();
        Read();
        Calc();
        Console.Write(sb.ToString());
    }
    void Calc(){
        long count = 1;
        if(H%2 == 1){
            for(int i=0;i*2+1<W;i++){
                if(S[H/2,i] != S[H/2,W-1-i]){
                    count *= 2;
                    break;
                }
            }
        }
        if(W%2 == 1){
            for(int i=0;i*2+1<H;i++){
                if(S[i,W/2] != S[H-1-i,W/2]){
                    count *= 2;
                    break;
                }
            }
        }
        bool[,] b = new bool[H/2,W/2];
        for(int i=0;i<H/2;i++){
            for(int j=0;j<W/2;j++){
                if(S[i,j] == S[H-1-i,j] && S[H-1-i,j] == S[H-1-i,W-1-j] && S[H-1-i,W-1-j] == S[i,W-1-j]){
                    b[i,j] = false;
                }
                else if((S[i,j] == S[H-1-i,j] && S[H-1-i,j] == S[H-1-i,W-1-j]) || (S[H-1-i,j] == S[H-1-i,W-1-j] && S[H-1-i,W-1-j] == S[i,W-1-j]) || (S[H-1-i,W-1-j] == S[i,W-1-j] && S[i,W-1-j] == S[i,j]) || (S[i,W-1-j] == S[i,j] && S[i,j] == S[H-1-i,j])){
                    b[i,j] = false;
                    count = count * 4 % Define.mod;
                }
                else if((S[i,j] == S[H-1-i,W-1-j] && S[H-1-i,j] == S[i,W-1-j]) || (S[i,j] == S[H-1-i,j] && S[H-1-i,W-1-j] == S[i,W-1-j]) || (S[i,j] == S[i,W-1-j] && S[H-1-i,j] == S[H-1-i,W-1-j])){
                    b[i,j] = false;
                    count = count * 6 % Define.mod;
                }
                else if(S[i,j] == S[H-1-i,j] || S[i,j] == S[i,W-1-j] || S[i,j] == S[H-1-i,W-1-j] || S[H-1-i,j] == S[H-1-i,W-1-j] || S[H-1-i,j] == S[i,W-1-j] || S[i,W-1-j] == S[H-1-i,W-1-j]){
                    b[i,j] = false;
                    count = count * 12 % Define.mod; 
                }
                else{
                    b[i,j] = true;
                    count = count * 12 % Define.mod;
                }
            }
        }
        UnionFind U = new UnionFind(H/2+W/2);
        for(int i=0;i<H/2;i++){
            for(int j=0;j<W/2;j++){
                if(b[i,j]){
                    U.Union(i,H/2+j);
                }
            }
        }
        int exp = 0;
        for(int i=0;i<H/2+W/2;i++){
            if(U.Get(i) == i){
                exp += U.Num(i)-1;
            }
        }
        for(int i=0;i<exp;i++){
            count = count * 2 % Define.mod;
        }
        sb.Append(count+"\n");
    }
    void Read(){
        string[] str = Console.ReadLine().Split(' ');
        H = int.Parse(str[0]);
        W = int.Parse(str[1]);
        S = new char[H,W];
        for(int i=0;i<H;i++){
            string s = Console.ReadLine();
            for(int j=0;j<W;j++){
                S[i,j] = s[j];
            }
        }
    }    
}
class UnionFind{
    int[] par;
    int[] num;
    public UnionFind(int n){
        par = new int[n];
        num = new int[n];
        for(int i=0;i<n;i++){
            par[i] = i;
            num[i] = 1;
        }
    }
    public int Num(int x){
        return num[Get(x)];
    }
    public void Union(int x,int y){
        int i = Get(x);
        int j = Get(y);
        if(i != j){
            num[i] += num[j];
            par[j] = i;  
        } 
    }
    public bool Same(int x,int y){
        return Get(x) == Get(y);
    }
    public int Get(int x){
        if(x != par[x]){
            par[x] = Get(par[x]);
        }
        return par[x];
    }
}
public static class Define{
    public const long mod = 1000000007;
}

Measured memory_bytes: 3216