Box blur is a simple operation for blurring images. To apply box blur, simply replace each pixel with the average of its and the surrounding 8 pixels' values. Consider, for example, the following example, in which each "pixel" has a one-digit value:
\begin{array} {|r|r|}\hline 1 & 1 & 1 \\ \hline 1 & 7 & 1 \\ \hline 1 & 1 & 1 \\ \hline \end{array}
To get the blurred value of the center pixel we add its value to the 8 surrounding pixels' values and divide by 9.
$$ \frac{7+1+1+1+1+1+1+1+1}{9}=\frac{5}{3}=1.\overline{6} $$
Repeat this operation for every pixel and you've blurred the image.
The task
Like pixels, strings are just numbers, so we can box blur them too. Your task is to take a string, which may have multiple lines, in some convenient format and return a new string that's been "blurred" by the above process. That is to say, you'll take each character's ASCII value and treat it as that character's value, "blur" the values, and return the new values' corresponding characters.
For example, given the following input:
'''#
''#'
'#''
#'''
Your output would look like this:
''&%
'&&&
&&&'
%&''
Edges and corners
How do you blur a "pixel" that doesn't have eight neighbors because it's on an edge or in a corner of the "canvas"? For our purposes, you'll solve this by "filling in" the missing pixels with the nearest pixel's value. In the example below the missing value northwest of 1 is filled in with 1; likewise the missing value east of 6 is filled in with 6.
\begin{array} {|r|r|}\hline \color{silver}{1} & \color{silver}{1} & \color{silver}{2} & \color{silver}{3} & \color{silver}{3} \\ \hline \color{silver}{1} & 1 & 2 & 3 & \color{silver}{3} \\ \hline \color{silver}{4} & 4 & 5 & 6 & \color{silver}{6} \\ \hline \color{silver}{7} & 7 & 8 & 9 & \color{silver}{9} \\ \hline \color{silver}{7} & \color{silver}{7} & \color{silver}{8} & \color{silver}{9} & \color{silver}{9} \\ \hline \end{array}
Rounding
For our purposes, you'll round fractions to the nearest integer. Halves should be rounded up.
Rules
The input will consist of one or more lines of one or more printable ASCII characters, i.e.
0x20
–0x7E
inclusive, plus newlines if applicable to your input format. The string will be "rectangular," i.e. every line will have the same length.The input format is flexible, e.g. a single string with lines separated by newlines, an array of strings with one string per line, a multi-dimensional array of characters, etc.
The output will be in the same format as the input, and likewise flexible.
Standard rules and default I/O rules apply and standard loopholes are forbidden.
This is code-golf so shortest solution in bytes wins.
More examples
Input Output
111 222
171 222
111 222
XXXXX INNNI
,,X,, ;DDD;
,,X,, ,;;;,
,,X,, ;DDD;
XXXXX INNNI
'888' /020/
8'''8 00/00
8'8'8 2/)/2
8'''8 00/00
'888' /020/
103050709 111324256
!~ JU
~! UJ
Q Q
+--+ <22<
| | <22<
+--+ <22<
^ M
* ;
* ;
^ M