Repository: scikit-image/scikit-image

Issue:
`skimage.filters.gaussian` doesn't use `output` parameter at all
## Description
`skimage.filters.gaussian` doesn't use the value of `output` parameter. It returns only the image of float64 dtype, even if explicitly specify the output dtype. 

## Way to reproduce
Simply run the code snippet:
```python
from skimage.filters import gaussian
import numpy as np

image = np.arange(25, dtype=np.uint8).reshape((5,5))

# output is not specified
filtered_0 = gaussian(image, sigma=0.25)
print(filtered_0.dtype)
# return: float64

# output is specified
filtered_output = gaussian(image, output = np.uint8, sigma=0.25)
print(filtered_output.dtype)
# return: float64
```
This function is a wrapper around `scipy.ndi.gaussian_filter`. But the scikit-image `gaussian` doesn't pass the `output` to `scipy.ndi.gaussian_filter`.


`skimage.filters.gaussian` doesn't use `output` parameter at all
## Description
`skimage.filters.gaussian` doesn't use the value of `output` parameter. It returns only the image of float64 dtype, even if explicitly specify the output dtype. 

## Way to reproduce
Simply run the code snippet:
```python
from skimage.filters import gaussian
import numpy as np

image = np.arange(25, dtype=np.uint8).reshape((5,5))

# output is not specified
filtered_0 = gaussian(image, sigma=0.25)
print(filtered_0.dtype)
# return: float64

# output is specified
filtered_output = gaussian(image, output = np.uint8, sigma=0.25)
print(filtered_output.dtype)
# return: float64
```
This function is a wrapper around `scipy.ndi.gaussian_filter`. But the scikit-image `gaussian` doesn't pass the `output` to `scipy.ndi.gaussian_filter`.




Discussion:
Indeed this is a bug. Would you like to provide the patch in a PR that would:
1. Remedy this issue?
2. Add a test so that it doesn't get reintroduced as a bug in the future?
Yes, I would. I think i can investigate it
Indeed this is a bug. Would you like to provide the patch in a PR that would:
1. Remedy this issue?
2. Add a test so that it doesn't get reintroduced as a bug in the future?
Yes, I would. I think i can investigate it

Resolving patch:
diff --git a/skimage/filters/_gaussian.py b/skimage/filters/_gaussian.py
--- a/skimage/filters/_gaussian.py
+++ b/skimage/filters/_gaussian.py
@@ -57,6 +57,10 @@ def gaussian(image, sigma=1, output=None, mode='nearest', cval=0,
 
     Integer arrays are converted to float.
 
+    The ``output`` should be floating point data type since gaussian converts
+    to float provided ``image``. If ``output`` is not provided, another array
+    will be allocated and returned as the result.
+
     The multi-dimensional filter is implemented as a sequence of
     one-dimensional convolution filters. The intermediate arrays are
     stored in the same data type as the output. Therefore, for output
@@ -113,8 +117,13 @@ def gaussian(image, sigma=1, output=None, mode='nearest', cval=0,
         if len(sigma) != image.ndim:
             sigma = np.concatenate((np.asarray(sigma), [0]))
     image = convert_to_float(image, preserve_range)
-    return ndi.gaussian_filter(image, sigma, mode=mode, cval=cval,
-                               truncate=truncate)
+    if output is None:
+        output = np.empty_like(image)
+    elif not np.issubdtype(output.dtype, np.floating):
+        raise ValueError("Provided output data type is not float")
+    ndi.gaussian_filter(image, sigma, output=output, mode=mode, cval=cval,
+                        truncate=truncate)
+    return output
 
 
 def _guess_spatial_dimensions(image):


Test patch:
diff --git a/skimage/filters/tests/test_gaussian.py b/skimage/filters/tests/test_gaussian.py
--- a/skimage/filters/tests/test_gaussian.py
+++ b/skimage/filters/tests/test_gaussian.py
@@ -1,3 +1,5 @@
+import pytest
+
 import numpy as np
 from skimage.filters._gaussian import gaussian, _guess_spatial_dimensions
 from skimage._shared import testing
@@ -82,3 +84,22 @@ def test_guess_spatial_dimensions():
     testing.assert_equal(_guess_spatial_dimensions(im4), 3)
     with testing.raises(ValueError):
         _guess_spatial_dimensions(im5)
+
+
+@pytest.mark.parametrize(
+    "dtype", [np.float32, np.float64]
+)
+def test_preserve_output(dtype):
+    image = np.arange(9, dtype=dtype).reshape((3, 3))
+    output = np.zeros_like(image, dtype=dtype)
+    gaussian_image = gaussian(image, sigma=1, output=output,
+                              preserve_range=True)
+    assert gaussian_image is output
+
+
+def test_output_error():
+    image = np.arange(9, dtype=np.float32).reshape((3, 3))
+    output = np.zeros_like(image, dtype=np.uint8)
+    with pytest.raises(ValueError):
+        gaussian(image, sigma=1, output=output,
+                 preserve_range=True)