<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def fromarray(values, labels=None, npartitions=None, engine=None):
 """ Load images from an array. First dimension will be used to index images, so remaining dimensions after the first should be the dimensions of the images, e.g. (3, 100, 200) for 3 x (100, 200) images Parameters values : array-like The array of images. Can be a numpy array, a bolt array, or an array-like. labels : array, optional, default = None Labels for records. If provided, should be one-dimensional. npartitions : int, default = None Number of partitions for parallelization (spark only) engine : object, default = None Computational engine (e.g. a SparkContext for spark) """

    from .images import Images
    import bolt

    if isinstance(values, bolt.spark.array.BoltArraySpark):
        return Images(values)

    values = asarray(values)

    if values.ndim < 2:
        raise ValueError('Array for images must have at least 2 dimensions, got %g' % values.ndim)

    if values.ndim == 2:
        values = expand_dims(values, 0)

    shape = None
    dtype = None
    for im in values:
        if shape is None:
            shape = im.shape
            dtype = im.dtype
        if not im.shape == shape:
            raise ValueError('Arrays must all be of same shape; got both %s and %s' %
                             (str(shape), str(im.shape)))
        if not im.dtype == dtype:
            raise ValueError('Arrays must all be of same data type; got both %s and %s' %
                             (str(dtype), str(im.dtype)))

    if spark and isinstance(engine, spark):
        if not npartitions:
            npartitions = engine.defaultParallelism
        values = bolt.array(values, context=engine, npartitions=npartitions, axis=(0,))
        values._ordered = True
        return Images(values)

    return Images(values, labels=labels)