| Bytes | Lang | Time | Link |
|---|---|---|---|
| 029 | Charcoal | 250207T113142Z | Neil |
| 006 | Jalapeño | 250207T013410Z | ATaco |
| 164 | Google Sheets | 250205T100144Z | doubleun |
| 105 | R | 250205T192155Z | pajonk |
| 094 | Maple | 250205T194737Z | dharr |
| 017 | Retina | 250205T173219Z | Unrelate |
| 022 | K ngn/k | 250205T164320Z | att |
| 098 | Elixir | 250205T161746Z | TKDKid10 |
| 090 | Perl 5 MListUtil=max | 250205T052932Z | Xcali |
| 004 | Japt | 250205T141837Z | Shaggy |
| 006 | Jelly | 250205T135551Z | ais523 |
| 005 | 05AB1E | 250205T103707Z | Kevin Cr |
| 077 | Python | 250205T080909Z | l4m2 |
| 028 | Retina | 250205T084531Z | Neil |
| 019 | J | 250205T055855Z | Jonah |
| 014 | Uiua | 250205T055325Z | RubenVer |
| 079 | JavaScript Node.js | 250205T050037Z | l4m2 |
| 021 | TinyAPL beta 0.12 | 250205T054130Z | RubenVer |
| 086 | Python | 250205T040849Z | Mukundan |
Charcoal, 29 bytes
SθW⌕⮌θ «⊞υθSθ»≧◨⌈EυLιυ⁼υE⮌υ⮌ι
Try it online! Link is to verbose version of code. Takes input with a space as a terminator (since input lines can't end with a space) and outputs a Charcoal boolean, i.e. - for centrosymmetric, nothing if not. Explanation:
SθW⌕⮌θ «⊞υθSθ»
Read the input into an array. (The only other approach would be an awkward input format ["a\n\n b\n b\n\n a"].)
≧◨⌈EυLιυ
Pad all elements of the array to the length of the longest.
⁼υE⮌υ⮌ι
Test whether the array equals its rotation.
Jalapeño, 6 bytes
G₊={₂↶↦↶
Explained
G₊={₂↶↦↶
G₊ # Implicit input as grid, padded with spaces
={₂ # Is equal to
↶ # Row order reversed
↦↶ # Column order reversed (map reverse)
Hex-Dump of Bytecode
0 1 2 3 4 5 6 7 8 9 A B C D E F
0000: 0c 59 c6 d7 d0 d7
Google Sheets, 164 bytes
=index(let(a,tocol(split(A1,"
",,)),b,tocol(regexextract(a,rept("(.)",len(a)))),c,join(,if(b=""," ",b)),l,len(c),s,sequence(l),l=sum(n(mid(c,s,1)=mid(c,l-s+1,1)))))
Put the string in cell A1 and the formula in cell B1. Note that there is a hardcoded newline in the formula between the first two double quotes.

Ungolfed:
=index(let(
a, tocol(split(A1, char(10), false, false)),
b, tocol(regexextract(a, rept("(.)", len(a)))),
c, join(, if(b = "", " ", b)),
l, len(c),
s, sequence(l),
l = sum(n(mid(c, s, 1) = mid(c, l - s + 1, 1)))
))
Update: the formula also takes into account pajonk's new suggested test case (+2 bytes):
a
b
a
R, 111 105 bytes
\(s,`?`=strsplit)all(rev(v<-unlist(substr(paste0(x<-el(s?"
"),strrep(" ",n<-max(nchar(x)))),1,n)?""))==v)
Maple, 94 bytes
proc(s)uses StringTools;u:=Split(s,"\n");IsPalindrome(cat(PadRight~(u,max(length~(u)))[]))end;
Straightforward code. Accepts multiline string s; splits at newlines; finds longest substring and pads substrings to that length; concatenates the substrings; checks if it is a palindrome.
Retina, 17 bytes
P`.+
s~`.+
$\$^$&
Steals the actual approach from Neil's solution, but with a different non-0.8.2-compatible palindrome checking method that doesn't appear to have been used before.
P`.+
Right-pad every line to the same length with spaces.
s~`.+
$\$^$&
In single-line mode s, run an eval stage ~ containing a replace stage (implicit) that replaces the entire padded working string (.+ with the s flag to include newlines) with itself $& reversed $^ and escaped $\. The result of the replacement is a match stage which counts the occurrences of the padded string reversed inside the original padded string.
K (ngn/k), 22 bytes
#|:\,/$/|1(|/#:')\"
"\
Returns 1 if centrosymmetric, and 2 otherwise.
Fairly straightforward translation of the definition.
"\n"\ split lines
$/|1(|/#:')\ pad lines
,/ join
|:\ and its reverse (if distinct)
# count
Elixir, 98 bytes
fn a->import String
b=trim Enum.join split(a,"\n")|>Enum.map(&ljust&1,bit_size a)
b==reverse b end
Similar concept as I4m2, but using as much Elixir trickery as possible. I tried a rotation approach but it was way larger.
Perl 5 -MList::Util=max, 94 90 bytes
chomp,$_.=$"x((max map y///c,@a)-y///c)for@a=<>;say("@a"eq"@{[map{$d=reverse}reverse@a]}")
Japt, 4 bytes
Õ
¶Ô
ú êQ
Õ\n¶Ô :Implicit input of string U
Õ :Transpose
\n :Reassign to U
¶ :Is equal to
Ô : Reverse
ú êQ :Implicit input of string
ú :Right pad each line with spaces to length of longest
êQ :Is palindrome?
Jelly, 6 bytes
Ỵz⁶YUƑ
Try it online! (I copied the encoding of the test cases into strings from @Kevin Cruijssen's answer.)
Explanation
As the question mentions, this problem would be trivial if we had a string that was correctly padded with spaces already. As such, it can be solved by padding the string ourself, then checking to see whether that makes it into a palindrome.
Ỵz⁶YUƑ
Ỵ split {input} on newlines
z ragged transpose {the split input}, padding with
⁶ spaces
Y join {the result of the transpose} with newlines
Ƒ {return} whether {the joined result} is invariant when
U reversed
This algorithm actually checks the transpose of the input for centrosymmetry, rather than the input itself, because transposing a ragged array is the easiest way to pad it to a rectangle in Jelly and there was no reason to transpose it back (it remains centrosymmetric).
05AB1E, 5 bytes
.BÂíQ
Input as a multi-line string.
Try it online or verify all test cases.
Explanation:
.B # Split the (implicit) multi-line string on newlines,
# and add trailing spaces if necessary to make it a rectangle
 # Bifurcate it; short for Duplicate & Reverse copy
í # Reverse each inner row of this reversed copy
Q # Check if the two list of strings are the same
# (after which the result is output implicitly)
Python, 77 bytes
lambda x:(a:="".join(f"{i:{len(x)}}"for i in x.split('\n')).strip())==a[::-1]
Quite different to my JS solution so separated answer
-1B tsh
Retina, 28 bytes
P`.+
s(+`^(.)(.*)\1$
$2
^.?$
Try it online! No test suite because that's tricky when the inputs are multiline. Explanation:
P`.+
Pad all of the lines to the same length.
s(`
Evaluate the rest of the program in single-line mode where . also matches a newline.
+`^(.)(.*)\1$
$2
Repeatedly remove matching characters from the beginning and end of the string.
^.?$
Check that at most one character is left.
J, 19 bytes
[:(-:|:@|.^:2)];._2
J does the right thing by default re: padding when you chop into lines.
After that we just check if applying transpose after reverse twice gives us back the same thing.
Uiua, 14 bytes
≍≡⇌⊸⇌⬚@ ⊜∘⊸≥@
Explanation
≍≡⇌⊸⇌⬚@ ⊜∘⊸≥@
@ ⊜∘⊸≥@ # Split by newlines, and join into a matrix filling with spaces
≍≡⇌⊸⇌ # Is the 180° rotation of the matrix equal to the original matrix?
💎
Created with the help of Luminespire.
JavaScript (Node.js), 79 bytes
f=(x,y=[])=>1/x?y+''==y.reverse():f(x.replace(/^.?/mg,c=>y.push(c||' ')&&''),y)
Flips and test
TinyAPL beta 0.12, 21 bytes
⦅⊖◡⍤⊖⊸≡·↑⬚' '' '≤⇾⊆⊢⦆
Explanation
⦅⊖◡⍤⊖⊸≡·↑⬚' '' '≤⇾⊆⊢⦆
' '≤⇾⊆⊢ ⍝ Split by newlines
↑⬚' ' ⍝ Make into a matrix padding with spaces
⊖◡⍤⊖⊸≡ ⍝ Is it equal to the 180° rotation?
💎
Created with the help of Luminespire.
Python, 86 bytes
lambda x:(x:=x.split('\n'))!=(a:="".join(f"{i:{max(map(len,x))}}"for i in x))==a[::-1]
Pads the given string into a rectangle then checks if it is a palindrome
Python, 86 bytes
lambda x:(x:=x.split('\n'))==[f"{i:{max(map(len,x))}}"[::-1].rstrip()for i in x[::-1]]
Uses the fact that the input won't contain trailing spaces on any of the lines