Exemple #1
0
def test_getbbox_no_args():
    # Arrange
    p = ImagePath.Path([0, 1, 2, 3])

    # Act / Assert
    with pytest.raises(TypeError):
        p.getbbox(1)
Exemple #2
0
def test_invalid_coords():
    # Arrange
    coords = ["a", "b"]

    # Act / Assert
    with pytest.raises(SystemError):
        ImagePath.Path(coords)
Exemple #3
0
def test_path():

    p = ImagePath.Path(list(range(10)))

    # sequence interface
    assert_equal(len(p), 5)
    assert_equal(p[0], (0.0, 1.0))
    assert_equal(p[-1], (8.0, 9.0))
    assert_equal(list(p[:1]), [(0.0, 1.0)])
    assert_equal(list(p), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0),
                           (8.0, 9.0)])

    # method sanity check
    assert_equal(p.tolist(), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0),
                              (8.0, 9.0)])
    assert_equal(p.tolist(1),
                 [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])

    assert_equal(p.getbbox(), (0.0, 1.0, 8.0, 9.0))

    assert_equal(p.compact(5), 2)
    assert_equal(list(p), [(0.0, 1.0), (4.0, 5.0), (8.0, 9.0)])

    p.transform((1, 0, 1, 0, 1, 1))
    assert_equal(list(p), [(1.0, 2.0), (5.0, 6.0), (9.0, 10.0)])

    # alternative constructors
    p = ImagePath.Path([0, 1])
    assert_equal(list(p), [(0.0, 1.0)])
    p = ImagePath.Path([0.0, 1.0])
    assert_equal(list(p), [(0.0, 1.0)])
    p = ImagePath.Path([0, 1])
    assert_equal(list(p), [(0.0, 1.0)])
    p = ImagePath.Path([(0, 1)])
    assert_equal(list(p), [(0.0, 1.0)])
    p = ImagePath.Path(p)
    assert_equal(list(p), [(0.0, 1.0)])
    p = ImagePath.Path(p.tolist(0))
    assert_equal(list(p), [(0.0, 1.0)])
    p = ImagePath.Path(p.tolist(1))
    assert_equal(list(p), [(0.0, 1.0)])
    p = ImagePath.Path(array.array("f", [0, 1]))
    assert_equal(list(p), [(0.0, 1.0)])
    p = ImagePath.Path(array.array("f", [0, 1]).tostring())
    assert_equal(list(p), [(0.0, 1.0)])
Exemple #4
0
def test_path_odd_number_of_coordinates():
    # Arrange
    coords = [0]

    # Act / Assert
    with pytest.raises(ValueError) as e:
        ImagePath.Path(coords)

    assert str(e.value) == "wrong number of coordinates"
Exemple #5
0
def test_invalid_coords():
    # Arrange
    coords = ["a", "b"]

    # Act / Assert
    with pytest.raises(ValueError) as e:
        ImagePath.Path(coords)

    assert str(e.value) == "incorrect coordinate type"
Exemple #6
0
def test_map(coords, expected):
    # Arrange
    p = ImagePath.Path(coords)

    # Act
    # Modifies the path in-place
    p.map(lambda x, y: (x * 2, y * 3))

    # Assert
    assert list(p) == expected
Exemple #7
0
def draw_linestring(draw_ctx, antialias, color, linestring, merc_center, zoom,
                    img_size):
    vectors = []

    for point in linestring:
        coord = Coords(point[0], point[1])
        merc_point = transform_to_mercator(coord, zoom)
        img_coord = convert_to_img_coords(merc_center, merc_point, img_size, 1)
        vectors.append((img_coord[0] * antialias, img_coord[1] * antialias))

    draw_ctx.line(ImagePath.Path(vectors), color, 10)
def cropImage(imgPath, label, coordinates):
    if len(coordinates) != 0:
        pixels = []
        for coordinate in coordinates:
            x = (float)(coordinate.split(',')[0])
            y = (float)(coordinate.split(',')[1])
            pixels.append((x, y))
        im = Image.open(imgPath)
        contour = ImagePath.Path(pixels)
        minimalBound = contour.getbbox()
        im = im.crop(minimalBound)
        im.save(imgPath)
