labelme
                                
                                 labelme copied to clipboard
                                
                                    labelme copied to clipboard
                            
                            
                            
                        Rectangle shape coordinates not sorted before being passed to PIL.ImageDraw() in utils.shape_to_mask()
Provide environment information
$ which python
/redacted/.cache/pypoetry/virtualenvs/labelme-issue-reprod-y-dKVbcE-py3.12/bin/python
$ python --version
Python 3.12.7
$ python -m pip list | grep labelme
labelme                   5.5.0
What OS are you using?
Arch Linux x86_64 Kernel: 6.12.3-zen1-1-zen
Describe the Bug
In line 33 of labelme/utils/shape.py, in shape_to_mask, the rectangle shape coordinates are not sorted before being passed to PIL.ImageDraw() in utils.shape_to_mask(). When any rectangle shapes are not created from upper left to lower right (and thus automatically sorted), a ValueError: x1 must be greater than or equal to x0 will be raised.
Expected Behavior
utils.shape_to_mask() can correctly process rectangle shapes created in any way, even when the x and y coordinates are not sorted, without raising any error.
To Reproduce
For rectangular shapes not created from upperleft to lowerright, as in test.json:
{
  "version": "5.5.0",
  "flags": {},
  "shapes": [
    {
      "label": "blabla",
      "points": [
        [
          149.9047619047619,
          28.64625850340135
        ],
        [
          80.85714285714285,
          98.71428571428571
        ]
      ],
      "group_id": null,
      "description": "",
      "shape_type": "rectangle",
      "flags": {},
      "mask": null
    }
  ],
  "imagePath": "test.png",
  "imageData": "redacted",
  "imageHeight": 226,
  "imageWidth": 226
}
Calling utils.shape_to_mask(), as in this reproduction script:
import labelme
label_file = labelme.LabelFile(filename="./test.json")
img = labelme.utils.img_data_to_arr(label_file.imageData)
for shape in label_file.shapes:
    points = shape["points"]
    shape_type = shape.get("shape_type", "polygon")
    mask = labelme.utils.shape_to_mask(img.shape[:2], points, shape_type)
Will cause the following error:
Traceback (most recent call last):
  File "/redacted/labelme_issue_reprod/reprod.py", line 8, in <module>
    mask = labelme.utils.shape_to_mask(img.shape[:2], points, shape_type)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/redacted/.cache/pypoetry/virtualenvs/labelme-issue-reprod-y-dKVbcE-py3.12/lib/python3.12/site-packages/labelme/utils/shape.py", line 33, in shape_to_mask
    draw.rectangle(xy, outline=1, fill=1)
  File "/redacted/.cache/pypoetry/virtualenvs/labelme-issue-reprod-y-dKVbcE-py3.12/lib/python3.12/site-packages/PIL/ImageDraw.py", line 411, in rectangle
    self.draw.draw_rectangle(xy, fill_ink, 1)
ValueError: x1 must be greater than or equal to x0