#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct fdp
{
    long long bl ;
    long long br ;
    long long tl ;
    long long tr ;
};
int n,m;
fdp f[1005][1005]; int a[1005][1005] ;
long long maxi;
void dptl ()
{
    for (int i=1;i <= n; i++)
        for (int j=1 ;j<= m ; j++)
    {
        f[i][j].tl = max ( f[i-1][j].tl,f[i][j-1].tl) +a[i][j];

    }
}
void dptr ()
{
    for (int i=1;i<=n; i++)
        for (int j=m ;j>= 1 ;j--)
    {
        f[i][j].tr = max (f[i-1][j].tr,f[i][j+1].tr) +a[i][j] ;
    }
}
void dpbl ()
{
    for (int i=n;i >=1; i--)
        for (int j=1 ;j<= m ; j++)
    {
        f[i][j].bl = max ( f[i+1][j].bl, f[i][j-1].bl) +a[i][j] ;
    }
}
void dpbr ()
{
    for (int i=n;i >= 1; i--)
        for (int j=m ;j>= 1 ; j--)
    {
        f[i][j].br = max ( f[i+1][j].br , f[i][j+1].br) +a[i][j] ;
    }
}
bool ck (int i , int j)
{
    if (i < 1) return false ;
    if (i > n ) return false ;
    if (j < 1) return false ;
    if (j > n ) return false ;
    return true ;
}
int main()
{
    maxi = -1 ;
  //  freopen ("429B.inp","r",stdin);
  //  freopen ("429B.out","w",stdout);
    cin >>n>>m ;
    for (int i=1;i<= n ; i++)
        for (int j=1 ; j <= m; j++)
    {
        cin>>a[i][j];
    }
    dpbl() ;
    dpbr() ;
    dptl () ;
    dptr () ;
    for (int i=2; i < n ; i++)
        for (int j = 2 ; j < m ; j++)
    {
                        maxi = max (maxi, f[i-1][j].tl+f[i+1][j].br+f[i][j-1].bl+f[i][j+1].tr);
                        maxi = max (maxi, f[i-1][j].tr+f[i+1][j].bl+f[i][j-1].tl+f[i][j+1].br);
    }
    /*
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].bl<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].br<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].tl<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].tr<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
*/
        cout << maxi <<endl;
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct fdp
{
    long long bl ;
    long long br ;
    long long tl ;
    long long tr ;
};
int n,m;
fdp f[1005][1005]; int a[1005][1005] ;
long long maxi =-1;
void dptl ()
{
    for (int i=1;i <= n; i++)
        for (int j=1 ;j<= m ; j++)
    {
        f[i][j].tl = max ( f[i-1][j].tl,f[i][j-1].tl) +a[i][j];

    }
}
void dptr ()
{
    for (int i=1;i<=n; i++)
        for (int j=m ;j>= 1 ;j--)
    {
        f[i][j].tr = max (f[i-1][j].tr,f[i][j+1].tr) +a[i][j] ;
    }
}
void dpbl ()
{
    for (int i=n;i >=1; i--)
        for (int j=1 ;j<= m ; j++)
    {
        f[i][j].bl = max ( f[i+1][j].bl, f[i][j-1].bl) +a[i][j] ;
    }
}
void dpbr ()
{
    for (int i=n;i >= 1; i--)
        for (int j=m ;j>= 1 ; j--)
    {
        f[i][j].br = max ( f[i+1][j].br , f[i][j+1].br) +a[i][j] ;
    }
}
bool ck (int i , int j)
{
    if (i < 1) return false ;
    if (i > n ) return false ;
    if (j < 1) return false ;
    if (j > n ) return false ;
    return true ;
}
int main()
{
    maxi = -1 ;
 //   freopen ("429B.inp","r",stdin);
 //   freopen ("429B.out","w",stdout);
    cin >>n>>m ;
    for (int i=1;i<= n ; i++)
        for (int j=1 ; j <= m; j++)
    {
        cin>>a[i][j];
    }
    dpbl() ;
    dpbr() ;
    dptl () ;
    dptr () ;
    for (int i=1; i <= n ; i++)
        for (int j = 1 ; j <= m ; j++)
    {
                        maxi = max (maxi, f[i-1][j].tl+f[i+1][j].br+f[i][j-1].bl+f[i][j+1].tr);
                        maxi = max (maxi, f[i-1][j].tr+f[i+1][j].bl+f[i][j-1].tl+f[i][j+1].br);
    }
    /*
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].bl<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].br<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].tl<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].tr<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
*/
        cout << maxi <<endl;
    return 0;
}


#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct fdp
{
    int bl ;
    int br ;
    int tl ;
    int tr ;
};
int n,m,maxi;
fdp f[1000][1000]; int a[1000][1000] ;
void dptl ()
{
    for (int i=1;i <= n; i++)
        for (int j=1 ;j<= m ; j++)
    {
        f[i][j].tl = max ( f[i-1][j].tl,f[i][j-1].tl) +a[i][j];

    }
}
void dptr ()
{
    for (int i=1;i<=n; i++)
        for (int j=m ;j>= 1 ;j--)
    {
        f[i][j].tr = max (f[i-1][j].tr,f[i][j+1].tr) +a[i][j] ;
    }
}
void dpbl ()
{
    for (int i=n;i >=1; i--)
        for (int j=1 ;j<= m ; j++)
    {
        f[i][j].bl = max ( f[i+1][j].bl, f[i][j-1].bl) +a[i][j] ;
    }
}
void dpbr ()
{
    for (int i=n;i >= 1; i--)
        for (int j=m ;j>= 1 ; j--)
    {
        f[i][j].br = max ( f[i+1][j].br , f[i][j+1].br) +a[i][j] ;
    }
}
bool ck (int i , int j)
{
    if (i < 1) return false ;
    if (i > n ) return false ;
    if (j < 1) return false ;
    if (j > n ) return false ;
    return true ;
}
int main()
{
    maxi = -1 ;
 //   freopen ("429B.inp","r",stdin);
 //   freopen ("429B.out","w",stdout);
    cin >>n>>m ;
    for (int i=1;i<= n ; i++)
        for (int j=1 ; j <= m; j++)
    {
        cin>>a[i][j];
    }
    dpbl() ;
    dpbr() ;
    dptl () ;
    dptr () ;
    for (int i=1; i <= n ; i++)
        for (int j = 1 ; j <= m ; j++)
    {
                        maxi = max (maxi, f[i-1][j].tl+f[i+1][j].br+f[i][j-1].bl+f[i][j+1].tr);
                        maxi = max (maxi, f[i-1][j].tr+f[i+1][j].bl+f[i][j-1].tl+f[i][j+1].br);
    }
    /*
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].bl<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].br<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].tl<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
for (int i=1; i <= n ; i++)
{
        for (int j = 1 ; j <= m ; j++)
    {
        cout << f[i][j].tr<< " ";
    }
    cout <<endl ;
}
cout <<"*******************************"<<endl ;
*/
        cout << maxi <<endl;
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long lli;
#define mod 1000000007
#define mod2 998244353
#define fori(n) for (int i = 0; i < n; i++)
#define forj(n) for (int j = 0; j < n; j++)
#define forr(c, n) for (int i = c; i < n; i++)
#define forli(n) for (lli i = 0; i < n; i++)
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define endl "\n"
#define sortvec(a) sort(a.begin(), a.end())

//FUNCTONS
lli llipower(lli x, lli y)
{
    lli res = 1;
    while (y > 0)
    {
        if (y & 1)
            res = (res * x);
        y = y >> 1;
        x = (x * x);
    }
    return res;
}
lli llipowerp(lli x, lli y, lli p)
{
    lli res = 1;
    x = x % p;
    while (y > 0)
    {
        if (y & 1)
            res = (res * x) % p;
        y = y >> 1;
        x = (x * x) % p;
    }
    return res;
}
lli gcd(lli a, lli b)
{
    if (!a)
        return b;
    return gcd(b % a, a);
}
lli binarySearch(vector<int> arr, int l, int r, int x)
{
    if (r >= l)
    {
        lli mid = l + (r - l) / 2;
        if (arr[mid] == x)
            return mid;
        if (arr[mid] > x)
            return binarySearch(arr, l, mid - 1, x);
        return binarySearch(arr, mid + 1, r, x);
    }
    return -1;
}
template <typename T>
void printvec(vector<T> inp)
{
    for (int i = 0; i < inp.size(); i++)
    {
        cout << inp[i] << " ";
    }
    cout << endl;
}
template <typename T>
T ceildiv(T x, T y) { return 1 + ((x - 1) / y); }
lli modInverse(lli a, lli m)
{
    lli g = gcd(a, m);
    if (g != 1)
        return -1;
    else
        return llipowerp(a, m - 2, m);
}

struct node{
    lli tl,tr,bl,br;
    node(){
        tl=-1LL;
        tr=-1LL;
        bl=-1LL;
        br=-1LL;

    }
};
int a[1001][1001];
node dp[1001][1001];
int n,m;
lli filltl(int i,int j){
    if(i<=0 || j<=0) return 0LL;
    if(dp[i][j].tl==-1)
        dp[i][j].tl=max(filltl(i-1,j),filltl(i,j-1))+a[i][j];
    return dp[i][j].tl;
}

lli filltr(int i, int j)
{
    if (i <= 0 || j >m)
        return 0LL;
    if (dp[i][j].tr == -1)
        dp[i][j].tr = max(filltr(i - 1, j), filltr(i, j + 1)) + a[i][j];
    return dp[i][j].tr;
}
lli fillbl(int i, int j)
{
    if (i >n || j <= 0)
        return 0LL;
    if (dp[i][j].bl == -1)
        dp[i][j].bl = max(fillbl(i + 1, j), fillbl(i, j - 1)) + a[i][j];
    return dp[i][j].bl;
}
lli fillbr(int i, int j)
{
    if (i > n || j >m)
        return 0LL;
    if (dp[i][j].br == -1)
        dp[i][j].br = max(fillbr(i + 1, j), fillbr(i, j + 1)) + a[i][j];
    return dp[i][j].br;
}
lli csum(node a){
    return a.tl+a.tr+a.bl;+a.br;
}
int main()
{
    cin>>n>>m;
    fori(n){
        forj(m){
            cin>>a[i+1][j+1];
        }
    }
    lli ans=0;

    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(dp[i][j].tl==-1) filltl(i,j);
            if (dp[i][j].tr == -1)
                filltr(i, j);
            if (dp[i][j].bl == -1)
                fillbl(i, j);
            if (dp[i][j].br == -1)
                fillbr(i, j);

            ans = max(ans, max(filltl(i, j - 1) + filltr(i - 1, j) + fillbr(i, j + 1) + fillbl(i + 1, j), fillbl(i, j - 1) + filltl(i - 1, j) + filltr(i, j + 1) + fillbr(i + 1, j)));

        }
    }
    cout<<ans<<endl;
    // for (int i = 1; i <= n; i++)
    // {
    //     for (int j = 1; j <= m; j++)
    //     {
    //         cout << a[i][j] << " ";
    //     }
    //     cout << endl;
    // }
    // for(int i=1;i<=n;i++)
    // {
    //     for(int j=1;j<=m;j++)
    //     {
    //         cout << (dp[i][j].tl + dp[i][j].tr + dp[i][j].bl + dp[i][j].br -4*a[i][j])<< " ";
    //     }
    //     cout<<endl;
    // }
    // cout<<dp[1][1].tl<<endl;
    // cout << dp[1][1].tr << endl;
    // cout << dp[1][1].bl << endl;
    // cout << dp[1][1].br << endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long lli;
#define mod 1000000007
#define mod2 998244353
#define fori(n) for (int i = 0; i < n; i++)
#define forj(n) for (int j = 0; j < n; j++)
#define forr(c, n) for (int i = c; i < n; i++)
#define forli(n) for (lli i = 0; i < n; i++)
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define endl "\n"
#define sortvec(a) sort(a.begin(), a.end())

//FUNCTONS
lli llipower(lli x, lli y)
{
    lli res = 1;
    while (y > 0)
    {
        if (y & 1)
            res = (res * x);
        y = y >> 1;
        x = (x * x);
    }
    return res;
}
lli llipowerp(lli x, lli y, lli p)
{
    lli res = 1;
    x = x % p;
    while (y > 0)
    {
        if (y & 1)
            res = (res * x) % p;
        y = y >> 1;
        x = (x * x) % p;
    }
    return res;
}
lli gcd(lli a, lli b)
{
    if (!a)
        return b;
    return gcd(b % a, a);
}
lli binarySearch(vector<int> arr, int l, int r, int x)
{
    if (r >= l)
    {
        lli mid = l + (r - l) / 2;
        if (arr[mid] == x)
            return mid;
        if (arr[mid] > x)
            return binarySearch(arr, l, mid - 1, x);
        return binarySearch(arr, mid + 1, r, x);
    }
    return -1;
}
template <typename T>
void printvec(vector<T> inp)
{
    for (int i = 0; i < inp.size(); i++)
    {
        cout << inp[i] << " ";
    }
    cout << endl;
}
template <typename T>
T ceildiv(T x, T y) { return 1 + ((x - 1) / y); }
lli modInverse(lli a, lli m)
{
    lli g = gcd(a, m);
    if (g != 1)
        return -1;
    else
        return llipowerp(a, m - 2, m);
}

struct node{
    lli tl,tr,bl,br;
    node(){
        tl=-1LL;
        tr=-1LL;
        bl=-1LL;
        br=-1LL;

    }
};
int a[1001][1001];
node dp[1001][1001];
int n,m;
lli filltl(int i,int j){
    if(i<=0 || j<=0) return 0LL;
    if(dp[i][j].tl==-1)
        dp[i][j].tl=max(filltl(i-1,j),filltl(i,j-1))+a[i][j];
    return dp[i][j].tl;
}

lli filltr(int i, int j)
{
    if (i <= 0 || j >m)
        return 0LL;
    if (dp[i][j].tr == -1)
        dp[i][j].tr = max(filltr(i - 1, j), filltr(i, j + 1)) + a[i][j];
    return dp[i][j].tr;
}
lli fillbl(int i, int j)
{
    if (i >n || j <= 0)
        return 0LL;
    if (dp[i][j].bl == -1)
        dp[i][j].bl = max(fillbl(i + 1, j), fillbl(i, j - 1)) + a[i][j];
    return dp[i][j].bl;
}
lli fillbr(int i, int j)
{
    if (i > n || j >m)
        return 0LL;
    if (dp[i][j].br == -1)
        dp[i][j].br = max(fillbr(i + 1, j), fillbr(i, j + 1)) + a[i][j];
    return dp[i][j].br;
}
lli csum(node a){
    return a.tl+a.tr+a.bl;+a.br;
}
int main()
{
    cin>>n>>m;
    fori(n){
        forj(m){
            cin>>a[i+1][j+1];
        }
    }
    lli ans=0;
    lli p,q;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            p = (i > 1 && i < n && j > 1 && j < n) ? (filltl(i, j - 1) + filltr(i - 1, j) + fillbr(i, j + 1) + fillbl(i + 1, j)) : 0;
            q = (i > 1 && i < n && j > 1 && j < n) ? (fillbl(i, j - 1) + filltl(i - 1, j) + filltr(i, j + 1) + fillbr(i + 1, j)) : 0;
            ans=max(ans,max(p,q));

            //cout<<ans<<" "<<p<<" "<<q<<" "<<i<<" "<<j<<endl;
        }
    }
    cout<<ans<<endl;
    // for (int i = 1; i <= n; i++)
    // {
    //     for (int j = 1; j <= m; j++)
    //     {
    //         cout << a[i][j] << " ";
    //     }
    //     cout << endl;
    // }
    // for(int i=1;i<=n;i++)
    // {
    //     for(int j=1;j<=m;j++)
    //     {
    //         cout << (dp[i][j].tl + dp[i][j].tr + dp[i][j].bl + dp[i][j].br -4*a[i][j])<< " ";
    //     }
    //     cout<<endl;
    // }
    // cout<<dp[1][1].tl<<endl;
    // cout << dp[1][1].tr << endl;
    // cout << dp[1][1].bl << endl;
    // cout << dp[1][1].br << endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long lli;