Exemple #9
0
def test_transform():
    # Arrange
    p = ImagePath.Path([0, 1, 2, 3])
    theta = math.pi / 15

    # Act
    # Affine transform, in-place
    p.transform((math.cos(theta), math.sin(theta), 20, -math.sin(theta),
                 math.cos(theta), 20), )

    # Assert
    assert p.tolist() == [
        (20.20791169081776, 20.978147600733806),
        (22.58003027392089, 22.518619420565898),
    ]
	def __init__(self, population_size, polygon_number, original_image):
		self.max_coordinate = min(original_image.size[0], original_image.size[1])
		self.coordinate_range = [original_image.size[0], original_image.size[1]]
		self.original_image = original_image.convert('RGBA')
		self.original_image_array = np.array(original_image)
		self.size = original_image.size
		self.candidate_array = np.zeros((self.size[0], self.size[1], 4))
		self.population_size = population_size
		self.polygon_number = polygon_number
		self.mutation_rate = 0.5

		new_image = ImagePath.Path(((0,0),(0,self.coordinate_range[1]),(self.coordinate_range[0],self.coordinate_range[1]),(self.coordinate_range[0],0))).getbbox()  #hardcoded for MonaLisa pic
		size = list(map(int, map(math.ceil, new_image[2:]))) 
		self.test_img = Image.new("RGBA", size)  
		self.background = Image.new("RGBA", size, (255,0,0,0))
		self.random_initialization(population_size, polygon_number)
Exemple #11
0
def make_object(N, min_indexes, max_indexes):
    """
        returns:
            amplitude, phase
            both with normalized values between 0 and 1

    """
    # must be divisible by 4
    assert N % 4 == 0
    obj = np.zeros((N, N), dtype=np.complex128)

    min_x = N / 4 + 1
    min_y = N / 4 + 1
    max_x = N - N / 4 - 1
    max_y = N - N / 4 - 1

    # generate random indexes
    # np.random.seed(3367)
    indexes_n = np.random.randint(min_indexes, max_indexes)
    # for each index generate an x and y point
    x = []
    y = []
    for i in range(indexes_n):

        x_val = min_x + np.random.rand(1) * (max_x - min_x)
        y_val = min_y + np.random.rand(1) * (max_y - min_y)

        x.append(int(x_val))
        y.append(int(y_val))

    x.append(x[0])
    y.append(y[0])

    xy = [(x_, y_) for x_, y_ in zip(x, y)]
    image = ImagePath.Path(xy).getbbox()
    size = list(map(int, map(math.ceil, image[2:])))
    img = Image.new("RGB", [N, N], "#000000")
    img1 = ImageDraw.Draw(img)
    img1.polygon(xy, fill="#ffffff")
    # convert to numpy array
    amplitude = np.array(img.getdata(), dtype=np.uint8).reshape(N, N, -1)
    amplitude = np.sum(amplitude, axis=2)
    amplitude = amplitude / np.max(amplitude)

    # apply gaussian filter
    amplitude = gaussian_filter(amplitude, sigma=0.8, order=0)
    return amplitude
Exemple #12
0
def test_transform_with_wrap():
    # Arrange
    p = ImagePath.Path([0, 1, 2, 3])
    theta = math.pi / 15

    # Act
    # Affine transform, in-place, with wrap parameter
    p.transform(
        (math.cos(theta), math.sin(theta), 20, -math.sin(theta), math.cos(theta), 20),
        1.0,
    )

    # Assert
    assert p.tolist() == [
        (0.20791169081775962, 20.978147600733806),
        (0.5800302739208902, 22.518619420565898),
    ]
Exemple #13
0
def coordinate():
    side = random.randint(3, 6)
    # 坐标加1把单位圆从原点移动到第一象限
    xy = [(math.cos(th) + 1, math.sin(th) + 1)
          for th in [s * (2 * math.pi) / side for s in range(side)]]

    loc, scale = 75, 10
    x_scale, y_scale = random.normal(loc, scale), random.normal(loc, scale)
    x_shift, y_shift = random.uniform(0, 800), random.uniform(0, 800)
    xy = list(
        map(
            lambda coords:
            (coords[0] * x_scale + x_shift, coords[1] * y_scale + y_shift),
            xy))
    if random.randn() > 0.25:
        return ImagePath.Path(xy).getbbox()
    return xy
