[Question]
  [
You're given a rectangular grid of the characters `.` and `#`, like this:
```
..........
..#.......
....#..#..
...#......
..........
```
Your task is to fill the entire axis-aligned bounding box of the `#` with further `#`:
```
..........
..######..
..######..
..######..
..........
```
The axis-aligned bounding box is the smallest rectangle which contains all the `#`.
**Want more? [Try Part II!](https://codegolf.stackexchange.com/q/91517/8478)**
## Rules
You may use any two *distinct* printable ASCII characters (0x20 to 0x7E, inclusive), in place of `#` and `.`. I'll continue referring to them as `#` and `.` for the remainder of the specification though.
Input and output may either be a single linefeed-separated string or a list of strings (one for each line), but the format has to be consistent.
You may assume that the input contains at least one `#` and all lines are the same length.
You may write a [program or a function](http://meta.codegolf.stackexchange.com/q/2419) and use any of the our [standard methods](http://meta.codegolf.stackexchange.com/q/2447) of receiving input and providing output.
You may use any [programming language](http://meta.codegolf.stackexchange.com/q/2028), but note that [these loopholes](http://meta.codegolf.stackexchange.com/questions/1061/loopholes-that-are-forbidden-by-default) are forbidden by default.
This is [code-golf](/questions/tagged/code-golf "show questions tagged 'code-golf'"), so the shortest valid answer – measured in *bytes* – wins.
## Test Cases
Each test case has input and output next to each other.
```
#    #
...    ...
#..    #..
...    ...
...    ...
#..    ###
..#    ###
.#.    ###
#..    ###
..#    ###
.....    .....
.#.#.    .###.
.....    .....
...    ...
.#.    .#.
...    .#.
.#.    .#.
...    ...
..........    ..........
..........    ..........
....#.....    ....#.....
..........    ..........
..........    ..........
..........    ..........
....#.....    ...##.....
...#......    ...##.....
..........    ..........
..#.......    ..###.....
....#.....    ..###.....
...#......    ..###.....
..........    ..........
..#.......    ..######..
....#..#..    ..######..
...#......    ..######..
.........#    ..########
..#.......    ..########
....#..#..    ..########
...#......    ..########
```
  
[Answer]
# VBA Excel, ~~150 bytes~~ 146 bytes
**Instruction:**
Create a workbook with two blank worksheets: Sheet1 and Sheet2. Set the input in Sheet1 and then put the following code in the Sheet1 code module
```
Sub A:For Each C In UsedRange:If C.Value="#"Then Sheet2.Range(C.Address)="#"
Next:For Each C In Sheet2.UsedRange:Range(C.Address)="#":Next:End Sub
```
**Ungolfed the code:**
```
Sub A()
For Each C In UsedRange
    If C.Value = "#" Then Sheet2.Range(C.Address) = "#"
Next
For Each C In Sheet2.UsedRange
    Range(C.Address) = "#"
Next
End Sub
```
**Explanation:**
1. Loop through every cell in the used range Sheet1
2. Set the conditional statement to *copy* every cell contains character hashtag (#) in the used range Sheet1 and *paste* it to the cell in Sheet2 with the same address as Sheet1.
3. Loop through once again every cell in the used range Sheet2 to *copy* every cell address in it and then use it to assign character hashtag (#) to the cell in Sheet1 with the same address as the used range Sheet2.
**Example I/O:**
[![INPUT](https://i.stack.imgur.com/i74m2.png)](https://i.stack.imgur.com/i74m2.png) 
[![OUTPUT](https://i.stack.imgur.com/oFD5s.png)](https://i.stack.imgur.com/oFD5s.png)
**Caveat:** Make sure every cell in Sheet2 always blank every time you run the program.
[Answer]
# [05AB1E](https://github.com/Adriandmen/05AB1E/), ~~70~~ ~~68~~ ~~69~~ ~~61~~ ~~58~~ ~~60~~ 40 bytes
```
€S`¹gG~}Dg©L*0KŸ<U¹v¼y1åi®FXNå}ë0®×}J}¾ä
```
**Explanation**
```
€S`                                       # split each string in input to a charlist and place separately on stack
   ¹gG~}                                  # OR the char arrays to produce a single list with 1's in the columns that have 1's and 0 in the rest
        Dg L*                             # multiply by indices (1-indexed)
          ©                               # store row length in register
             0K                           # remove 0's (the indices which should not have 1's
               Ÿ<U                        # store a list of the indices that should have 1's in X
                  ¹v                 }    # for each string in input
                    ¼                     # increase counter
                     y1åi      ë   }      # if the row contains at least one 1
                         ®FXNå}           # push 1 for indices which should have 1 and else 0
                                0®×       # else push a row of 0's
                                    J     # join into a string
                                      ¾ä  # split the string in rows
```
[Try it online](http://05ab1e.tryitonline.net/#code=4oKsU2DCuWdHfn1EZ8KpTCowS8W4PFXCuXbCvHkxw6Vpwq5GWE7DpX3DqzDCrsOXfUp9wr7DpA&input=WycwMDAwMDAwMDAwJywnMDAxMDAwMDAwMCcsJzAwMTAxMDAxMDAnLCcwMDAxMDAwMDAwJywnMDAwMDAwMDAwMCdd)
[Answer]
# Mathematica, ~~91~~ 70 bytes
*21 bytes saved due to [@MartinEnder](http://ppcg.lol/users/8478).*
```
ReplacePart["."+0#,Tuples[Range@@@MinMax/@(#~Position~"#")]]->"#"]&
```
Anonymous function. Takes a character matrix as input an returns a character matrix as output. The Unicode character is U+F3C7 for `\[Transpose]`.
[Answer]
# [Jelly](https://github.com/DennisMitchell/jelly), ~~21~~ ~~19~~ ~~18~~ 17 [bytes](https://github.com/DennisMitchell/jelly/wiki/Code-page)
```
|/Tr/FṬ|
ỴµZÇZ&ÇY
```
This is a full program. Input and output are strings of **0**'s and **1**'s, delimited by linefeeds.
[Try it online!](http://jelly.tryitonline.net/#code=fC9Uci9G4bmsfArhu7TCtVrDh1omw4dZ&input=&args=MDAwMDAwMDAwMAowMDEwMDAwMDAwCjAwMDAxMDAxMDAKMDAwMTAwMDAwMA) or [verify all test cases](http://jelly.tryitonline.net/#code=fC9Uci9G4bmsfArhu7TCtVrDh1omw4dZCsWT4bmj4oCcwrbCtuKAncOH4oKsauKAnMK2wrbigJ0&input=&args=MQoKMDAwCjEwMAowMDAKCjAwMAoxMDAKMDAxCgowMTAKMTAwCjAwMQoKMDAwMDAKMDEwMTAKMDAwMDAKCjAwMAowMTAKMDAwCjAxMAowMDAKCjAwMDAwMDAwMDAKMDAwMDAwMDAwMAowMDAwMTAwMDAwCjAwMDAwMDAwMDAKCjAwMDAwMDAwMDAKMDAwMDAwMDAwMAowMDAwMTAwMDAwCjAwMDEwMDAwMDAKCjAwMDAwMDAwMDAKMDAxMDAwMDAwMAowMDAwMTAwMDAwCjAwMDEwMDAwMDAKCjAwMDAwMDAwMDAKMDAxMDAwMDAwMAowMDAwMTAwMTAwCjAwMDEwMDAwMDAKCjAwMDAwMDAwMDEKMDAxMDAwMDAwMAowMDAwMTAwMTAwCjAwMDEwMDAwMDA).
### How it works
```
ỴµZÇZ&ÇY  Main link. Argument: s (string)
Ỵ         Split s at linefeeds into the array A.
 µ        Begin a new, monadic chain. Argument: A
  Z       Zip/transpose A.
   Ç      Apply the helper link to the transpose.
    Z     Zip/transpose to restore the original order.
      Ç   Apply the helper link to A.
     &    Take the bitwise AND of both results.
       Y  Join, separating by linefeeds.
|/Tr/FṬ|  Helper link. Argument: A (array of strings)
|/        Reduce A columnwise by bitwise OR. This casts to integer.
  T       Truth; yield the indices of 1's.
   r/     Reduce by range. This yields an exponentially growing, nested, ragged
          array that contains all integers between the lowest and highest index
          in the previous result, at least once but possibly multiple times.
     F    Flatten the result.
      Ṭ   Untruth; yield an array with 1's at the specified indices.
          Multiple occurrences of the same index are ignored.
       |  Take the bitwise OR of the result and each row of A.
```
[Answer]
## C#, ~~262~~ 251 bytes
```
s=>{int l,t,r,b,i,j,k;l=t=r=b=i=-1;for(;++i<s.Length;){j=s[i].IndexOf('#');if(j>-1){k=s[i].LastIndexOf('#');l=l==-1|j<l?j:l;t=t==-1?i:t;r=k>r?k:r;b=i;}}for(i=t;i<=b;++i)for(j=l;j<=r;){var c=s[i].ToCharArray();c[j++]='#';s[i]=new string(c);}return s;};
```
Will golf it further when I have more time.
It compiles into a `Func<string[], string[]>`.
Formatted version:
```
s =>
{
    int l, t, r, b, i, j, k;
    l = t = r = b = i = -1;
    for (; ++i < s.Length;)
    {
        j = s[i].IndexOf('#');
        if (j > -1)
        {
            k = s[i].LastIndexOf('#');
            l = l == -1 | j < l ? j : l;
            t = t == -1 ? i : t;
            r = k > r ? k : r;
            b = i;
        }
    } 
    for (i = t; i <= b; ++i)
        for (j = l; j <= r;)
        {
            var c = s[i].ToCharArray();
            c[j++] = '#';
            s[i] = new string(c);
        }
    return s;
};
```
[Answer]
## [Retina](https://github.com/m-ender/retina), 87 bytes
Byte count assumes ISO 8859-1 encoding.
```
Tm`A` `^\GA+¶|(¶A+)+\Z|^(A+?)(?<=(?=\D*^\2Z)\A\D*)|(A+)$(?=\D*\Z(?<!(?<!\3)$\D*))
T`p`L
```
Uses `A` for `.` and `Z` for `#`.
[Try it online!](http://retina.tryitonline.net/#code=VG1gQWAgYF5cR0ErwrZ8KMK2QSspK1xafF4oQSs_KSg_PD0oPz1cRCpeXDJaKVxBXEQqKXwoQSspJCg_PVxEKlxaKD88ISg_PCFcMykkXEQqKSkKVGBwYEw&input=QUFBQUFBQUFBQQpBQVpBQUFaQUFBCkFBQUFaQUFaQUEKQUFBWkFBQUFBQQpBQUFBQUFBQUFB)
[Answer]
# Scala, 317 characters
```
val a=input.split("\n");val e=a.map{s=>(s.indexOf("#"),s.lastIndexOf("#"))}.zipWithIndex.filter(_._1._1!= -1);val b=(e.map{s=>s._1._1}.min,e.map{s=>s._1._2}.max,e.head._2,e.last._2);print((0 to a.length-1).map{y=>(0 to a(y).length-1).map{x=>if(x>=b._1&&x<=b._2&&y>=b._3&&y<=b._4)"#" else "."}.mkString+"\n"}.mkString)
```
More readable version, could probably have golfed it more:
```
val a=input.split("\n")
val e=a.map{s=>
    (s.indexOf("#"),s.lastIndexOf("#"))
}.zipWithIndex        // Need the indexes for the Y values
.filter(_._1._1!= -1) // Ugly because of tupleception: (actual tuple, index)
val b=(
    e.map{s=>s._1._1}.min,
    e.map{s=>s._1._2}.max,
    e.head._2,
    e.last._2)
print(
    (0 to a.length-1).map{y=>
        (0 to a(y).length-1).map{x=>
            if(x>=b._1&&x<=b._2&&y>=b._3&&y<=b._4)"#" 
            else "."
        }.mkString+"\n"
    }.mkString
)
```
[Answer]
## JavaScript (ES6), 168 bytes
```
s=>/^#/gm.test(s)?/#$/gm.test(s)?s.replace(/^.*#[^]*#.*$/m,s=>s.replace(/./g,'#'))?f(s.replace(/.$/gm,'')).replace(/$/gm,'.'):f(s.replace(/^./gm,'')).replace(/^/gm,'.')
```
Takes input as a multiline string. Works by recursively stripping leading and trailing `.`s from all lines until at least one line begins and one ends with a `#`, then selects as many lines as possible but starting and finishing on lines containing `#` and changes all the `.`s to `#`. Probably readily golfable.
[Answer]
# R, ~~158~~ 155 bytes
This program takes in input points `.` and hashtags `#`, line by line.
```
v=c();f=which((d=matrix(strsplit(paste0(a<-scan(,""),collapse=""),"")[[1]],nr=sum(a<0),b=T))=="#",a=T);d[min(f[,1]):max(f[,1]),min(f[,2]):max(f[,2])]="#";d
```
**Ungolfed :**
```
a<-scan(,"")             #Input
v=c()                   #Empty vector
f=which((d=(matrix(strsplit(paste0(a,collapse=""),"")[[1]],nr=length(a),b=T)))=="#",a=T) #Main work is here !
d[min(f[,1]):max(f[,1]),min(f[,2]):max(f[,2])]="#"                        #Creates 
                                                                          #the new figure
d                       #Displays it
```
Here are the details of the third line :
```
paste0(a,collapse="") 
#Collapses the input into a single string
strsplit(paste0(a,collapse=""),"")[[1]] 
#Split this string character-wise
matrix(strsplit(paste0(a,collapse=""),"")[[1]],nr=sum(a<0),b=T) 
#Creates and fills (by row) a matrix with number of row the number of line of the input
which((d=(matrix(strsplit(paste0(a,collapse=""),"")[[1]],nr=l,b=T)))=="#",a=T)
#Gives the index of the matrix's elements that are "#"
```
[Answer]
## PowerShell v3+, ~~215~~ ~~162~~ ~~148~~ ~~144~~ 139 bytes
```
param($n)$n|%{(((-join(0..($n[0].length-1)|%{$i=$_;+('1'-in(0..($n.length-1)|%{$n[$_][$i]}))}))-replace'(?<=1.*?).(?=.*?1)',1),$_)[0-ge$_]}
```
Takes input as an array of strings `$n`, with `0` instead of `.` and `1` instead of `#`. Then, we loop through `$n`, each iteration testing whether the current string is smaller than `0` (i.e., there's a `1` in it), and if so, output a string. Uses a [pseudo-ternary](https://codegolf.stackexchange.com/a/79895/42963) in place of an `if`/`else` operation.
The string is constructed from loops through the width of the input string. Each iteration, we tack on a `0` or a `1` depending upon if `1` is found somewhere in the corresponding vertical column. For the last test case, for example, this will result in a string like `0011001001`. Requires v3+ for the `-in` operator. That string is paired with a fancy-dancy regex replace to replace any "inner" `0`s with `1`s. Much thanks to [Business Cat](http://chat.stackexchange.com/transcript/message/31904068#31904068) in chat for the assist on that. Our string would be `0011111111` at this point.
Else, output the current (all-zeros) string `$_`.
The resulting strings are left on the pipeline, and output is implicit. The default `Write-Output` for an array of strings is with a newline between each element, so that's visually what happens.
### Examples
```
PS C:\Tools\Scripts\golfing> .\highlight-the-bounding-box-cartesian.ps1 '0000000001','0010000000','0000100100','0001000000'
0011111111
0011111111
0011111111
0011111111
PS C:\Tools\Scripts\golfing> .\highlight-the-bounding-box-cartesian.ps1 '0000000000','0000000000','0000100000','0001000000'
0000000000
0000000000
0001100000
0001100000
```
[Answer]
# Perl, 51 bytes
Includes +2 for `-0p`
Give input on STDIN, off character is `A`, on character is `a`, e.g.:
```
bounding.pl
AAAAAAAAAA
AAaAAAAAAA
AAAAaAAaAA
AAAaAAAAAA
AAAAAAAAAA
^D
```
`bounding.pl`:
```
#!/usr/bin/perl -0p
s%(?=\D*a).+%$a|=$&%eg;s%.*a.*%$a%g;s/a.*a/\L$&/g
```
Same length:
```
#!/usr/bin/perl -0p
s%.+%${a./a/g}|=$&%eg;s%.*a.*%$a1%g;s/a.*a/\L$&/g
```
[Answer]
# Python, ~~219~~ 212 bytes
```
def b(a):j=len(a[0]);g=range;z=g(len(a));h=[i for i in z if'#'in a[i]];w=[i for i,c in[(i,[r[i]for r in a])for i in g(j)]if'#'in c];return[[any((r<h[0],h[-1]<r,c<w[0],w[-1]<c))and'.'or'#'for c in g(j)]for r in z]
```
(Although I think another method may well be shorter)
Takes and returns a list of list of chars.
Test it on [**ideoone**](http://ideone.com/P7GhYV)
[Answer]
# [Perl 6](http://perl6.org/), 62 bytes
```
{.[.grep(/a/,:k).minmax;$_».grep('a',:k).flat.minmax]='a'xx*}
```
An anonymous routine that can be passed an array of arrays of characters (representing the matrix) as argument, and modifies it in-place so that the calling scope has the modified array afterwards.
Uses `a` instead of `#` as the "on" character. The "off" character can be anything, it doesn't care.
[Answer]
# Python 3, 153 bytes
```
r=lambda w:list(zip(*w[::-1]))
f=lambda w,n=4:list(map(''.join,n and(('#'in w[0])and r(r(r(f(r(w),n-1))))or[w[0]]+foo(w[1:],n))or['#'*len(w[0])]*len(w)))
```
Input and output are a list of strings.
## ungolfed
```
r=lambda w:list(zip(*w[::-1]))   # rotate grid cw 90 degrees
def f(w,n=4):
    if n:
        if '#' in w[0]:
            u = r(r(r(f(r(w), n-1))))
        else:
            u = [w[0]] + foo(w[1:], n)
    else:
        u = ['#'*len(w[0])]*len(w)
 return list(map(''.join,u))
```
## theory of operation
The main idea is to remove rows and columns around the outside of the array if they don't have a '#'. Whatever is left should be filled in with '#'s.
It is implemented using a recursive function.
Case 1: row 0 doesn't contain a '#'. Result is row 0 + recursive call on remaining rows.
Case 2: row 0 does contain a '#'. No more rows can be removed. Rotate array cw so that column 0 is now row 0. Then recursively process the rotated array. The result is rotated ccw.
Base case: The array has been rotated 4 times, meaning that all outer rows/columns have been removed if possible. Whatever remains should be filled in with '#'s
[Answer]
# Python 2, 184 bytes
```
def c(i):
 m=n=();e,z=enumerate,'for j,r in e(i):\n for k,c in e(r):%s'
 exec z%'\n  if"#"==c:m+=j,;n+=k,'
 exec z%'\n  if min(m)<=j<=max(m)<[]>min(n)<=k<=max(n):i[j][k]="#"'
 return i
```
Input and output are a list of strings.
[Try it on Ideone](http://ideone.com/BpKCMq) (fork of Jonathan Allan's test page)
[Answer]
# [Pyth](https://github.com/isaacg1/pyth), 50 bytes
```
L}hbebjuXGhHX@GhHeH\#*yhMJs.e,Lkfq\#@bTUb.zySeMJ.z
```
[Try it online!](http://pyth.herokuapp.com/?code=L%7DhbebjuXGhHX%40GhHeH%5C%23%2ayhMJs.e%2CLkfq%5C%23%40bTUb.zySeMJ.z&input=..........%0A..%23.......%0A....%23..%23..%0A...%23......%0A..........&debug=0)
]