#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <assert.h>
#include <vector>
#include <map>
#include <set>

using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
static const double EPS = 1e-9;
static const double PI = acos(-1.0);

#define REP(i, n) for (int i = 0; i < (int)(n); i++)
#define FOR(i, s, n) for (int i = (s); i < (int)(n); i++)
#define FOREQ(i, s, n) for (int i = (s); i <= (int)(n); i++)
#define FORIT(it, c) for (__typeof((c).begin())it = (c).begin(); it != (c).end(); it++)
#define MEMSET(v, h) memset((v), h, sizeof(v))

struct UnionFind {
  int parent[610 * 610];
  UnionFind() { MEMSET(parent, -1); }
  int UnionSet(int x, int y) {
    x = root(x); y = root(y);
    if (x == y) { return 0; }
    if (parent[x] > parent[y]) { swap(x, y); }
    parent[x] += parent[y];
    parent[y] = x;
    return 1;
  }
  int FindSet(int x, int y) {
    return root(x) == root(y);
  }
  int root(int x) { return parent[x] < 0 ? x : parent[x] = root(parent[x]); }
};

typedef vector<int> Array;
typedef vector<Array> Matrix;

template <class T>
void PrintMatrix(const vector<vector<T> > &matrix) {
  REP(y, matrix.size()) {
    REP(x, matrix[y].size()) {
      cout << matrix[y][x] << " ";
    }
    puts("");
  }
}

template <class T>
vector<vector<T> > Transpose(const vector<vector<T> > &matrix) {
  int h = matrix.size();
  int w = matrix[0].size();
  vector<vector<T> > ret(w, vector<T>(h));
  REP(y, h) {
    REP(x, w) {
      ret[w - x - 1][h - y - 1] = matrix[y][x];
    }
  }
  return ret;
}

//=====================

UnionFind ufind;
pair<Matrix, Matrix> calc(const vector<vector<char> > &field) {
  int h = field.size();
  int w = field[0].size();
  ufind = UnionFind();
  pair<Matrix, Matrix> ret(Matrix(h, Array(w, 0)), Matrix(h, Array(w, 0)));
  map<double, vector<pair<int, int> > > que;
  REP(y, h - 1) {
    REP(x, w - 1) {
      int dy = h - 2 - y;
      int dx = x;
      if (dy == 0 && dx == 0) { continue; }
      int g = __gcd(dy, dx);
      dy /= g; dx /= g;
      double angle = dy / (double)dx;
      if (dx == 0) { angle = 1e+100; }
      que[angle].push_back(make_pair(x, y));
    }
  }
  int lans = 0;
  FORIT (it1, que) {
    //PrintMatrix(ret);
    //cout << endl;
    //cout << lans << endl;
    assert(lans >= 0);
    const vector<pair<int, int> > &poss = it1->second;
    FORIT(it2, poss) {
      ret.first[it2->second][it2->first] = lans;
    }
    FORIT(it2, poss) {
      int x = it2->first;
      int y = it2->second;
      if (field[y][x] == '.') { continue; }
      lans++;
      if (field[y + 1][x] == '#' && ufind.UnionSet(y * w + x, (y + 1) * w + x)) { lans--; }
      if (field[y][x + 1] == '#' && ufind.UnionSet(y * w + x, y * w + (x + 1))) { lans--; }
      if (field[y][x + 1] == '#' && field[y + 1][x] == '#' && ufind.UnionSet(y * w + x + 1, (y + 1) * w + x)) { lans--; }
      if (field[y][x] == '#' && field[y + 1][x + 1] == '#' && ufind.UnionSet(y * w + x, (y + 1) * w + x + 1)) { lans--; }
    }
    FORIT(it2, poss) {
      ret.second[it2->second][it2->first] = lans;
    }
  }
  return ret;
}

char str[1010];
int main() {
  int h, w;
  while (scanf("%d %d", &h, &w) > 0) {
    vector<vector<char> > field(h + 2, vector<char>(w + 2, '.'));
    REP(y, h) {
      int v = scanf("%s", str);
      assert(v == 1);
      REP(x, w) { field[y + 1][x + 1] = str[x]; }
    }
    pair<Matrix, Matrix> lans = calc(field);
    //PrintMatrix(lans.first);
    //PrintMatrix(lans.second);
    field = Transpose(field);
    pair<Matrix, Matrix> rans = calc(field);
    //PrintMatrix(rans.first);
    //PrintMatrix(rans.second);
    rans.first = Transpose(rans.first);
    rans.second = Transpose(rans.second);
    //PrintMatrix(rans);
    int ans = 0;
    REP(y, h + 1) {
      REP(x, w + 1) {
        ans = max(ans, lans.first[y][x] + rans.second[y + 1][x + 1]);
        ans = max(ans, lans.second[y][x] + rans.first[y + 1][x + 1]);
      }
    }
    printf("%d\n", ans);
  }
}

Measured memory_bytes: 22000