Exemple #14
0
    def drawPatch(self, pos, turn, invert, type, draw, size, foreColor,
                  backColor):
        """
        @param size patch size
        """
        path = self.PATH_SET[type]
        if not path:
            # blank patch
            invert = not invert
            path = [(0., 0.), (1., 0.), (1., 1.), (0., 1.), (0., 0.)]
        patch = ImagePath.Path(path)
        if invert:
            foreColor, backColor = backColor, foreColor

        mat = Matrix2D.rotateSquare(turn, pivot=(0.5, 0.5)) * \
            Matrix2D.translate(*pos) * \
            Matrix2D.scale(size, size)

        patch.transform(mat.for_PIL())
        draw.rectangle((pos[0] * size, pos[1] * size, (pos[0] + 1) * size,
                        (pos[1] + 1) * size), fill=backColor)
        draw.polygon(patch, fill=foreColor, outline=foreColor)
Exemple #15
0
 def render(self, op, xy, pen, brush=None):
     # handle color arguments
     outline = fill = None
     width = 1
     if isinstance(pen, Pen):
         outline = pen.color
         width = pen.width
     elif isinstance(brush, Pen):
         outline = brush.color
         width = brush.width
     if isinstance(brush, Brush):
         fill = brush.color
     elif isinstance(pen, Brush):
         fill = pen.color
     # handle transformation
     if self.transform:
         xy = ImagePath.Path(xy)
         xy.transform(self.transform)
     # render the item
     if op == "line":
         self.draw.line(xy, fill=outline, width=width)
     else:
         getattr(self.draw, op)(xy, fill=fill, outline=outline)
Exemple #16
0
def test_getbbox(coords, expected):
    # Arrange
    p = ImagePath.Path(coords)

    # Act / Assert
    assert p.getbbox() == expected
Exemple #17
0
    def as_raster(self, *args):
        '''
        Group 1:
            Variant 1:
                refraster, pixeltype, [value=1, nodataval=0]
        Group 2:
            Variant 2:
                ...
            Variant 3:
                scalex, scaley, pixeltype, [value=1, nodataval=0, upperleftx=NULL, upperlefty=NULL, skewx=0, skewy=0]
        Group 3:
            Variant 4:
                ...
            Variant 5:
                width, height, pixeltype, [value=1, nodataval=0, upperleftx=NULL, upperlefty=NULL, skewx=0, skewy=0
        '''
        from ..raster.raster import Raster, make_empty_raster

        # parse args
        def getarg(args, pos, default):
            if len(args) >= (pos+1):
                val = args[pos]
                if val is None:
                    val = default
            else:
                val = default
            return val
            
        # GROUP 1: existing raster
        if not isinstance(args[0], (float,int)):
            # raster ref, text pixeltype, double precision value=1, double precision nodataval=0, boolean touched=false
            if isinstance(args[0], Raster):
                ref = args[0]
            else:
                ref = Raster(args[0])
            pixeltype = args[1]
            value = getarg(args, 2, 1) 
            nodataval = getarg(args, 3, 0)
            
        # GROUP 2: set params, autocalc width/height
        elif isinstance(args[0], float) and isinstance(args[2], float):
