We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
skimage.io.imread returns incorrect dimensions (according to docs)
See here: http://stackoverflow.com/questions/30088841

Importing a TIFF image using skimage.io.imread returns an array with shape (3,M,N) instead of (M,N,3). This breaks the flatten and as_grey features. The results are the same calling `imread` with `plugin='tifffile'`.

```
In [1]: im = skimage.io.imread('image.tif')

In [2]: im.shape
Out[2]: (3, 768, 1024)

In [3]: im = skimage.io.imread('image.tif', as_grey = True)

In [4]: im.shape
Out[4]: (3, 768)

In [5]: im = skimage.io.imread('image.tif', flatten = True)

In [6]: im.shape
Out[6]: (3, 768)
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `skimage/io/_io.py`
Content:
```
1 from io import BytesIO
2 import warnings
3 
4 import numpy as np
5 import six
6 
7 from ..io.manage_plugins import call_plugin
8 from ..color import rgb2grey
9 from .util import file_or_url_context
10 from ..exposure import is_low_contrast
11 from .._shared._warnings import all_warnings
12 
13 
14 __all__ = ['imread', 'imread_collection', 'imsave', 'imshow', 'show']
15 
16 
17 def imread(fname, as_grey=False, plugin=None, flatten=None,
18            **plugin_args):
19     """Load an image from file.
20 
21     Parameters
22     ----------
23     fname : string
24         Image file name, e.g. ``test.jpg`` or URL.
25     as_grey : bool
26         If True, convert color images to grey-scale (32-bit floats).
27         Images that are already in grey-scale format are not converted.
28     plugin : str
29         Name of plugin to use (Python Imaging Library by default).
30 
31     Other Parameters
32     ----------------
33     flatten : bool
34         Backward compatible keyword, superseded by `as_grey`.
35 
36     Returns
37     -------
38     img_array : ndarray
39         The different colour bands/channels are stored in the
40         third dimension, such that a grey-image is MxN, an
41         RGB-image MxNx3 and an RGBA-image MxNx4.
42 
43     Other parameters
44     ----------------
45     plugin_args : keywords
46         Passed to the given plugin.
47 
48     """
49     # Backward compatibility
50     if flatten is not None:
51         as_grey = flatten
52 
53     with file_or_url_context(fname) as fname:
54         img = call_plugin('imread', fname, plugin=plugin, **plugin_args)
55 
56     if as_grey and getattr(img, 'ndim', 0) >= 3:
57         img = rgb2grey(img)
58 
59     return img
60 
61 
62 def imread_collection(load_pattern, conserve_memory=True,
63                       plugin=None, **plugin_args):
64     """
65     Load a collection of images.
66 
67     Parameters
68     ----------
69     load_pattern : str or list
70         List of objects to load. These are usually filenames, but may
71         vary depending on the currently active plugin.  See the docstring
72         for ``ImageCollection`` for the default behaviour of this parameter.
73     conserve_memory : bool, optional
74         If True, never keep more than one in memory at a specific
75         time.  Otherwise, images will be cached once they are loaded.
76 
77     Returns
78     -------
79     ic : ImageCollection
80         Collection of images.
81 
82     Other parameters
83     ----------------
84     plugin_args : keywords
85         Passed to the given plugin.
86 
87     """
88     return call_plugin('imread_collection', load_pattern, conserve_memory,
89                        plugin=plugin, **plugin_args)
90 
91 
92 def imsave(fname, arr, plugin=None, **plugin_args):
93     """Save an image to file.
94 
95     Parameters
96     ----------
97     fname : str
98         Target filename.
99     arr : ndarray of shape (M,N) or (M,N,3) or (M,N,4)
100         Image data.
101     plugin : str
102         Name of plugin to use.  By default, the different plugins are
103         tried (starting with the Python Imaging Library) until a suitable
104         candidate is found.
105 
106     Other parameters
107     ----------------
108     plugin_args : keywords
109         Passed to the given plugin.
110 
111     """
112     if is_low_contrast(arr):
113         warnings.warn('%s is a low contrast image' % fname)
114     return call_plugin('imsave', fname, arr, plugin=plugin, **plugin_args)
115 
116 
117 def imshow(arr, plugin=None, **plugin_args):
118     """Display an image.
119 
120     Parameters
121     ----------
122     arr : ndarray or str
123         Image data or name of image file.
124     plugin : str
125         Name of plugin to use.  By default, the different plugins are
126         tried (starting with the Python Imaging Library) until a suitable
127         candidate is found.
128 
129     Other parameters
130     ----------------
131     plugin_args : keywords
132         Passed to the given plugin.
133 
134     """
135     if isinstance(arr, six.string_types):
136         arr = call_plugin('imread', arr, plugin=plugin)
137     return call_plugin('imshow', arr, plugin=plugin, **plugin_args)
138 
139 
140 def show():
141     '''Display pending images.
142 
143     Launch the event loop of the current gui plugin, and display all
144     pending images, queued via `imshow`. This is required when using
145     `imshow` from non-interactive scripts.
146 
147     A call to `show` will block execution of code until all windows
148     have been closed.
149 
150     Examples
151     --------
152     >>> import skimage.io as io
153 
154     >>> for i in range(4):
155     ...     ax_im = io.imshow(np.random.rand(50, 50))
156     >>> io.show() # doctest: +SKIP
157 
158     '''
159     return call_plugin('_app_show')
160
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/skimage/io/_io.py b/skimage/io/_io.py
--- a/skimage/io/_io.py
+++ b/skimage/io/_io.py
@@ -53,8 +53,16 @@
     with file_or_url_context(fname) as fname:
         img = call_plugin('imread', fname, plugin=plugin, **plugin_args)
 
