prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Additional improvement for da.image.imread
  I think following 2 improvements make the function better.
  #### 1. Allow custom `imread` function.
  
  Some prefer `opencv` which reads color in BGR order, otherwise `skimage` reads in RGB order. Adding `dialect` option (like `dialect='skimage'` or `dialect='cv'`) or accept different file read function may better.
  #### 2. Allow custom preprocessing function.
  
  In image processing, input images may have different sizes. In these case, preprocessing is needed between image read and array creation. This preprocessing function must return the same size of array on user's responsibility.
  
  
  </issue>
  <code>
  [start of dask/array/image.py]
  1 from glob import glob
  2 import os
  3 
  4 try:
  5     from skimage.io import imread as sk_imread
  6 except ImportError:
  7     pass
  8 
  9 from .core import Array
  10 from ..base import tokenize
  11 
  12 def add_leading_dimension(x):
  13     return x[None, ...]
  14 
  15 
  16 def imread(filename):
  17     """ Read a stack of images into a dask array
  18 
  19     Parameters
  20     ----------
  21 
  22     filename: string
  23         A globstring like 'myfile.*.png'
  24 
  25     Example
  26     -------
  27 
  28     >>> from dask.array.image import imread
  29     >>> im = imread('2015-*-*.png')  # doctest: +SKIP
  30     >>> im.shape  # doctest: +SKIP
  31     (365, 1000, 1000, 3)
  32 
  33     Returns
  34     -------
  35 
  36     Dask array of all images stacked along the first dimension.  All images
  37     will be treated as individual chunks
  38     """
  39     filenames = sorted(glob(filename))
  40     if not filenames:
  41         raise ValueError("No files found under name %s" % filename)
  42 
  43     name = 'imread-%s' % tokenize(filenames, map(os.path.getmtime, filenames))
  44 
  45     sample = sk_imread(filenames[0])
  46 
  47     dsk = dict(((name, i) + (0,) * len(sample.shape),
  48                 (add_leading_dimension, (sk_imread, filename)))
  49                 for i, filename in enumerate(filenames))
  50 
  51     chunks = ((1,) * len(filenames),) + tuple((d,) for d in sample.shape)
  52 
  53     return Array(dsk, name, chunks, sample.dtype)
  54
  [end of dask/array/image.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/dask/array/image.py b/dask/array/image.py
  --- a/dask/array/image.py
  +++ b/dask/array/image.py
  @@ -13,7 +13,7 @@
       return x[None, ...]
   
   
  -def imread(filename):
  +def imread(filename, imread=None, preprocess=None):
       """ Read a stack of images into a dask array
   
       Parameters
  @@ -21,6 +21,13 @@
   
       filename: string
           A globstring like 'myfile.*.png'
  +    imread: function (optional)
  +        Optionally provide custom imread function.
  +        Function should expect a filename and produce a numpy array.
  +        Defaults to ``skimage.io.imread``.
  +    preprocess: function (optional)
  +        Optionally provide custom function to preprocess the image.
  +        Function should expect a numpy array for a single image.
   
       Example
       -------
  @@ -36,17 +43,25 @@
       Dask array of all images stacked along the first dimension.  All images
       will be treated as individual chunks
       """
  +    imread = imread or sk_imread
       filenames = sorted(glob(filename))
       if not filenames:
           raise ValueError("No files found under name %s" % filename)
   
       name = 'imread-%s' % tokenize(filenames, map(os.path.getmtime, filenames))
   
  -    sample = sk_imread(filenames[0])
  -
  -    dsk = dict(((name, i) + (0,) * len(sample.shape),
  -                (add_leading_dimension, (sk_imread, filename)))
  -                for i, filename in enumerate(filenames))
  +    sample = imread(filenames[0])
  +    if preprocess:
  +        sample = preprocess(sample)
  +
  +    keys = [(name, i) + (0,) * len(sample.shape) for i in range(len(filenames))]
  +    if preprocess:
  +        values = [(add_leading_dimension, (preprocess, (imread, filename)))
  +                  for filename in filenames]
  +    else:
  +        values = [(add_leading_dimension, (imread, filename))
  +                  for filename in filenames]
  +    dsk = dict(zip(keys, values))
   
       chunks = ((1,) * len(filenames),) + tuple((d,) for d in sample.shape)
  
verification_info: {"golden_diff": "diff --git a/dask/array/image.py b/dask/array/image.py\n--- a/dask/array/image.py\n+++ b/dask/array/image.py\n@@ -13,7 +13,7 @@\n     return x[None, ...]\n \n \n-def imread(filename):\n+def imread(filename, imread=None, preprocess=None):\n     \"\"\" Read a stack of images into a dask array\n \n     Parameters\n@@ -21,6 +21,13 @@\n \n     filename: string\n         A globstring like 'myfile.*.png'\n+    imread: function (optional)\n+        Optionally provide custom imread function.\n+        Function should expect a filename and produce a numpy array.\n+        Defaults to ``skimage.io.imread``.\n+    preprocess: function (optional)\n+        Optionally provide custom function to preprocess the image.\n+        Function should expect a numpy array for a single image.\n \n     Example\n     -------\n@@ -36,17 +43,25 @@\n     Dask array of all images stacked along the first dimension.  All images\n     will be treated as individual chunks\n     \"\"\"\n+    imread = imread or sk_imread\n     filenames = sorted(glob(filename))\n     if not filenames:\n         raise ValueError(\"No files found under name %s\" % filename)\n \n     name = 'imread-%s' % tokenize(filenames, map(os.path.getmtime, filenames))\n \n-    sample = sk_imread(filenames[0])\n-\n-    dsk = dict(((name, i) + (0,) * len(sample.shape),\n-                (add_leading_dimension, (sk_imread, filename)))\n-                for i, filename in enumerate(filenames))\n+    sample = imread(filenames[0])\n+    if preprocess:\n+        sample = preprocess(sample)\n+\n+    keys = [(name, i) + (0,) * len(sample.shape) for i in range(len(filenames))]\n+    if preprocess:\n+        values = [(add_leading_dimension, (preprocess, (imread, filename)))\n+                  for filename in filenames]\n+    else:\n+        values = [(add_leading_dimension, (imread, filename))\n+                  for filename in filenames]\n+    dsk = dict(zip(keys, values))\n \n     chunks = ((1,) * len(filenames),) + tuple((d,) for d in sample.shape)\n", "issue": "Additional improvement for da.image.imread\nI think following 2 improvements make the function better.\n#### 1. Allow custom `imread` function.\n\nSome prefer `opencv` which reads color in BGR order, otherwise `skimage` reads in RGB order. Adding `dialect` option (like `dialect='skimage'` or `dialect='cv'`) or accept different file read function may better.\n#### 2. Allow custom preprocessing function.\n\nIn image processing, input images may have different sizes. In these case, preprocessing is needed between image read and array creation. This preprocessing function must return the same size of array on user's responsibility.\n\n", "before_files": [{"content": "from glob import glob\nimport os\n\ntry:\n    from skimage.io import imread as sk_imread\nexcept ImportError:\n    pass\n\nfrom .core import Array\nfrom ..base import tokenize\n\ndef add_leading_dimension(x):\n    return x[None, ...]\n\n\ndef imread(filename):\n    \"\"\" Read a stack of images into a dask array\n\n    Parameters\n    ----------\n\n    filename: string\n        A globstring like 'myfile.*.png'\n\n    Example\n    -------\n\n    >>> from dask.array.image import imread\n    >>> im = imread('2015-*-*.png')  # doctest: +SKIP\n    >>> im.shape  # doctest: +SKIP\n    (365, 1000, 1000, 3)\n\n    Returns\n    -------\n\n    Dask array of all images stacked along the first dimension.  All images\n    will be treated as individual chunks\n    \"\"\"\n    filenames = sorted(glob(filename))\n    if not filenames:\n        raise ValueError(\"No files found under name %s\" % filename)\n\n    name = 'imread-%s' % tokenize(filenames, map(os.path.getmtime, filenames))\n\n    sample = sk_imread(filenames[0])\n\n    dsk = dict(((name, i) + (0,) * len(sample.shape),\n                (add_leading_dimension, (sk_imread, filename)))\n                for i, filename in enumerate(filenames))\n\n    chunks = ((1,) * len(filenames),) + tuple((d,) for d in sample.shape)\n\n    return Array(dsk, name, chunks, sample.dtype)\n", "path": "dask/array/image.py"}]}