##            # double precision scalex, double precision scaley, double precision gridx, double precision gridy, text pixeltype, double precision value=1, double precision nodataval=0, double precision skewx=0, double precision skewy=0, boolean touched=false
##            # aligns upperleft to gridx/y
            scaleX,scaleY,gridX,gridY = args[:4]
            pixeltype = args[4]
            value = getarg(args, 5, 1) 
            nodataval = getarg(args, 6, 0) 
            skewX = getarg(args, 7, 0.0) 
            skewY = getarg(args, 8, 0.0)

            xmin,ymin,xmax,ymax = self.bbox()
            width = abs(xmax-xmin) / float(scaleX)
            height = abs(ymax-ymin) / float(scaleY)
            width = int(round(abs(width)))
            height = int(round(abs(height)))

            from affine import Affine
            upperLeftX = xmin if scaleX > 0 else xmax
            upperLeftY = ymin if scaleY > 0 else ymax
            aff = Affine(scaleX,skewX,upperLeftX, skewY,scaleY,upperLeftY)
            gridCol,gridRow = (~aff) * (gridX,gridY) # predict pixel of gridx,gridy
            gridX2,gridY2 = aff * (math.floor(gridCol), math.floor(gridRow)) # use whole pixel to predict gridx,gridy
            upperLeftX,upperLeftY = upperLeftX - (gridX2-gridX), upperLeftY - (gridY2-gridY) # use actual and predicted gridx,gridy to adjust upperleft geom extent

            #print 'bbox',xmin,ymin,xmax,ymax
            #print 'grid align',gridX,gridY,gridCol,gridRow,gridX2,gridY2
            #print 'asrast params',width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY
            
            ref = make_empty_raster(width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY)
            
        elif isinstance(args[0], float) and isinstance(args[2], basestring):
            # double precision scalex, double precision scaley, text pixeltype, double precision value=1, double precision nodataval=0, double precision upperleftx=NULL, double precision upperlefty=NULL, double precision skewx=0, double precision skewy=0, boolean touched=false
            # uses upperleft
            scaleX,scaleY,pixeltype = args[:3]
            value = getarg(args, 3, 1) 
            nodataval = getarg(args, 4, 0) 
            xmin,ymin,xmax,ymax = self.bbox()
            upperLeftX = getarg(args, 5, xmin) 
            upperLeftY = getarg(args, 6, ymax) # flipped y by default
            skewX = getarg(args, 7, 0.0) 
            skewY = getarg(args, 8, 0.0) 
            width = abs(xmax-xmin) / float(scaleX)
            height = abs(ymax-ymin) / float(scaleY)
            width = int(round(abs(width)))
            height = int(round(abs(height)))
            
            ref = make_empty_raster(width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY)
            
        # GROUP 3: set width/height, autocalc params
        elif isinstance(args[0], int) and isinstance(args[2], float):
            # integer width, integer height, double precision gridx, double precision gridy, text pixeltype, double precision value=1, double precision nodataval=0, double precision skewx=0, double precision skewy=0, boolean touched=false
            # aligns upperleft to gridx/y            
            width,height,gridX,gridY = args[:4]
            pixeltype = args[4]
            value = getarg(args, 5, 1) 
            nodataval = getarg(args, 6, 0) 
            skewX = getarg(args, 7, 0.0) 
            skewY = getarg(args, 8, 0.0)

            xmin,ymin,xmax,ymax = self.bbox()
            scaleX = abs(xmax-xmin) / float(width)
            scaleY = abs(ymax-ymin) / float(height) * -1 # flipped y by default (since we only width,height,upperleft, no way to know what direction crs goes)

            from affine import Affine
            upperLeftX = xmin if scaleX > 0 else xmax
            upperLeftY = ymin if scaleY > 0 else ymax
            aff = Affine(scaleX,skewX,upperLeftX, skewY,scaleY,upperLeftY)
            gridCol,gridRow = (~aff) * (gridX,gridY) # predict pixel of gridx,gridy
            gridX2,gridY2 = aff * (math.floor(gridCol), math.floor(gridRow)) # use whole pixel to predict gridx,gridy
            upperLeftX,upperLeftY = upperLeftX - (gridX2-gridX), upperLeftY - (gridY2-gridY) # use actual and predicted gridx,gridy to adjust upperleft geom extent

            ref = make_empty_raster(width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY)

        elif isinstance(args[0], int) and isinstance(args[2], basestring):
            # integer width, integer height, text pixeltype, double precision value=1, double precision nodataval=0, double precision upperleftx=NULL, double precision upperlefty=NULL, double precision skewx=0, double precision skewy=0, boolean touched=false
            # uses upperleft
            width,height,pixeltype = args[:3]
            value = getarg(args, 3, 1) 
            nodataval = getarg(args, 4, 0) 
            xmin,ymin,xmax,ymax = self.bbox()
            upperLeftX = getarg(args, 5, xmin) 
            upperLeftY = getarg(args, 6, ymax) # flipped y by default
            skewX = getarg(args, 7, 0.0) 
            skewY = getarg(args, 8, 0.0) 
            scaleX = abs(xmax-xmin) / float(width)
            scaleY = abs(ymax-ymin) / float(height) * -1 # flipped y by default
            
            ref = make_empty_raster(width, height, upperLeftX, upperLeftY, scaleX, scaleY, skewX, skewY)
            
        else:
            raise Exception('Invalid function args: {}'.format(args))

        # create drawer
        import numpy as np
        from PIL import Image,ImageDraw,ImagePath
        mode = {'b1':'1', 'u1':'L', 'i4':'I', 'f8':'F'}[pixeltype]
        img = Image.new(mode, (ref.width, ref.height), nodataval)
        drawer = ImageDraw.Draw(img)

        # get the raster's inverse affine to use for drawing
        a,b,c,d,e,f,_,_,_ = list(~ref._affine) 

        # set burn values
        fill = value
        outline = None
        holefill = nodataval
        holeoutline = None
        #print ["burnmain",fill,outline,"burnhole",holefill,holeoutline]

        # make all multis so can treat all same
        geoj = self.as_GeoJSON()
        geotype = geoj['type']
        coords = geoj["coordinates"]
        if not "Multi" in geotype:
            coords = [coords]

        # polygon, basic black fill, no outline
        if "Polygon" in geotype:
            for poly in coords:
                # exterior
                exterior = [tuple(p) for p in poly[0]]
                path = ImagePath.Path(exterior)
                #print list(path)[:10]
                path.transform((a,b,c,d,e,f))
                #print list(path)[:10]
                drawer.polygon(path, fill=fill, outline=outline)
                # holes
                if len(poly) > 1:
                    for hole in poly[1:]:
                        hole = [tuple(p) for p in hole]
                        path = ImagePath.Path(hole)
                        path.transform((a,b,c,d,e,f))
                        drawer.polygon(path, fill=holefill, outline=holeoutline)
                        
        # line, 1 pixel line thickness
        elif "LineString" in geotype:
            for line in coords:
                path = ImagePath.Path(line)
                path.transform((a,b,c,d,e,f))
                drawer.line(path, fill=fill)
            
        # point, 1 pixel square size
        elif "Point" in geotype:
            path = ImagePath.Path(coords)
            path.transform((a,b,c,d,e,f))
            drawer.point(path, fill=fill)

        # make raster from drawn img
        out = make_empty_raster(ref)
        out._load_header()
        arr = np.array(img)
        # TODO: prob outsource to builtin add_band() method
        wkb = out._wkb.tobytes()
        dtypes = ['b1', 'u1', 'u1', 'i1', 'u1', 'i2',
                  'u2', 'i4', 'u4', 'f4', 'f8']
        pixeltypenum = dtypes.index(pixeltype)
        bandheader = {'isOffline': False,
                      'hasNodataValue': True,
                      'isNodataValue': False, # maybe check?
                      'pixtype': pixeltypenum,
                      'nodata': nodataval,
                      }
        wkb += out._write_band_header(bandheader)
        wkb += arr.tostring()

        wkb_mem = memoryview(wkb)
        rast = Raster(wkb_mem)
        return rast