-    if as_grey and getattr(img, 'ndim', 0) >= 3:
-        img = rgb2grey(img)
+    if not hasattr(img, 'ndim'):
+        return img
+
+    if img.ndim > 2:
+        if img.shape[-1] not in (3, 4) and img.shape[-3] in (3, 4):
+            img = np.swapaxes(img, -1, -3)
+            img = np.swapaxes(img, -2, -3)
+
+        if as_grey:
+            img = rgb2grey(img)
 
     return img

{"golden_diff": "diff --git a/skimage/io/_io.py b/skimage/io/_io.py\n--- a/skimage/io/_io.py\n+++ b/skimage/io/_io.py\n@@ -53,8 +53,16 @@\n     with file_or_url_context(fname) as fname:\n         img = call_plugin('imread', fname, plugin=plugin, **plugin_args)\n \n-    if as_grey and getattr(img, 'ndim', 0) >= 3:\n-        img = rgb2grey(img)\n+    if not hasattr(img, 'ndim'):\n+        return img\n+\n+    if img.ndim > 2:\n+        if img.shape[-1] not in (3, 4) and img.shape[-3] in (3, 4):\n+            img = np.swapaxes(img, -1, -3)\n+            img = np.swapaxes(img, -2, -3)\n+\n+        if as_grey:\n+            img = rgb2grey(img)\n \n     return img\n", "issue": "skimage.io.imread returns incorrect dimensions (according to docs)\nSee here: http://stackoverflow.com/questions/30088841\n\nImporting a TIFF image using skimage.io.imread returns an array with shape (3,M,N) instead of (M,N,3). This breaks the flatten and as_grey features. The results are the same calling `imread` with `plugin='tifffile'`.\n\n```\nIn [1]: im = skimage.io.imread('image.tif')\n\nIn [2]: im.shape\nOut[2]: (3, 768, 1024)\n\nIn [3]: im = skimage.io.imread('image.tif', as_grey = True)\n\nIn [4]: im.shape\nOut[4]: (3, 768)\n\nIn [5]: im = skimage.io.imread('image.tif', flatten = True)\n\nIn [6]: im.shape\nOut[6]: (3, 768)\n```\n\n", "before_files": [{"content": "from io import BytesIO\nimport warnings\n\nimport numpy as np\nimport six\n\nfrom ..io.manage_plugins import call_plugin\nfrom ..color import rgb2grey\nfrom .util import file_or_url_context\nfrom ..exposure import is_low_contrast\nfrom .._shared._warnings import all_warnings\n\n\n__all__ = ['imread', 'imread_collection', 'imsave', 'imshow', 'show']\n\n\ndef imread(fname, as_grey=False, plugin=None, flatten=None,\n           **plugin_args):\n    \"\"\"Load an image from file.\n\n    Parameters\n    ----------\n    fname : string\n        Image file name, e.g. ``test.jpg`` or URL.\n    as_grey : bool\n        If True, convert color images to grey-scale (32-bit floats).\n        Images that are already in grey-scale format are not converted.\n    plugin : str\n        Name of plugin to use (Python Imaging Library by default).\n\n    Other Parameters\n    ----------------\n    flatten : bool\n        Backward compatible keyword, superseded by `as_grey`.\n\n    Returns\n    -------\n    img_array : ndarray\n        The different colour bands/channels are stored in the\n        third dimension, such that a grey-image is MxN, an\n        RGB-image MxNx3 and an RGBA-image MxNx4.\n\n    Other parameters\n    ----------------\n    plugin_args : keywords\n        Passed to the given plugin.\n\n    \"\"\"\n    # Backward compatibility\n    if flatten is not None:\n        as_grey = flatten\n\n    with file_or_url_context(fname) as fname:\n        img = call_plugin('imread', fname, plugin=plugin, **plugin_args)\n\n    if as_grey and getattr(img, 'ndim', 0) >= 3:\n        img = rgb2grey(img)\n\n    return img\n\n\ndef imread_collection(load_pattern, conserve_memory=True,\n                      plugin=None, **plugin_args):\n    \"\"\"\n    Load a collection of images.\n\n    Parameters\n    ----------\n    load_pattern : str or list\n        List of objects to load. These are usually filenames, but may\n        vary depending on the currently active plugin.  See the docstring\n        for ``ImageCollection`` for the default behaviour of this parameter.\n    conserve_memory : bool, optional\n        If True, never keep more than one in memory at a specific\n        time.  Otherwise, images will be cached once they are loaded.\n\n    Returns\n    -------\n    ic : ImageCollection\n        Collection of images.\n\n    Other parameters\n    ----------------\n    plugin_args : keywords\n        Passed to the given plugin.\n\n    \"\"\"\n    return call_plugin('imread_collection', load_pattern, conserve_memory,\n                       plugin=plugin, **plugin_args)\n\n\ndef imsave(fname, arr, plugin=None, **plugin_args):\n    \"\"\"Save an image to file.\n\n    Parameters\n    ----------\n    fname : str\n        Target filename.\n    arr : ndarray of shape (M,N) or (M,N,3) or (M,N,4)\n        Image data.\n    plugin : str\n        Name of plugin to use.  By default, the different plugins are\n        tried (starting with the Python Imaging Library) until a suitable\n        candidate is found.\n\n    Other parameters\n    ----------------\n    plugin_args : keywords\n        Passed to the given plugin.\n\n    \"\"\"\n    if is_low_contrast(arr):\n        warnings.warn('%s is a low contrast image' % fname)\n    return call_plugin('imsave', fname, arr, plugin=plugin, **plugin_args)\n\n\ndef imshow(arr, plugin=None, **plugin_args):\n    \"\"\"Display an image.\n\n    Parameters\n    ----------\n    arr : ndarray or str\n        Image data or name of image file.\n    plugin : str\n        Name of plugin to use.  By default, the different plugins are\n        tried (starting with the Python Imaging Library) until a suitable\n        candidate is found.\n\n    Other parameters\n    ----------------\n    plugin_args : keywords\n        Passed to the given plugin.\n\n    \"\"\"\n    if isinstance(arr, six.string_types):\n        arr = call_plugin('imread', arr, plugin=plugin)\n    return call_plugin('imshow', arr, plugin=plugin, **plugin_args)\n\n\ndef show():\n    '''Display pending images.\n\n    Launch the event loop of the current gui plugin, and display all\n    pending images, queued via `imshow`. This is required when using\n    `imshow` from non-interactive scripts.\n\n    A call to `show` will block execution of code until all windows\n    have been closed.\n\n    Examples\n    --------\n    >>> import skimage.io as io\n\n    >>> for i in range(4):\n    ...     ax_im = io.imshow(np.random.rand(50, 50))\n    >>> io.show() # doctest: +SKIP\n\n    '''\n    return call_plugin('_app_show')\n", "path": "skimage/io/_io.py"}], "after_files": [{"content": "from io import BytesIO\nimport warnings\n\nimport numpy as np\nimport six\n\nfrom ..io.manage_plugins import call_plugin\nfrom ..color import rgb2grey\nfrom .util import file_or_url_context\nfrom ..exposure import is_low_contrast\nfrom .._shared._warnings import all_warnings\n\n\n__all__ = ['imread', 'imread_collection', 'imsave', 'imshow', 'show']\n\n\ndef imread(fname, as_grey=False, plugin=None, flatten=None,\n           **plugin_args):\n    \"\"\"Load an image from file.\n\n    Parameters\n    ----------\n    fname : string\n        Image file name, e.g. ``test.jpg`` or URL.\n    as_grey : bool\n        If True, convert color images to grey-scale (32-bit floats).\n        Images that are already in grey-scale format are not converted.\n    plugin : str\n        Name of plugin to use (Python Imaging Library by default).\n\n    Other Parameters\n    ----------------\n    flatten : bool\n        Backward compatible keyword, superseded by `as_grey`.\n\n    Returns\n    -------\n    img_array : ndarray\n        The different colour bands/channels are stored in the\n        third dimension, such that a grey-image is MxN, an\n        RGB-image MxNx3 and an RGBA-image MxNx4.\n\n    Other parameters\n    ----------------\n    plugin_args : keywords\n        Passed to the given plugin.\n\n    \"\"\"\n    # Backward compatibility\n    if flatten is not None:\n        as_grey = flatten\n\n    with file_or_url_context(fname) as fname:\n        img = call_plugin('imread', fname, plugin=plugin, **plugin_args)\n\n    if not hasattr(img, 'ndim'):\n        return img\n\n    if img.ndim > 2:\n        if img.shape[-1] not in (3, 4) and img.shape[-3] in (3, 4):\n            img = np.swapaxes(img, -1, -3)\n            img = np.swapaxes(img, -2, -3)\n\n        if as_grey:\n            img = rgb2grey(img)\n\n    return img\n\n\ndef imread_collection(load_pattern, conserve_memory=True,\n                      plugin=None, **plugin_args):\n    \"\"\"\n    Load a collection of images.\n\n    Parameters\n    ----------\n    load_pattern : str or list\n        List of objects to load. These are usually filenames, but may\n        vary depending on the currently active plugin.  See the docstring\n        for ``ImageCollection`` for the default behaviour of this parameter.\n    conserve_memory : bool, optional\n        If True, never keep more than one in memory at a specific\n        time.  Otherwise, images will be cached once they are loaded.\n\n    Returns\n    -------\n    ic : ImageCollection\n        Collection of images.\n\n    Other parameters\n    ----------------\n    plugin_args : keywords\n        Passed to the given plugin.\n\n    \"\"\"\n    return call_plugin('imread_collection', load_pattern, conserve_memory,\n                       plugin=plugin, **plugin_args)\n\n\ndef imsave(fname, arr, plugin=None, **plugin_args):\n    \"\"\"Save an image to file.\n\n    Parameters\n    ----------\n    fname : str\n        Target filename.\n    arr : ndarray of shape (M,N) or (M,N,3) or (M,N,4)\n        Image data.\n    plugin : str\n        Name of plugin to use.  By default, the different plugins are\n        tried (starting with the Python Imaging Library) until a suitable\n        candidate is found.\n\n    Other parameters\n    ----------------\n    plugin_args : keywords\n        Passed to the given plugin.\n\n    \"\"\"\n    if is_low_contrast(arr):\n        warnings.warn('%s is a low contrast image' % fname)\n    return call_plugin('imsave', fname, arr, plugin=plugin, **plugin_args)\n\n\ndef imshow(arr, plugin=None, **plugin_args):\n    \"\"\"Display an image.\n\n    Parameters\n    ----------\n    arr : ndarray or str\n        Image data or name of image file.\n    plugin : str\n        Name of plugin to use.  By default, the different plugins are\n        tried (starting with the Python Imaging Library) until a suitable\n        candidate is found.\n\n    Other parameters\n    ----------------\n    plugin_args : keywords\n        Passed to the given plugin.\n\n    \"\"\"\n    if isinstance(arr, six.string_types):\n        arr = call_plugin('imread', arr, plugin=plugin)\n    return call_plugin('imshow', arr, plugin=plugin, **plugin_args)\n\n\ndef show():\n    '''Display pending images.\n\n    Launch the event loop of the current gui plugin, and display all\n    pending images, queued via `imshow`. This is required when using\n    `imshow` from non-interactive scripts.\n\n    A call to `show` will block execution of code until all windows\n    have been closed.\n\n    Examples\n    --------\n    >>> import skimage.io as io\n\n    >>> for i in range(4):\n    ...     ax_im = io.imshow(np.random.rand(50, 50))\n    >>> io.show() # doctest: +SKIP\n\n    '''\n    return call_plugin('_app_show')\n", "path": "skimage/io/_io.py"}]}