#define mod 1000000007
#define mod2 998244353
#define fori(n) for (int i = 0; i < n; i++)
#define forj(n) for (int j = 0; j < n; j++)
#define forr(c, n) for (int i = c; i < n; i++)
#define forli(n) for (lli i = 0; i < n; i++)
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define endl "\n"
#define sortvec(a) sort(a.begin(), a.end())

//FUNCTONS
lli llipower(lli x, lli y)
{
    lli res = 1;
    while (y > 0)
    {
        if (y & 1)
            res = (res * x);
        y = y >> 1;
        x = (x * x);
    }
    return res;
}
lli llipowerp(lli x, lli y, lli p)
{
    lli res = 1;
    x = x % p;
    while (y > 0)
    {
        if (y & 1)
            res = (res * x) % p;
        y = y >> 1;
        x = (x * x) % p;
    }
    return res;
}
lli gcd(lli a, lli b)
{
    if (!a)
        return b;
    return gcd(b % a, a);
}
lli binarySearch(vector<int> arr, int l, int r, int x)
{
    if (r >= l)
    {
        lli mid = l + (r - l) / 2;
        if (arr[mid] == x)
            return mid;
        if (arr[mid] > x)
            return binarySearch(arr, l, mid - 1, x);
        return binarySearch(arr, mid + 1, r, x);
    }
    return -1;
}
template <typename T>
void printvec(vector<T> inp)
{
    for (int i = 0; i < inp.size(); i++)
    {
        cout << inp[i] << " ";
    }
    cout << endl;
}
template <typename T>
T ceildiv(T x, T y) { return 1 + ((x - 1) / y); }
lli modInverse(lli a, lli m)
{
    lli g = gcd(a, m);
    if (g != 1)
        return -1;
    else
        return llipowerp(a, m - 2, m);
}