Exemple #18
0
 def text(self, xy, text, font):
     if self.transform:
         xy = ImagePath.Path(xy)
         xy.transform(self.transform)
     self.draw.text(xy, text, font=font.font, fill=font.color)
Exemple #19
0
import math
import typing
from abc import ABC, abstractmethod
from typing import overload

# noinspection PyPackageRequirements
from PIL import ImagePath

from x7.lib.iters import iter_rotate
from .typing import *

Points = Iterable[Union['BasePoint', Number, Tuple[Number, Number]]]
PointList = List['BasePoint']
PointUnionList = List[Union['BasePoint', Tuple[float, float]]]
PointTFUnionList = List[Union['BasePoint', float, Tuple[float, float]]]
ImagePathType = type(ImagePath.Path([]))
XYTuple = Tuple[float, float]
XYList = List[XYTuple]
PointOrXYList = Union[PointList, XYList]

__all__ = [
    'BBox',
    'BasePoint',
    'ImagePathType',
    'Line',
    'ParallelLineError',
    'Point',
    'PointCalc',
    'PointRelative',
    'PointList',
    'PointOrXYList',
Exemple #20
0
    def test_path(self):

        p = ImagePath.Path(list(range(10)))

        # sequence interface
        self.assertEqual(len(p), 5)
        self.assertEqual(p[0], (0.0, 1.0))
        self.assertEqual(p[-1], (8.0, 9.0))
        self.assertEqual(list(p[:1]), [(0.0, 1.0)])
        with self.assertRaises(TypeError) as cm:
            p['foo']
        self.assertEqual(str(cm.exception),
                         "Path indices must be integers, not str")
        self.assertEqual(list(p), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0),
                                   (6.0, 7.0), (8.0, 9.0)])

        # method sanity check
        self.assertEqual(p.tolist(), [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0),
                                      (6.0, 7.0), (8.0, 9.0)])
        self.assertEqual(p.tolist(1),
                         [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])

        self.assertEqual(p.getbbox(), (0.0, 1.0, 8.0, 9.0))

        self.assertEqual(p.compact(5), 2)
        self.assertEqual(list(p), [(0.0, 1.0), (4.0, 5.0), (8.0, 9.0)])

        p.transform((1, 0, 1, 0, 1, 1))
        self.assertEqual(list(p), [(1.0, 2.0), (5.0, 6.0), (9.0, 10.0)])

        # alternative constructors
        p = ImagePath.Path([0, 1])
        self.assertEqual(list(p), [(0.0, 1.0)])
        p = ImagePath.Path([0.0, 1.0])
        self.assertEqual(list(p), [(0.0, 1.0)])
        p = ImagePath.Path([0, 1])
        self.assertEqual(list(p), [(0.0, 1.0)])
        p = ImagePath.Path([(0, 1)])
        self.assertEqual(list(p), [(0.0, 1.0)])
        p = ImagePath.Path(p)
        self.assertEqual(list(p), [(0.0, 1.0)])
        p = ImagePath.Path(p.tolist(0))
        self.assertEqual(list(p), [(0.0, 1.0)])
        p = ImagePath.Path(p.tolist(1))
        self.assertEqual(list(p), [(0.0, 1.0)])
        p = ImagePath.Path(array.array("f", [0, 1]))
        self.assertEqual(list(p), [(0.0, 1.0)])

        arr = array.array("f", [0, 1])
        if hasattr(arr, 'tobytes'):
            p = ImagePath.Path(arr.tobytes())
        else:
            p = ImagePath.Path(arr.tostring())
        self.assertEqual(list(p), [(0.0, 1.0)])
