sharp icon indicating copy to clipboard operation
sharp copied to clipboard

Enhancement: expose vips_text to create an image containing rendered text

Open gargsms opened this issue 7 years ago • 63 comments

I was fiddling with SVG overlays, and tried a SVG containing text inside a foreignObject div, but it didn't render. My use case is to make the text fit the container dynamically. I won't be knowing the text length beforehand, but I know how wide the container will be. Here is the SVG image I am using: http://jsbin.com/jowaboluga/1/edit?html,output Since there is no support of drawing text over an image, I had to make a SVG with the text.

Is there any way to achieve the desired effect?

gargsms avatar Jul 15 '16 09:07 gargsms

Hello, a quick Stack Overflow search revealed the following, which may help:

http://stackoverflow.com/questions/2938779/svg-scaling-text-to-fit-container http://stackoverflow.com/questions/283346/how-to-resize-text-in-svg-dynamically

lovell avatar Jul 16 '16 10:07 lovell

@lovell I did look up those links already. And I believe they are not catering to my use case. I want the text to wrap by itself if it is overflowing the container - something easily achievable with foreignObject support. Anyhow, if it is not there, I will have to devise some method to make it work.

By the way, any plans to include the watermark functionality by default? https://github.com/h2non/bimg/ has the watermark support built in.

I would be more than willing to work on a patch if it is possible - need a few pointers, though.

gargsms avatar Jul 16 '16 14:07 gargsms

I suspect librsvg (as used by libvips for SVG rendering) doesn't support the foreignObject extension to SVG and it's likely *magick has the same limitation.

I'd be happy to accept a PR that exposes vips_text, a wrapper around pango, for image creation. I need to think a little about how this should fit into the existing API (e.g. should work alongside #470).

lovell avatar Jul 18 '16 14:07 lovell

I should be able to work this out and submit a PR soon. Not sure about *magick, though. Instead of using it with #470, I think it could be used better as an extension to .overlayWith().

gargsms avatar Jul 20 '16 10:07 gargsms

In terms of the API to expose this, I see it working a bit like the proposed "create image" helper described in https://github.com/lovell/sharp/issues/470#issuecomment-239620622

sharp({
  text: {
    text: string,
    font: string,
    width: integer,
    align: string,
    dpi: integer,
    spacing: integer
  }
})...

Please note that this is a proposed API and is not currently available.

lovell avatar Aug 13 '16 13:08 lovell

I have implemented the text API, though not for the pencil branch.

There is a small issue, however. On my local system, if I use the text API, I can successfully write text to an image, however, if I do the same on an EC2 instance (my use case requires this), it throws an error

Error: VipsOperation: class "text" not found
     at Error (native) null

and since there is no error trace logged with this error, I cannot quite understand how it is happening.

I have also tried compiling vips there and I can use vips text <out_image> <text> giving me the correct output.

gargsms avatar Aug 24 '16 16:08 gargsms

You can have a look at the code on my fork here #183cb8

gargsms avatar Aug 24 '16 16:08 gargsms

Ha. It fixed by itself. Works now. I had to recompile libvips from source, though.

gargsms avatar Aug 24 '16 20:08 gargsms

Hi Guys,

Would love to have this merged in the main Sharp release.

Any ETA on that?

niravmehta avatar Jan 17 '17 04:01 niravmehta

@niravmehta I have the text API exposed in my forks, gargsms/sharp and gargsms/libvips

I was a little occupied with work lately, and never got the time to maintain my forks up-to-date to the upstreams. Moreover, sharp had quite a big overhaul in the pencil release.

You can use my forks, if they seem fine to you. I cannot guarantee it, but I will try my best to make PRs both to sharp and libvips in the coming days, maybe this week, because I happen to have the need to expose few other functionalities in sharp, notably tilt.

To use my fork of sharp, you would need to compile my libvips fork from source and replace your previous installation, if any, with it. There aren't very many changes to sharp code for the text functionality as most of the operations are handled in libvips. I need to discuss the implementation with @jcupitt, and @lovell first as I am not very certain of handling edge cases, and if it is optimal. For my purposes, it seems to work just fine, with no visible degradation in the text operation performance. I am yet to document the text API. Sorry about that. I will try and do this ASAP.

gargsms avatar Jan 17 '17 21:01 gargsms

i need this too

jd1378 avatar Jan 29 '17 12:01 jd1378

Hello, this issue appears to have been left hanging for several months. As I also need this, I would like to repeat niravmehta's question. Any ETA for inclusion in the main release?

NIPanag avatar Jun 18 '17 04:06 NIPanag

@NIPanag As always, happy to accept a PR implementing the suggested API or similar. As an aside, please remember requesting things like an "ETA" generally has the opposite effect in open source.

lovell avatar Jun 18 '17 11:06 lovell