struct node{
    lli tl,tr,bl,br;
    node(){
        tl=-1LL;
        tr=-1LL;
        bl=-1LL;
        br=-1LL;

    }
};
int a[1001][1001];
node dp[1001][1001];
int n,m;
lli filltl(int i,int j){
    if(i<=0 || j<=0) return 0LL;
    if(dp[i][j].tl==-1)
        dp[i][j].tl=max(filltl(i-1,j),filltl(i,j-1))+a[i][j];
    return dp[i][j].tl;
}

lli filltr(int i, int j)
{
    if (i <= 0 || j >m)
        return 0LL;
    if (dp[i][j].tr == -1)
        dp[i][j].tr = max(filltr(i - 1, j), filltr(i, j + 1)) + a[i][j];
    return dp[i][j].tr;
}
lli fillbl(int i, int j)
{
    if (i >n || j <= 0)
        return 0LL;
    if (dp[i][j].bl == -1)
        dp[i][j].bl = max(fillbl(i + 1, j), fillbl(i, j - 1)) + a[i][j];
    return dp[i][j].bl;
}
lli fillbr(int i, int j)
{
    if (i > n || j >m)
        return 0LL;
    if (dp[i][j].br == -1)
        dp[i][j].br = max(fillbr(i + 1, j), fillbr(i, j + 1)) + a[i][j];
    return dp[i][j].br;
}
lli csum(node a){
    return a.tl+a.tr+a.bl;+a.br;
}
int main()
{
    cin>>n>>m;
    fori(n){
        forj(m){
            cin>>a[i+1][j+1];
        }
    }
    lli ans=0;
    lli p,q;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            p = (i > 1 && i < n && j > 1 && j < m) ? (filltl(i, j - 1) + filltr(i - 1, j) + fillbr(i, j + 1) + fillbl(i + 1, j)) : 0;
            q = (i > 1 && i < n && j > 1 && j < m) ? (fillbl(i, j - 1) + filltl(i - 1, j) + filltr(i, j + 1) + fillbr(i + 1, j)) : 0;
            ans=max(ans,max(p,q));

            //cout<<ans<<" "<<p<<" "<<q<<" "<<i<<" "<<j<<endl;
        }
    }
    cout<<ans<<endl;
    // for (int i = 1; i <= n; i++)
    // {
    //     for (int j = 1; j <= m; j++)
    //     {
    //         cout << a[i][j] << " ";
    //     }
    //     cout << endl;
    // }
    // for(int i=1;i<=n;i++)
    // {
    //     for(int j=1;j<=m;j++)
    //     {
    //         cout << (dp[i][j].tl + dp[i][j].tr + dp[i][j].bl + dp[i][j].br -4*a[i][j])<< " ";
    //     }
    //     cout<<endl;
    // }
    // cout<<dp[1][1].tl<<endl;
    // cout << dp[1][1].tr << endl;
    // cout << dp[1][1].bl << endl;
    // cout << dp[1][1].br << endl;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long lli;
#define mod 1000000007
#define mod2 998244353
#define fori(n) for (int i = 0; i < n; i++)
#define forj(n) for (int j = 0; j < n; j++)
#define forr(c, n) for (int i = c; i < n; i++)
#define forli(n) for (lli i = 0; i < n; i++)
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define fast ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define endl "\n"
#define sortvec(a) sort(a.begin(), a.end())

//FUNCTONS
lli llipower(lli x, lli y)
{
    lli res = 1;
    while (y > 0)
    {
        if (y & 1)
            res = (res * x);
        y = y >> 1;
        x = (x * x);
    }
    return res;
}
lli llipowerp(lli x, lli y, lli p)
{
    lli res = 1;
    x = x % p;
    while (y > 0)
    {
        if (y & 1)
            res = (res * x) % p;
        y = y >> 1;
        x = (x * x) % p;
    }
    return res;
}
lli gcd(lli a, lli b)
{
    if (!a)
        return b;
    return gcd(b % a, a);
}
lli binarySearch(vector<int> arr, int l, int r, int x)
{
    if (r >= l)
    {
        lli mid = l + (r - l) / 2;
        if (arr[mid] == x)
            return mid;
        if (arr[mid] > x)
            return binarySearch(arr, l, mid - 1, x);
        return binarySearch(arr, mid + 1, r, x);
    }
    return -1;
}
template <typename T>
void printvec(vector<T> inp)
{
    for (int i = 0; i < inp.size(); i++)
    {
        cout << inp[i] << " ";
    }
    cout << endl;
}
template <typename T>
T ceildiv(T x, T y) { return 1 + ((x - 1) / y); }
lli modInverse(lli a, lli m)
{
    lli g = gcd(a, m);
    if (g != 1)
        return -1;
    else
        return llipowerp(a, m - 2, m);
}

struct node{
    lli tl,tr,bl,br;
    node(){
        tl=-1LL;
        tr=-1LL;
        bl=-1LL;
        br=-1LL;

    }
};
int a[1001][1001];
node dp[1001][1001];
int n,m;
lli filltl(int i,int j){
    if(i<=0 || j<=0) return 0LL;
    if(dp[i][j].tl==-1)
        dp[i][j].tl=max(filltl(i-1,j),filltl(i,j-1))+a[i][j];
    return dp[i][j].tl;
}

