def compute_chunksize(src, w, h, chunksize=None, max_mem=None):
    """
    Attempts to compute a chunksize for the resampling output array
    that is as close as possible to the input array chunksize, while
    also respecting the maximum memory constraint to avoid loading
    to much data into memory at the same time.

    Parameters
    ----------
    src : dask.array.Array
        The source array to resample
    w : int
        New grid width
    h : int
        New grid height
    chunksize : tuple(int, int) (optional)
        Size of the output chunks. By default the chunk size is
        inherited from the *src* array.
    max_mem : int (optional)
        The maximum number of bytes that should be loaded into memory
        during the regridding operation.

    Returns
    -------
    chunksize : tuple(int, int)
        Size of the output chunks.
    """
    start_chunksize = src.chunksize if chunksize is None else chunksize
    if max_mem is None:
        return start_chunksize
    sh, sw = src.shape
    height_fraction = float(sh) / h
    width_fraction = float(sw) / w
    ch, cw = start_chunksize
    dim = True
    nbytes = src.dtype.itemsize
    while ch * height_fraction * (cw * width_fraction) * nbytes > max_mem:
        if dim:
            cw -= 1
        else:
            ch -= 1
        dim = not dim
    if ch == 0 or cw == 0:
        min_mem = height_fraction * width_fraction * nbytes
        raise ValueError(
            'Given the memory constraints the resampling operation could not find a chunksize that avoids loading too much data into memory. Either relax the memory constraint to a minimum of %d bytes or resample to a larger grid size. Note: A future implementation could handle this condition by declaring temporary arrays.'
             % min_mem)
    return ch, cw
