Add "stroke_width" option for Image.Draw.line!() function
severian1778 opened this issue · comments
Just a litte detail here, but its nice to be able to draw lines of different widths with the svg Draw module so one doesn't have to use a graphing library.
- Is it possible to add a width option to draw line?
- Is it also possible to add "stroke_type" option as well? {dotted, solid, dashed etc.}
The functions in Image.Draw
are very simple - the underlying functions in libvips
are very simple. The reason I could add :stroke_width
to Draw.circle
and Draw.rectangle
is that I can fake it with concentric shapes and use a flood fill. But with a line the angle of the line means its very difficult to render a wider stroke because then I have to get into the mechanics of aliasing the ends of the line at an angle. Which I don't think it worth it because the Image.Draw
functions mutate the underlying image which also means the image has to be fully rendered which is against the overall design strategy of libvips
.
I would prefer to focus on more functions in Image.Shape
which I've never properly built out. It uses SVG
shapes so the rendering works properly and we can leverage all of the options that SVG
provides. The upside is flexibility, and it being the right fit for the libvips
architecture. The downside is that its compositing process (base image composed with the shape image) not a mutating function.
Anyway, I can definitely do what you're after by adding Image.Shape.line
which I can do this weekend. But it won't be the same as Image.Draw.line
for the reasons outlined above.
@kipcole9 aha I see what you mean. I mean I could just draw X lines and stack them and it should be fine for now in terms of creating a width mechanic. SVG is very useful but I can see how within the scope of the entire project how it might take a back seat for now. In my mind though, it would be so powerful to fold SVG into the Image stack. Image is such a joy to use so far and SVG additions just send me to the moon as I work in data visualization.
I may have miscommunicated. SVG
is absolutely a first-class citizen in libvips
is is to be preferred in nearly every case. It's the functions in Image.Draw
that are the "only use as a last resort or for a specific use case".
The functions in Image.Shape
all use SVG for drawing - but there are no functions yet for the basics like square
or ellipse
or line
. I will add those functions.
I can probably still add stroke_width
to Image.Draw.line
but thats the limit of practical implementation. There's no practical way to add line style in those functions (the Image.Draw
functions). Of course its trivial in the Image.Shape
functions since they are SVG
driven and thats where I would focus.
Oh ok that is great! I am still learning the code base here so that is good news. No worries, I look forward to the Shape module "taking shape" :D
Huh! I added resvg to my app because I assumed svg would not work. Maybe I don't need that then? For converting to a raster image like a PNG?
@lawik Converting SVG to a raster image is most definitely part of Vix
/libvips
. You can see some examples in the Image.Shape module. It uses libsvg under the hood although there is some discussion about moving to librsvg.
You can use both Image.open/2
and Image.from_binary/1
:
# An image from an svg string
iex> {:ok, i} = Image.from_binary "<svg viewBox=\"0 0 100 100\" xmlns=\"http://www.w3.org/2000/svg\">
...> <line x1=\"0\" y1=\"80\" x2=\"100\" y2=\"20\" stroke=\"green\" />
...> </svg>"
{:ok, %Vix.Vips.Image{ref: #Reference<0.3301218185.3652845603.95591>}}
# Or an image path with the .svg suffix
iex> Image.open!("/Users/kip/Desktop/svg_test.svg")
%Vix.Vips.Image{ref: #Reference<0.3301218185.3652845603.95595>}
It's been a long time - and maybe this isn't anywhere top of your list now :-).
But I have added Image.Shape.line/5
to draw lines using SVG - including stroke width. It's not a mutation, it returns a new image of a line that would need to be Image.compose/2
d. But since stroke width isn't possible with the current mutation functions its better - and arguably since its a pure function - the best approach.
I will close this for now but please reopen if required.