lli filltr(int i, int j)
{
    if (i <= 0 || j >m)
        return 0LL;
    if (dp[i][j].tr == -1)
        dp[i][j].tr = max(filltr(i - 1, j), filltr(i, j + 1)) + a[i][j];
    return dp[i][j].tr;
}
lli fillbl(int i, int j)
{
    if (i >n || j <= 0)
        return 0LL;
    if (dp[i][j].bl == -1)
        dp[i][j].bl = max(fillbl(i + 1, j), fillbl(i, j - 1)) + a[i][j];
    return dp[i][j].bl;
}
lli fillbr(int i, int j)
{
    if (i > n || j >m)
        return 0LL;
    if (dp[i][j].br == -1)
        dp[i][j].br = max(fillbr(i + 1, j), fillbr(i, j + 1)) + a[i][j];
    return dp[i][j].br;
}
int main()
{
    cin>>n>>m;
    fori(n){
        forj(m){
            cin>>a[i+1][j+1];
        }
    }
    lli ans=0;

    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(dp[i][j].tl==-1) filltl(i,j);
            if (dp[i][j].tr == -1)
                filltr(i, j);
            if (dp[i][j].bl == -1)
                fillbl(i, j);
            if (dp[i][j].br == -1)
                fillbr(i, j);

            ans=max(ans,(dp[i][j].tl+dp[i][j].tr+dp[i][j].bl+dp[i][j].br)-4*a[i][j]);
        }
    }
    cout<<ans<<endl;
    // for (int i = 1; i <= n; i++)
    // {
    //     for (int j = 1; j <= m; j++)
    //     {
    //         cout << a[i][j] << " ";
    //     }
    //     cout << endl;
    // }
    // for(int i=1;i<=n;i++)
    // {
    //     for(int j=1;j<=m;j++)
    //     {
    //         cout << dp[i][j].tl + dp[i][j].tr + dp[i][j].bl + dp[i][j].br << " ";
    //     }
    //     cout<<endl;
    // }
    // cout<<dp[1][1].tl<<endl;
    // cout << dp[1][1].tr << endl;
    // cout << dp[1][1].bl << endl;
    // cout << dp[1][1].br << endl;
}


#include <bits/stdc++.h>
using namespace std;

#define FOR(i, x, n) for(ll i = x; i < n; i++)
#define pb push_back
#define ll long long
#define hii cout << "hii" << endl
#define pii pair<int, int>
#define pll pair<ll, ll>
#define int ll
#define mpp make_pair
#define endl '\n'
#define ff first
#define ss second
#define all(s) s.begin(), s.end()
#define fuck_you_scanf ios_base:: sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define si size()

const int N = 1e6 + 5;
const int MAX = 1e3 + 15;

int n, m;
int arr[MAX][MAX];
int DP1[MAX][MAX];
int DP2[MAX][MAX];
int DP3[MAX][MAX];
int DP4[MAX][MAX];

int f1(int i, int j) // (left)upar se niche ke liye
{
    if(i > n or j > m) return 0;

    int ans1 = f1(i + 1, j);
    int ans2 = f1(i, j + 1);
    return DP1[i][j] = arr[i][j] + max(ans1, ans2);
}

int f2(int i, int j) // (left) niche se upar ke liye
{
    if(i <= 0 or j > m) return 0;

    int ans1 = f2(i - 1, j);
    int ans2 = f2(i, j + 1);
    return DP2[i][j] = arr[i][j] + max(ans1, ans2);
}

int f3(int i, int j) // (right) nichhe se upar jane ke liye
{
    if(i <= 0 or j <= 0) return 0;

    int ans1 = f3(i - 1, j);
    int ans2 = f3(i, j - 1);
    return DP3[i][j] = arr[i][j] + max(ans1, ans2);
}

int f4(int i, int j) // right upar se nichhe jane ke liye
{
    if(j <= 0 or i > n) return 0;

    int ans1 = f4(i + 1, j);
    int ans2 = f4(i, j - 1);
    return DP4[i][j] = arr[i][j] + max(ans1, ans2);
}

int32_t main()
{
    fuck_you_scanf;

    cin >> n >> m;

    FOR(i, 1, n + 1)
    {
        FOR(j, 1, m + 1)
        {
            cin >> arr[i][j];
        }
    }

    f1(1, 1);
    f2(n, 1);
    f3(n, m);
    f4(1, m);

    int ret = 0;

    FOR(i, 1, n + 1)
    {
        FOR(j, 1, m + 1)
        {
            int temp = DP1[i][j] + DP2[i][j] + DP3[i][j] + DP4[i][j];
            temp -= 4 * arr[i][j];
            ret = max(ret, temp);
        }
    }

    // cerr << DP1[2][2] << " " << DP2[2][2] << " " << DP3[2][2] << " " << DP4[2][2] << endl;

    cout << ret << endl;

}


#include <bits/stdc++.h>
using namespace std;

#define FOR(i, x, n) for(ll i = x; i < n; i++)
#define pb push_back
#define ll long long
#define hii cout << "hii" << endl
#define pii pair<int, int>
#define pll pair<ll, ll>
#define int ll
#define mpp make_pair
#define endl '\n'
#define ff first
#define ss second
#define all(s) s.begin(), s.end()
#define fuck_you_scanf ios_base:: sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define si size()

const int N = 1e6 + 5;
const int MAX = 1e3 + 15;

int n, m;
int arr[MAX][MAX];
int DP1[MAX][MAX];
int DP2[MAX][MAX];
int DP3[MAX][MAX];
int DP4[MAX][MAX];

int f1(int i, int j)
{
    if(i > n or j > m) return 0;

    int ans1 = f1(i + 1, j);
    int ans2 = f1(i, j + 1);
    return DP1[i][j] = arr[i][j] + max(ans1, ans2);
}

int f2(int i, int j)
{
    if(i <= 0 or j > m) return 0;

    int ans1 = f2(i - 1, j);
    int ans2 = f2(i, j + 1);
    return DP2[i][j] = arr[i][j] + max(ans1, ans2);
}

int f3(int i, int j)
{
    if(i <= 0 or j <= 0) return 0;

    int ans1 = f3(i - 1, j);
    int ans2 = f3(i, j - 1);
    return DP3[i][j] = arr[i][j] + max(ans1, ans2);
}

int f4(int i, int j)
{
    if(j <= 0 or i > n) return 0;

    int ans1 = f4(i + 1, j);
    int ans2 = f4(i, j - 1);
    return DP4[i][j] = arr[i][j] + max(ans1, ans2);
}

int32_t main()
{
    fuck_you_scanf;

    cin >> n >> m;

    FOR(i, 1, n + 1)
    {
        FOR(j, 1, m + 1)
        {
            cin >> arr[i][j];
        }
    }

    f1(1, 1);
    f2(n, 1);
    f3(n, m);
    f4(1, m);

    int ret = 0;

    FOR(i, 2, n)
    {
            FOR(j, 2, m)
            {
                    int ans1 = DP1[i + 1][j] + DP2[i][j + 1] + DP3[i - 1][j] + DP4[i][j - 1];
                    int ans2 = DP1[i][j + 1] + DP2[i - 1][j] + DP3[i][j - 1] + DP4[i + 1][j];
                    ret = max({ans1, ans2, ret});
            }
    }

    cout << ret << endl;

}


#include <bits/stdc++.h>
using namespace std;

#define FOR(i, x, n) for(ll i = x; i < n; i++)
#define pb push_back
#define ll long long
#define hii cout << "hii" << endl
#define pii pair<int, int>
#define pll pair<ll, ll>
#define int ll
#define mpp make_pair
#define endl '\n'
#define ff first
#define ss second
#define all(s) s.begin(), s.end()
#define fuck_you_scanf ios_base:: sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define si size()

const int N = 1e6 + 5;
const int MAX = 1e3 + 15;

int n, m;
int arr[MAX][MAX];
int DP1[MAX][MAX];
int DP2[MAX][MAX];
int DP3[MAX][MAX];
int DP4[MAX][MAX];

int f1(int i, int j)
{
    if(i > n or j > m) return 0;

    int ans1 = f1(i + 1, j);
    int ans2 = f1(i, j + 1);
    return DP1[i][j] = arr[i][j] + max(ans1, ans2);
}