Exemple #21
0
def test_path():

    p = ImagePath.Path(list(range(10)))

    # sequence interface
    assert len(p) == 5
    assert p[0] == (0.0, 1.0)
    assert p[-1] == (8.0, 9.0)
    assert list(p[:1]) == [(0.0, 1.0)]
    with pytest.raises(TypeError) as cm:
        p["foo"]
    assert str(cm.value) == "Path indices must be integers, not str"
    assert list(p) == [(0.0, 1.0), (2.0, 3.0), (4.0, 5.0), (6.0, 7.0),
                       (8.0, 9.0)]

    # method sanity check
    assert p.tolist() == [
        (0.0, 1.0),
        (2.0, 3.0),
        (4.0, 5.0),
        (6.0, 7.0),
        (8.0, 9.0),
    ]
    assert p.tolist(1) == [0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0]

    assert p.getbbox() == (0.0, 1.0, 8.0, 9.0)

    assert p.compact(5) == 2
    assert list(p) == [(0.0, 1.0), (4.0, 5.0), (8.0, 9.0)]

    p.transform((1, 0, 1, 0, 1, 1))
    assert list(p) == [(1.0, 2.0), (5.0, 6.0), (9.0, 10.0)]

    # alternative constructors
    p = ImagePath.Path([0, 1])
    assert list(p) == [(0.0, 1.0)]
    p = ImagePath.Path([0.0, 1.0])
    assert list(p) == [(0.0, 1.0)]
    p = ImagePath.Path([0, 1])
    assert list(p) == [(0.0, 1.0)]
    p = ImagePath.Path([(0, 1)])
    assert list(p) == [(0.0, 1.0)]
    p = ImagePath.Path(p)
    assert list(p) == [(0.0, 1.0)]
    p = ImagePath.Path(p.tolist(0))
    assert list(p) == [(0.0, 1.0)]
    p = ImagePath.Path(p.tolist(1))
    assert list(p) == [(0.0, 1.0)]
    p = ImagePath.Path(array.array("f", [0, 1]))
    assert list(p) == [(0.0, 1.0)]

    arr = array.array("f", [0, 1])
    if hasattr(arr, "tobytes"):
        p = ImagePath.Path(arr.tobytes())
    else:
        p = ImagePath.Path(arr.tostring())
    assert list(p) == [(0.0, 1.0)]