# How can I create accurate image masks from Graphics?

I am looking to generate image masks using Graphics. For this, the requirements are that:

1. The rasterized mask must have the exact same dimensions as the image with which it will be used.
2. The image coordinates system (as described in the documentation of ImageValue, under Details) must line up perfectly with the Graphics coordinate system.

Neither seems to work readily.

#### Mask has an incorrect size

dims = {20, 20};

mask = Rasterize[
Graphics[{},
PlotRange -> Transpose[{{0, 0}, dims}], ImageSize -> dims,
PlotRangePadding -> None
],
ImageResolution -> 72
]


The mask is of the wrong size. ImageDimensions[mask] gives {20, 22}.

#### Coordinates don't line up

Example code:

dims = {21, 21};

pix = Image@ReplacePart[ConstantArray[0, dims], {{11, 11}} -> 1]

mask = Rasterize[
Graphics[{Disk[dims/2, 6]},
PlotRange -> Transpose[{{0, 0}, dims}], ImageSize -> dims,
PlotRangePadding -> None
],
ImageResolution -> 72
]


The image size is odd, so there is a middle pixel. pix visualizes this pixel. mask draws a disk around it. But the pixel is clearly not in the middle of the disk:

Magnify[mask + pix, 5]


#### Attempted workarounds

• ImageMargins -> 0, ImagePadding -> None does not help.
• Adding ImageSize to Rasterize as well, in addition to Graphics, does not help.
• RasterSize can force a specific image size, but it does not help with alignment

#### System information

Mathematica 13.0.1, macOS 10.14.6 (Mojave), and a retina screen

• Use RasterSize -> dims instead? ImageSize for Rasterize is only the display dimensions… Mar 8 at 10:29
• I'm not really a fan of RasterSize. I suspect what it does is a rescaling after creating an image. The ImageSize and the ImageResolution together should give a good result. The reason why I worry about such rescaling is that it might mess up the alignment between the image coordinates and the graphics coordinates. Mar 8 at 11:41
• Would RegionImage be of use? Mar 8 at 22:59
• @Szabolcs Why do you suspect such a thing? I've never noticed that, and i always use RasterSize. Even the help of Rasterize says: ImageSize => final displayed image size in printer's points. (So only display!). Mar 9 at 10:48
• @AlexeyPopkov The first problem can be reproduced in v13.0.0 Linux (Wolfram Cloud): i.stack.imgur.com/8KGMW.png Mar 9 at 12:37

## 1 Answer

The first behavior seems to be a bug of v13. In v12.3.1 it works as expected:

As to the second example, this seems to be another bug introduced in v12.3.1 or earlier, because v9.0.1 works as expected:

\$Version
dims = {21, 21};
pix = Image@ReplacePart[ConstantArray[0, dims], {{11, 11}} -> 1];
mask = Rasterize[Graphics[{Disk[dims/2, 6]},PlotRange -> Transpose[{{0, 0}, dims}]
(*,ImageSize -> dims*), PlotRangePadding -> None], "Image",
ImageResolution -> 72, RasterSize -> dims];
(* mask + pix *)
ImageAdd[mask, pix]


For comparison here's v12.3.1 result:

## Remark

1. I've removed the ImageSize option in Graphics and add the RasterSize option to Rasterize, otherwise the alignment will be wrong even in v9. (Yeah, once again, this seems to be a bug, in v9. )

2. I've used ImageAdd in v9 because the syntax mask + pix is introduced in v11.1.

3. I've explicitly set the second argument of Rasterize to "Image" in v9, because the default setting before v11.2 is "Graphics".

• I think the PlotRange is correct. For example, for a 1-by-1 image it should go from 0 to 1 when using ImageValue coordinates. But the centre of the Disk[] was indeed off. It should have been dims/2. I fixed that. I hope I did not make other mistakes. I'll check a couple of hours later. Mar 8 at 13:20
• It is interesting that uncommenting ImageSize -> dims in the above code in version 8.0.4 reproduces exactly the wrong alignment of version 13. Mar 8 at 14:21
• Show[mask, ImageSize -> dims] isn't needed in version 8 and its presence makes the whole comparison invalid because this piece of code converts Image to Graphics which at the next step is rasterized again to Image. I hadn't included this in my check with version 8. Mar 8 at 14:29
• @AlexeyPopkov "because this piece of code converts Image to Graphics which at the next step is rasterized again to Image" This doesn't seem to be the case in v9 period. I just checked the InputForm, mask is a Graphics[Raster[…],…] expression, and after Show[…] the InputForm is still a Graphics[Raster[…],…] expression. It's a bit surprising that ImageAdd[mask, pix] works as expected in v8, because ImageDimensions@mask isn't {21,21} in v8 and v9, it's {360, 378}! I'm not sure if this is by design or another bug in v8/v9 period. Mar 8 at 14:57
• @xzczd I wouldn't rely on the assumption that the WRI staff monitors the site. The only way to be sure that the support is aware of the problem is to send a report. And bigger weights are assigned to the problems reported by many people. Mar 9 at 12:56