int f2(int i, int j)
{
    if(i <= 0 or j > m) return 0;

    int ans1 = f2(i - 1, j);
    int ans2 = f2(i, j + 1);
    return DP2[i][j] = arr[i][j] + max(ans1, ans2);
}

int f3(int i, int j)
{
    if(i <= 0 or j <= 0) return 0;

    int ans1 = f3(i - 1, j);
    int ans2 = f3(i, j - 1);
    return DP3[i][j] = arr[i][j] + max(ans1, ans2);
}

int f4(int i, int j)
{
    if(j <= 0 or i > n) return 0;

    int ans1 = f4(i + 1, j);
    int ans2 = f4(i, j - 1);
    return DP4[i][j] = arr[i][j] + max(ans1, ans2);
}

int32_t main()
{
    fuck_you_scanf;

    cin >> n >> m;

    FOR(i, 1, n + 1)
    {
        FOR(j, 1, m + 1)
        {
            cin >> arr[i][j];
        }
    }

    f1(1, 1);
    f2(n, 1);
    f3(n, m);
    f4(1, m);

    int ret = 0;

    FOR(i, 2, n)
    {
            FOR(j, 2, m)
            {
                    int ans1 = DP2[i][j + 1] + DP1[i + 1][j] + DP3[i - 1][j] + DP4[i][j - 1];
                    int ans2 = DP2[i - 1][j] + DP1[i][j + 1] + DP3[i][j - 1] + DP4[i + 1][j];
                    ret = max(ans1, ans2);
            }
    }

    cout << ret << endl;

}


#include <bits/stdc++.h>
using namespace std;

#define FOR(i, x, n) for(ll i = x; i < n; i++)
#define pb push_back
#define ll long long
#define hii cout << "hii" << endl
#define pii pair<int, int>
#define pll pair<ll, ll>
#define int ll
#define mpp make_pair
#define endl '\n'
#define ff first
#define ss second
#define all(s) s.begin(), s.end()
#define fuck_you_scanf ios_base:: sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define si size()

const int N = 1e6 + 5;
const int MAX = 1e3 + 15;

int n, m;
int arr[MAX][MAX];
int DP1[MAX][MAX];
int DP2[MAX][MAX];
int DP3[MAX][MAX];
int DP4[MAX][MAX];

int f1(int i, int j)
{
    if(i > n or j > m) return 0;

    if(DP1[i][j] != -1) return DP1[i][j];

    int ans1 = f1(i + 1, j);
    int ans2 = f1(i, j + 1);
    return DP1[i][j] = arr[i][j] + max(ans1, ans2);
}

int f2(int i, int j)
{
    if(i <= 0 or j > m) return 0;

    if(DP2[i][j] != -1) return DP2[i][j];
    int ans1 = f2(i - 1, j);
    int ans2 = f2(i, j + 1);
    return DP2[i][j] = arr[i][j] + max(ans1, ans2);
}

int f3(int i, int j)
{
    if(i <= 0 or j <= 0) return 0;

    if(DP3[i][j] != -1) return DP3[i][j];
    int ans1 = f3(i - 1, j);
    int ans2 = f3(i, j - 1);
    return DP3[i][j] = arr[i][j] + max(ans1, ans2);
}

int f4(int i, int j)
{
    if(j <= 0 or i > n) return 0;

    if(DP4[i][j] != -1) return DP4[i][j];
    int ans1 = f4(i + 1, j);
    int ans2 = f4(i, j - 1);
    return DP4[i][j] = arr[i][j] + max(ans1, ans2);
}

int32_t main()
{
    fuck_you_scanf;

    cin >> n >> m;

    FOR(i, 1, n + 1)
    {
        FOR(j, 1, m + 1)
        {
            cin >> arr[i][j];
        }
    }

    memset(DP1, -1, sizeof(DP1));
    f1(1, 1);
    memset(DP2, -1, sizeof(DP2));
    f2(n, 1);
    memset(DP3, -1, sizeof(DP3));
    f3(n, m);
    memset(DP4, -1, sizeof(DP4));
    f4(1, m);

    int ret = 0;

    FOR(i, 2, n)
    {
            FOR(j, 2, m)
            {
                    int ans1 = DP1[i + 1][j] + DP2[i][j + 1] + DP3[i - 1][j] + DP4[i][j - 1];
                    int ans2 = DP1[i][j + 1] + DP2[i - 1][j] + DP3[i][j - 1] + DP4[i + 1][j];
                    ret = max({ans1, ans2, ret});
            }
    }

    cout << ret << endl;

}


#include <bits/stdc++.h>
using namespace std;

#define FOR(i, x, n) for(ll i = x; i < n; i++)
#define pb push_back
#define ll long long
#define hii cout << "hii" << endl
#define pii pair<int, int>
#define pll pair<ll, ll>
#define int ll
#define mpp make_pair
#define endl '\n'
#define ff first
#define ss second
#define all(s) s.begin(), s.end()
#define fuck_you_scanf ios_base:: sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define si size()

const int N = 1e6 + 5;
const int MAX = 1e3 + 15;

int n, m;
int arr[MAX][MAX];
int DP1[MAX][MAX];
int DP2[MAX][MAX];
int DP3[MAX][MAX];
int DP4[MAX][MAX];

int f1(int i, int j)
{
    if(i > n or j > m) return 0;

    int ans1 = f1(i + 1, j);
    int ans2 = f1(i, j + 1);
    return DP1[i][j] = arr[i][j] + max(ans1, ans2);
}

int f2(int i, int j)
{
    if(i <= 0 or j > m) return 0;

    int ans1 = f2(i - 1, j);
    int ans2 = f2(i, j + 1);
    return DP2[i][j] = arr[i][j] + max(ans1, ans2);
}

int f3(int i, int j)
{
    if(i <= 0 or j <= 0) return 0;

    int ans1 = f3(i - 1, j);
    int ans2 = f3(i, j - 1);
    return DP3[i][j] = arr[i][j] + max(ans1, ans2);
}

int f4(int i, int j)
{
    if(j <= 0 or i > n) return 0;

    int ans1 = f4(i + 1, j);
    int ans2 = f4(i, j - 1);
    return DP4[i][j] = arr[i][j] + max(ans1, ans2);
}

int32_t main()
{
    fuck_you_scanf;

    cin >> n >> m;

    FOR(i, 1, n + 1)
    {
        FOR(j, 1, m + 1)
        {
            cin >> arr[i][j];
        }
    }

    f1(1, 1);
    f2(n, 1);
    f3(n, m);
    f4(1, m);

    int ret = 0;

    FOR(i, 2, n)
    {
            FOR(j, 2, m)
            {
                    int ans1 = DP2[i - 1][j] + DP1[i][j + 1] + DP3[i][j - 1] + DP4[i + 1][j];
                    int ans2 = DP2[i][j + 1] + DP1[i + 1][j] + DP3[i - 1][j] + DP4[i][j - 1];
                    ret = max(ans1, ans2);
            }
    }

    cout << ret << endl;

}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

ll read() {
    ll   t = 0, f = 1;
    char ch = char(getchar());
    while(ch < '0' || ch > '9') {
        if(ch == '-')
            f = -1;
        ch = char(getchar());
    }
    while('0' <= ch && ch <= '9') {
        t  = t * 10 + ch - '0';
        ch = char(getchar());
    }
    return t * f;
}