@lovell I didn't mean to pressure, just wanted to see if anything's happened since it's been quite a while since anything was posted on it. I'll see if I can implement it myself and open a PR, perhaps working off what @gargsms has already done in their fork.

NIPanag avatar Jun 18 '17 12:06 NIPanag

Another issue to consider is getting vips text working on Windows. I've been trying for a few days, but I've not managed it yet :( I just get a set of annoying white squares.

jcupitt avatar Jun 18 '17 12:06 jcupitt

@jcupitt I don't have a Windows machine, perhaps I will try in a VM. I have implemented the text changes and already using them in production at my workplace. @lovell, @jcupitt I shall submit a PR within a few days. It would be a very crude PR, but it fulfills my goals. @NIPanag The delay was caused by the dependency of the sharp text API on the libvips text function. Since I never submitted the libvips PR, there is no reliable way this could have worked in sharp. I am extremely sorry for the delay. I have some free time at hand - vacation - and would send a PR soon. There's still a missing feature of gravity in the text rendering which I need to add before the PR is any usable.

gargsms avatar Jun 18 '17 22:06 gargsms

@gargsms Thank you for your update, a PR would be most welcome. There is no need to apologise about perceived time pressure - please ignore this.

lovell avatar Jun 19 '17 06:06 lovell

@gargsms Like I said above, I didn't mean to pressure anybody. Please don't stress because of my bad wording. As for windows testing, I should have free time tomorrow (the 20th) to look into it. I will certainly be able to test on Windows 7 64bit and possibly Windows 10 64bit.

NIPanag avatar Jun 19 '17 06:06 NIPanag

Like @jcupitt i also get white squares/rectangles but on Linux (CentOS). Looks like the font/encoding is not working properly.

const watermark = new Buffer(`<svg>
    <rect x="0" y="0" width="500" height="100" fill="#000" />
    <text x="10" y="76" font-size="74" fill="#fff">${conf.watermarkText}</text>
  </svg>`)

ctx.body = sharp(image.path)
              .overlayWith(watermark, {gravity: 'southeast'})
              .withMetadata()

It works fine on MacOS. Any suggestions ... is it vips problem or missing fonts problem. I also tried with font-family="sans-serif" but same result.

purepear avatar Jun 19 '17 09:06 purepear

Could you try the command-line interface?

vips text x.png "hello world"

And see if x.png has lettering in. It's always worked for me on linux / macOS, never properly on Windows. Font rendering involves at least freetype, fontconfig and pango and I'm not clear which one I've not been able configure correctly. harfbuzz, xft2 and cairo might also be involved :(

jcupitt avatar Jun 19 '17 09:06 jcupitt

@purepear This discussion is about exposing vips_text but the problem you describe appears to be about text rendering inside SVG via librsvg. Please can you open a new issue for this.

lovell avatar Jun 19 '17 09:06 lovell

Sorry @lovell I realized that a bit later. Saw the rectangles problem in google search. Anyways... my problem was there were no installed fonts on the linux server. I used text-to-svg to load a font and convert to path.

purepear avatar Jun 19 '17 12:06 purepear

Sorry for clogging up sharp. I've made a separate issue for getting text working on Windows.

jcupitt avatar Jun 19 '17 13:06 jcupitt

UPDATE: I was able to finish up the code changes on my side. Since this only requires sharp to expose the libvips functions, a PR to libvips is due. I will be able to make that PR in a few days time at max (I would want to do that by the coming weekend), and upon acceptance to libvips, I will submit a PR to sharp with the test cases I am still trying to finish up on.

gargsms avatar Jun 29 '17 02:06 gargsms

Hi @gargsms . I'm looking forward to this feature. Is it still in progress?

jmillerdesign avatar Jul 31 '17 18:07 jmillerdesign

Hi all. Sorry for all the delay. I had a version of the logic implemented already, but it wasn't necessarily the best implementation that was possible. So, I had to rewrite almost all of it from scratch. I have raised https://github.com/jcupitt/libvips/pull/701 which tries to fit text in the best possible way inside a rectangle. I ended up implementing gravity as well because I needed it.

I underestimated the complexity of the task, and overguessed my availability and free time earlier. Working with Pango and scourging documentation for that has not been the smoothest experience so far.

A wrapper for text would be trivial to add in sharp. We need to wait till @jcupitt and I could work out something that works good enough for all conditions.

gargsms avatar Aug 01 '17 18:08 gargsms

Awesome. Thanks for the hard work on this!

jmillerdesign avatar Aug 02 '17 06:08 jmillerdesign

I see libvips 8.6.0 was just released. Does that mean this feature can now be implemented into sharp?

jmillerdesign avatar Dec 11 '17 19:12 jmillerdesign

This feature is still unavailable?

ChrisRobston avatar Jul 31 '18 18:07 ChrisRobston

I'm wondering the same thing. I need to add multiple strings in different position on an image.

Extarys avatar Nov 17 '18 01:11 Extarys