yeee main() {
    setup_io();
    //

    ll R = read(), C = read();

    vvll B(R, vll(C));
    FOR(y, 0, R)
        FOR(x, 0, C)
            B[y][x] = read();

    vector<vvll> D(4, vvll(R, vll(C, 0)));

    FOR(y, 0, R)
        FOR(x, 0, C)
            D[0][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[0][y - 1][x],
                                       x == 1 - 1 ? 0 : D[0][y][x - 1]);
    ROF(y, R - 1, 0)
        FOR(x, 0, C)
            D[1][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[1][y + 1][x],
                                       x == 1 - 1 ? 0 : D[1][y][x - 1]);
    ROF(y, R - 1, 0)
        ROF(x, C - 1, 0)
            D[2][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[2][y + 1][x],
                                       x == C - 1 ? 0 : D[2][y][x + 1]);
    FOR(y, 0, R)
        ROF(x, C - 1, 0)
            D[3][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[3][y - 1][x],
                                       x == C - 1 ? 0 : D[3][y][x + 1]);

    DBG(1)
    FOR(i, 0, 4) {
        cout << D[i] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 1, R - 1) {
        FOR(x, 1, C - 1) {
            apply(max,
                  res,
                  D[0][y - 1][x] + D[2][y + 1][x] + D[1][y][x - 1] +
                      D[3][y][x + 1]);
            apply(max,
                  res,
                  D[0][y][x - 1] + D[2][y][x + 1] + D[1][y + 1][x] +
                      D[3][y - 1][x]);
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    scanf("%lld%lld", &R, &C);

    vvll B(R, vll(C));
    FOR(y, 0, R)
        FOR(x, 0, C)
            scanf("%lld", &B[y][x]);

    vector<vvll> D(4, vvll(R, vll(C, 0)));

    FOR(y, 0, R)
        FOR(x, 0, C)
            D[0][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[0][y - 1][x],
                                       x == 1 - 1 ? 0 : D[0][y][x - 1]);
    ROF(y, R - 1, 0)
        FOR(x, 0, C)
            D[1][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[1][y + 1][x],
                                       x == 1 - 1 ? 0 : D[1][y][x - 1]);
    ROF(y, R - 1, 0)
        ROF(x, C - 1, 0)
            D[2][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[2][y + 1][x],
                                       x == C - 1 ? 0 : D[2][y][x + 1]);
    FOR(y, 0, R)
        ROF(x, C - 1, 0)
            D[3][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[3][y - 1][x],
                                       x == C - 1 ? 0 : D[3][y][x + 1]);

    DBG(1)
    FOR(i, 0, 4) {
        cout << D[i] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 1, R - 1) {
        FOR(x, 1, C - 1) {
            apply(max,
                  res,
                  D[0][y - 1][x] + D[2][y + 1][x] + D[1][y][x - 1] +
                      D[3][y][x + 1]);
            apply(max,
                  res,
                  D[0][y][x - 1] + D[2][y][x + 1] + D[1][y + 1][x] +
                      D[3][y - 1][x]);
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    printf("%lld\n", res);
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = int; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    ll B[1005][1005] = {};
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    ll D[4][1005][1005] = {};

    FOR(y, 1, R + 1)
        FOR(x, 1, C + 1)
            D[0][y][x] = B[y][x] + max(D[0][y - 1][x], D[0][y][x - 1]);
    ROF(y, R, 1)
        FOR(x, 1, C + 1)
            D[1][y][x] = B[y][x] + max(D[1][y + 1][x], D[1][y][x - 1]);
    ROF(y, R, 1)
        ROF(x, C, 1)
            D[2][y][x] = B[y][x] + max(D[2][y + 1][x], D[2][y][x + 1]);
    FOR(y, 1, R + 1)
        ROF(x, C, 1)
            D[3][y][x] = B[y][x] + max(D[3][y - 1][x], D[3][y][x + 1]);

    DBG(1)
    FOR(i, 0, 4) {
        cout << D[i] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 2, R) {
        FOR(x, 2, C) {
            apply(max,
                  res,
                  D[0][y - 1][x] + D[2][y + 1][x] + D[1][y][x - 1] +
                      D[3][y][x + 1]);
            apply(max,
                  res,
                  D[0][y][x - 1] + D[2][y][x + 1] + D[1][y + 1][x] +
                      D[3][y - 1][x]);
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    vvll B(R, vll(C));
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    vector<vector<point>> dirs = {{{1, 0}, {0, 1}},
                                  {{1, 0}, {0, -1}},
                                  {{-1, 0}, {0, -1}},
                                  {{-1, 0}, {0, 1}}};
    vector<vector<vvll>>  D(4, vector<vvll>(2, vvll(R, vll(C, 0))));
    FOR(k, 0, len(dirs)) {
        FOR(y, 0, C) {
            FOR(x, 0, R) {
                point curr = {dirs[k][0].real() == 1 ? x : C - x - 1,
                              dirs[k][1].imag() == 1 ? y : R - y - 1};
                FOR(d, 0, len(dirs[k])) {
                    point nex = curr + dirs[k][d];
                    if(nex.real() < 0 || nex.real() >= C || nex.imag() < 0 ||
                       nex.imag() >= R)
                        continue;
                    FOR(d2, 0, 2)
                        apply(max,
                              D[k][d][nex.imag()][nex.real()],
                              D[k][d2][curr.imag()][curr.real()] +
                                  B[curr.imag()][curr.real()]);
                }
            }
        }
    }

    DBG(1)
    FOR(i, 0, 4) {
        FOR(j, 0, 2)
            cout << D[i][j] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 0, R) {
        FOR(x, 0, C) {
            FOR(d, 0, len(dirs)) {
                ll r = 0;
                FOR(k, 0, len(dirs))
                    r += D[k][(d + k % 2) % 2][y][x];
                apply(max, res, r);
            }
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    vvll B(R, vll(C));
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    vector<vector<point>> dirs = {{{1, 0}, {0, 1}},
                                  {{1, 0}, {0, -1}},
                                  {{-1, 0}, {0, -1}},
                                  {{-1, 0}, {0, 1}}};
    vector<vvll>          D(4, vvll(R, vll(C, 0)));
    FOR(k, 0, len(dirs)) {
        FOR(y, 0, R) {
            FOR(x, 0, C) {
                point curr = {dirs[k][0].real() == 1 ? x : C - x - 1,
                              dirs[k][1].imag() == 1 ? y : R - y - 1};
                FOR(d, 0, len(dirs[k])) {
                    point nex = curr + dirs[k][d];
                    if(nex.real() < 0 || nex.real() >= C || nex.imag() < 0 ||
                       nex.imag() >= R)
                        continue;
                    FOR(d2, 0, 2)
                        apply(max,
                              D[k][nex.imag()][nex.real()],
                              D[k][curr.imag()][curr.real()] +
                                  B[curr.imag()][curr.real()]);
                }
            }
        }
    }

    DBG(1)
    FOR(i, 0, 4) {
        cout << D[i] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 1, R - 1) {
        FOR(x, 1, C - 1) {
            FOR(d, 0, 2) {
                ll r = 0;
                FOR(k, 0, len(dirs))
                    r += B[y - dirs[k][(k + d) % 2].imag()]
                          [x - dirs[k][(k + d) % 2].real()] +
                         D[k][y - dirs[k][(k + d) % 2].imag()]
                          [x - dirs[k][(k + d) % 2].real()];
                apply(max, res, r);
                DBG(3) cout << "\t" << vll{y, x, r} << endl;
            }
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = int; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

ll B[1005][1005]  = {};
ll D1[1005][1005] = {}, D2[1005][1005] = {}, D3[1005][1005] = {},
   D4[1005][1005] = {};
yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    FOR(y, 1, R + 1)
        FOR(x, 1, C + 1)
            D1[y][x] = B[y - 1][x - 1] + max(D1[y - 1][x], D1[y][x - 1]);
    ROF(y, R, 1)
        FOR(x, 1, C + 1)
            D2[y][x] = B[y - 1][x - 1] + max(D2[y + 1][x], D2[y][x - 1]);
    ROF(y, R, 1)
        ROF(x, C, 1)
            D3[y][x] = B[y - 1][x - 1] + max(D3[y + 1][x], D3[y][x + 1]);
    FOR(y, 1, R + 1)
        ROF(x, C, 1)
            D4[y][x] = B[y - 1][x - 1] + max(D4[y - 1][x], D4[y][x + 1]);

    ll res = 0;
    FOR(y, 2, R) {
        FOR(x, 2, C) {
            apply(max,
                  res,
                  D1[y - 1][x] + D3[y + 1][x] + D2[y][x - 1] + D4[y][x + 1]);
            apply(max,
                  res,
                  D1[y][x - 1] + D3[y][x + 1] + D2[y + 1][x] + D4[y - 1][x]);
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    vvll B(R, vll(C));
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    vector<vector<point>> dirs = {{{1, 0}, {0, 1}},
                                  {{1, 0}, {0, -1}},
                                  {{-1, 0}, {0, -1}},
                                  {{-1, 0}, {0, 1}}};
    vector<vector<vvll>>  D(4, vector<vvll>(2, vvll(R, vll(C, 0))));
    FOR(k, 0, len(dirs)) {
        FOR(y, 0, C) {
            FOR(x, 0, R) {
                point curr = {dirs[k][0].real() == 1 ? x : C - x - 1,
                              dirs[k][1].imag() == 1 ? y : R - y - 1};
                FOR(d, 0, len(dirs[k])) {
                    point nex = curr + dirs[k][d];
                    if(nex.real() < 0 || nex.real() >= C || nex.imag() < 0 ||
                       nex.imag() >= R)
                        continue;
                    FOR(d2, 0, 2)
                        apply(max,
                              D[k][d][nex.imag()][nex.real()],
                              D[k][d2][curr.imag()][curr.real()] +
                                  B[curr.imag()][curr.real()]);
                }
            }
        }
    }

    DBG(1)
    FOR(i, 0, 4) {
        FOR(j, 0, 2)
            cout << D[i][j] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 1, R - 1) {
        FOR(x, 1, C - 1) {
            FOR(d, 0, len(dirs)) {
                ll r = 0;
                FOR(k, 0, len(dirs))
                    r += D[k][(d + k % 2) % 2][y][x];
                apply(max, res, r);
            }
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    vvll B(R, vll(C));
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    vector<vector<point>> dirs = {{{1, 0}, {0, 1}},
                                  {{1, 0}, {0, -1}},
                                  {{-1, 0}, {0, -1}},
                                  {{-1, 0}, {0, 1}}};
    vector<vector<vvll>>  D(4, vector<vvll>(2, vvll(R, vll(C, 0))));
    FOR(k, 0, len(dirs)) {
        FOR(y, 0, R) {
            FOR(x, 0, C) {
                point curr = {dirs[k][0].real() == 1 ? x : C - x - 1,
                              dirs[k][1].imag() == 1 ? y : R - y - 1};
                FOR(d, 0, len(dirs[k])) {
                    point nex = curr + dirs[k][d];
                    if(nex.real() < 0 || nex.real() >= C || nex.imag() < 0 ||
                       nex.imag() >= R)
                        continue;
                    FOR(d2, 0, 2)
                        apply(max,
                              D[k][d][nex.imag()][nex.real()],
                              D[k][d2][curr.imag()][curr.real()] +
                                  B[curr.imag()][curr.real()]);
                }
            }
        }
    }

    DBG(1)
    FOR(i, 0, 4) {
        FOR(j, 0, 2)
            cout << D[i][j] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 1, R - 1) {
        FOR(x, 1, C - 1) {
            FOR(d, 0, 2) {
                ll r = 0;
                FOR(k, 0, len(dirs))
                    r += D[k][(d + k % 2) % 2][y][x];
                apply(max, res, r);
                DBG(3) cout << "\t" << vll{y, x, r} << endl;
            }
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = int; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    vvll B(R, vll(C));
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    vector<vvll> D(4, vvll(R, vll(C, 0)));

    FOR(y, 0, R)
        FOR(x, 0, C)
            D[0][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[0][y - 1][x],
                                       x == 1 - 1 ? 0 : D[0][y][x - 1]);
    ROF(y, R - 1, 0)
        FOR(x, 0, C)
            D[1][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[1][y + 1][x],
                                       x == 1 - 1 ? 0 : D[1][y][x - 1]);
    ROF(y, R - 1, 0)
        ROF(x, C - 1, 0)
            D[2][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[2][y + 1][x],
                                       x == C - 1 ? 0 : D[2][y][x + 1]);
    FOR(y, 0, R)
        ROF(x, C - 1, 0)
            D[3][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[3][y - 1][x],
                                       x == C - 1 ? 0 : D[3][y][x + 1]);

    DBG(1)
    FOR(i, 0, 4) {
        cout << D[i] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 1, R - 1) {
        FOR(x, 1, C - 1) {
            apply(max,
                  res,
                  D[0][y - 1][x] + D[2][y + 1][x] + D[1][y][x - 1] +
                      D[3][y][x + 1]);
            apply(max,
                  res,
                  D[0][y][x - 1] + D[2][y][x + 1] + D[1][y + 1][x] +
                      D[3][y - 1][x]);
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = int; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

ll B[1005][1005], D1[1005][1005], D2[1005][1005], D3[1005][1005],
   D4[1005][1005];
yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    FOR(y, 1, R + 1)
        FOR(x, 1, C + 1)
            D1[y][x] = B[y - 1][x - 1] + max(D1[y - 1][x], D1[y][x - 1]);
    ROF(y, R, 1)
        FOR(x, 1, C + 1)
            D2[y][x] = B[y - 1][x - 1] + max(D2[y + 1][x], D2[y][x - 1]);
    ROF(y, R, 1)
        ROF(x, C, 1)
            D3[y][x] = B[y - 1][x - 1] + max(D3[y + 1][x], D3[y][x + 1]);
    FOR(y, 1, R + 1)
        ROF(x, C, 1)
            D4[y][x] = B[y - 1][x - 1] + max(D4[y - 1][x], D4[y][x + 1]);

    ll res = 0;
    FOR(y, 2, R) {
        FOR(x, 2, C) {
            apply(max,
                  res,
                  D1[y - 1][x] + D3[y + 1][x] + D2[y][x - 1] + D4[y][x + 1]);
            apply(max,
                  res,
                  D1[y][x - 1] + D3[y][x + 1] + D2[y + 1][x] + D4[y - 1][x]);
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = int; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    ll B[1005][1005] = {};
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    ll D[4][1005][1005] = {};

    FOR(y, 0, R)
        FOR(x, 0, C)
            D[0][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[0][y - 1][x],
                                       x == 1 - 1 ? 0 : D[0][y][x - 1]);
    ROF(y, R - 1, 0)
        FOR(x, 0, C)
            D[1][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[1][y + 1][x],
                                       x == 1 - 1 ? 0 : D[1][y][x - 1]);
    ROF(y, R - 1, 0)
        ROF(x, C - 1, 0)
            D[2][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[2][y + 1][x],
                                       x == C - 1 ? 0 : D[2][y][x + 1]);
    FOR(y, 0, R)
        ROF(x, C - 1, 0)
            D[3][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[3][y - 1][x],
                                       x == C - 1 ? 0 : D[3][y][x + 1]);

    DBG(1)
    FOR(i, 0, 4) {
        cout << D[i] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 1, R - 1) {
        FOR(x, 1, C - 1) {
            apply(max,
                  res,
                  D[0][y - 1][x] + D[2][y + 1][x] + D[1][y][x - 1] +
                      D[3][y][x + 1]);
            apply(max,
                  res,
                  D[0][y][x - 1] + D[2][y][x + 1] + D[1][y + 1][x] +
                      D[3][y - 1][x]);
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    vvll B(R, vll(C));
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    vector<vector<point>> dirs = {{{+1, 0}, {0, +1}},
                                  {{+1, 0}, {0, -1}},
                                  {{-1, 0}, {0, +1}},
                                  {{-1, 0}, {0, -1}}};
    vector<vector<vvll>>  D(4, vector<vvll>(2, vvll(R, vll(C, 0))));
    FOR(k, 0, len(dirs)) {
        FOR(y, 0, C) {
            FOR(x, 0, R) {
                point curr = {dirs[k][0].real() == 1 ? x : C - x - 1,
                              dirs[k][1].imag() == 1 ? y : R - y - 1};

                FOR(d, 0, len(dirs[k])) {
                    point nex = curr + dirs[k][d];
                    if(nex.real() < 0 || nex.real() >= C || nex.imag() < 0 ||
                       nex.imag() >= R)
                        continue;

                    FOR(d2, 0, len(dirs[k]))
                        apply(max,
                              D[k][d][nex.imag()][nex.real()],
                              D[k][d2][curr.imag()][curr.real()] +
                                  B[curr.imag()][curr.real()]);
                }
            }
        }
    }

    DBG(1)
    FOR(i, 0, 4) {
        FOR(j, 0, 2)
            cout << D[i][j] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 0, R) {
        FOR(x, 0, C) {
            apply(max,
                  res,
                  max(D[0][0][y][x], D[0][1][y][x]) +
                      max(D[1][0][y][x], D[1][1][y][x]) +
                      max(D[2][0][y][x], D[2][1][y][x]) +
                      max(D[3][0][y][x], D[3][1][y][x]));
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = int; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    ll B[1005][1005] = {};
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    ll D1[1005][1005] = {}, D2[1005][1005] = {}, D3[1005][1005] = {},
       D4[1005][1005] = {};

    FOR(y, 1, R + 1)
        FOR(x, 1, C + 1)
            D1[y][x] = B[y - 1][x - 1] + max(D1[y - 1][x], D1[y][x - 1]);
    ROF(y, R, 1)
        FOR(x, 1, C + 1)
            D2[y][x] = B[y - 1][x - 1] + max(D2[y + 1][x], D2[y][x - 1]);
    ROF(y, R, 1)
        ROF(x, C, 1)
            D3[y][x] = B[y - 1][x - 1] + max(D3[y + 1][x], D3[y][x + 1]);
    FOR(y, 1, R + 1)
        ROF(x, C, 1)
            D4[y][x] = B[y - 1][x - 1] + max(D4[y - 1][x], D4[y][x + 1]);

    ll res = 0;
    FOR(y, 2, R) {
        FOR(x, 2, C) {
            apply(max,
                  res,
                  D1[y - 1][x] + D3[y + 1][x] + D2[y][x - 1] + D4[y][x + 1]);
            apply(max,
                  res,
                  D1[y][x - 1] + D3[y][x + 1] + D2[y + 1][x] + D4[y - 1][x]);
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}


// clang-format off
// very important, much wow, such don't touch this
#define protected public
using iii = int; using yeee = iii;

#ifdef LOCAL
    const iii DEBUG = 0;
#else
    const iii DEBUG = -1;
#endif
#define DBG(x) if(DEBUG >= x)

#include <bits/stdc++.h>
using namespace std;

#if 0
    #include <ext/pb_ds/assoc_container.hpp>
    #include <ext/pb_ds/detail/standard_policies.hpp>
    using namespace __gnu_pbds;
    template<class T> using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;
    template<class T, class U> using hash_map = gp_hash_table<T, U>;
#endif

#define FOR(i, lo, hi) for(ll i = ll(lo); i < ll(hi); ++i)
#define ROF(i, hi, lo) for(ll i = ll(hi); i >= (ll)(lo); --i)
#define all(x) (x).begin(), (x).end()
#define len(x) ll((x).size())
#define pb push_back
#define apply(f, x, y) (x) = f((x), (y))

using ll = long long; using ull = unsigned long long; using ld = long double; using pll = pair<ll, ll>; using vb = vector<bool>; using vvb = vector<vb>; using vll = vector<ll>; using vvll = vector<vll>; using vpll = vector<pll>; using point = complex<ll>; /*|||*/ template <class T> T get() { T x; cin >> x; return x; } template <class T1, class T2> ostream &operator<<(ostream &out, const pair<T1, T2> &cont) { out << "(" << cont.first << ", " << cont.second << ")"; return out; } template <class T> ostream &operator<<(ostream &out, const vector<T> &cont) { for(long long int i=0; i < (long long int)(cont.size()); ++i) out << (i ? " " : "") << cont[i]; return out; } template <class T> ostream &operator<<(ostream &out, const set<T> &cont) { out << "{"; for(const T &x : cont) out << x << ", "; out << "}"; return out; } template <class T, class U> ostream &operator<<(ostream &out, const map<T, U> &cont) { out << "{"; for(const pair<T, U> &x : cont) out << "(" << x.first << ": " << x.second << "), "; out << "}"; return out; } template <class T> ostream &operator<<(ostream &out, vector<vector<T>> &cont) { for(vector<T> &v : cont) { for(long long int i = 0; i < (long long int)(v.size()); ++i) { out << (i ? " " : "") << v[i]; } out << "\n"; } return out; } /*|||*/ void setup_io(string input_file = "", string output_file = "", bool fast_cio = true) { if(fast_cio) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); } srand(unsigned(time(0))); DBG(0 && input_file != "") freopen(input_file.c_str(), "r", stdin); DBG(0 && output_file != "") freopen(output_file.c_str(), "w", stdout); } /*|||*/ std::chrono::_V2::system_clock::time_point get_time() { return chrono::high_resolution_clock::now(); } ld get_duration(std::chrono::_V2::system_clock::time_point start_time, std::chrono::_V2::system_clock::time_point end_time) { return ld(chrono::duration_cast<chrono::nanoseconds>(end_time - start_time).count()) / 1e9; } /*|||*/ ll sign(ld x) { return (x > 0) - (x < 0); } ll pow(ll x, ll exp, ll mod) { ll res = 1, y = x; while(exp) { if(!mod) { if(exp & 1) res = res * y; y = y * y; } else { if(exp & 1) res = (res * y) % mod; y = (y * y) % mod; } exp >>= 1; } return res; } /*|||*/ auto START_TIME = get_time(); const long long INF = LONG_LONG_MAX / 3; char newl = '\n';
// clang-format on

yeee main() {
    setup_io();
    //

    ll R, C;
    cin >> R >> C;

    vvll B(R, vll(C));
    FOR(y, 0, R)
        FOR(x, 0, C)
            cin >> B[y][x];

    vector<vvll> D(4, vvll(R, vll(C, 0)));

    FOR(y, 0, R)
        FOR(x, 0, C)
            D[0][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[0][y - 1][x],
                                       x == 1 - 1 ? 0 : D[0][y][x - 1]);
    ROF(y, R - 1, 0)
        FOR(x, 0, C)
            D[1][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[1][y + 1][x],
                                       x == 1 - 1 ? 0 : D[1][y][x - 1]);
    ROF(y, R - 1, 0)
        ROF(x, C - 1, 0)
            D[2][y][x] = B[y][x] + max(y == R - 1 ? 0 : D[2][y + 1][x],
                                       x == C - 1 ? 0 : D[2][y][x + 1]);
    FOR(y, 0, R)
        ROF(x, C - 1, 0)
            D[3][y][x] = B[y][x] + max(y == 1 - 1 ? 0 : D[3][y - 1][x],
                                       x == C - 1 ? 0 : D[3][y][x + 1]);

    DBG(1)
    FOR(i, 0, 4) {
        cout << D[i] << endl;
        cout << "---" << endl;
    }

    ll res = 0;
    FOR(y, 1, R - 1) {
        FOR(x, 1, C - 1) {
            apply(max,
                  res,
                  D[0][y - 1][x] + D[2][y + 1][x] + D[1][y][x - 1] +
                      D[3][y][x + 1]);
            apply(max,
                  res,
                  D[0][y][x - 1] + D[2][y][x + 1] + D[1][y + 1][x] +
                      D[3][y - 1][x]);
            DBG(3) cout << vll{y, x, res} << endl;
        }
    }

    cout << res << endl;
}