Text wrapping with Magick++

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
rarrum

Text wrapping with Magick++

Post by rarrum »

I'm attempting to use Magick++ to render text to an image in memory, which my app can then load onto a texture for use in OpenGL rendering. I'm already using Magick++ to load image files this way and it works great.

From looking at http://www.imagemagick.org/Usage/text/ it appears ImageMagick does everything that I need. However I'm not certain how achieve similar results to what's shown there using the C++ api.

I'm trying to figure out how to enable word wrapping. For example, here is the small bit I'm playing with right now:

Code: Select all

std::string text="Hello World"; //parameter coming in at run-time

Magic::Image image;
image.magick("RGBA");
image.size("50x100"); //how do I determine the size needed before rendering the text?  Or can it be sized automatically?

image.annotate(text, Magick::NorthWestGravity);
This cuts off the second word rather than wrapping it.

I'd also like to know how to determine the height needed to the hold the rendered text (with wrapping on, and a given width), so I can size the image appropriately tall to hold everything.
rarrum

Re: Text wrapping with Magick++

Post by rarrum »

Looking at http://www.imagemagick.org/api/annotate.php it looks like the C API might be able to do this... I can use that if I need to. Can someone confirm that the C++ API just hasn't implemented these?
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Text wrapping with Magick++

Post by el_supremo »

It looks like FormatMagickCaption etc. haven't been implemented in MagickWand or Magick++.
To use them you would have to call the MagickCore functions directly in C or C++.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
rarrum

Re: Text wrapping with Magick++

Post by rarrum »

Alright, can someone explain the parameters to FormatMagickCaption to me please? It's just crashing when I call it and I assume I've just misinterpreted what it's wanting.

http://www.imagemagick.org/api/annotate.php has:
ssize_t FormatMagickCaption(Image *image, DrawInfo *draw_info, TypeMetric *metrics, char **caption)

image: The image. For this I'm using .image() on my Magick::Image. I believe this is right.

caption: the caption. I'm not sure why it's wanting a pointer to a pointer to the string, rather than just a pointer to the string. Perhaps it wants an array of pointers to strings with the last array entry null, to render multiple strings or something?

draw_info: the draw info. I'm creating one of these with MagickCore::AcquireDrawInfo().

metrics: Return the font metrics in this structure. I'm passing it an instance allocated on the stack, assuming I don't need to do anything special to it before passing it in.

Here's what I have which is crashing in FormatMagickCaption:

Code: Select all

Magick::Image image;
image.magick("RGBA");
image.size("50x100");

MagickCore::DrawInfo *drawInfo=MagickCore::AcquireDrawInfo();
MagickCore::TypeMetric returnedMetrics;
char *captions=(char*)Text.c_str();
MagickCore::FormatMagickCaption(image.image(), drawInfo, &returnedMetrics, &captions);
MagickCore::DestroyDrawInfo(drawInfo);
rarrum

Re: Text wrapping with Magick++

Post by rarrum »

After digging around some more I found a MagickCore::StringToList which based on the input and return, might be what FormatMagickCaption is expecting for caption instead. However it still crashes.

Digging into the crash, it's in annotate.c line 487:

Code: Select all

for (i=0; i < (long) GetUTFOctets(p); i++)
    *q++=(*(p+i));
q is a null pointer.

It appears to just be taking q from draw_info->text. Is there some special way I need to initialize the draw info for use, beyond calling MagickCore::AcquireDrawInfo?
rarrum

Re: Text wrapping with Magick++

Post by rarrum »

Here is what I have as a starting point which at least functions even though it doesn't do what I want. It successfully writes the png file at the end, and viewing that in an editor shows that it contains a truncated Hello World because the image (isn't wide enough).

Code: Select all

std::string Text="Hello World";

Magick::Image image;
image.magick("RGBA");
image.size("50x100");

image.annotate(Text, Magick::NorthWestGravity);

image.write("temptest.png");

Here is what I currently have in my attempt to call FormatMagickCaption. It fails to write the png at the end and throws an exception: "Magick: No IDATs written into file `temptest.png' @ error/png.c/PNGErrorHandler/1455".

Code: Select all

std::string Text="Hello World";

Magick::Image image;
image.magick("RGBA");
image.size("50x100");

MagickCore::DrawInfo *drawInfo=MagickCore::AcquireDrawInfo();
MagickCore::CloneDrawInfo(image.imageInfo(), drawInfo);
drawInfo->gravity=MagickCore::NorthWestGravity;

drawInfo->text=MagickCore::AcquireString(Text.c_str());
char *captions=MagickCore::AcquireString(Text.c_str());
char *origCaptions=captions; //in case they change our pointer

MagickCore::TypeMetric returnedMetrics;
MagickCore::FormatMagickCaption(image.image(), drawInfo, &returnedMetrics, &captions);
            
//MagickCore::DestroyString(drawInfo->text); //DestroyDrawInfo apparently takes care of this
MagickCore::DestroyString(origCaptions);
origCaptions=0;

MagickCore::DestroyDrawInfo(drawInfo);

image.write("temptest.png");
I can't find any helpful documentation on what this API expects to be passed to it or any documented examples of calling it. Any assistance from someone more familiar with it would be appreciated.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Text wrapping with Magick++

Post by el_supremo »

See the C code I posted here viewtopic.php?f=1&t=17025. It shows how to create a caption and optionally write it to a ram buffer.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
rarrum

Re: Text wrapping with Magick++

Post by rarrum »

The MagickWand code there is almost exactly what I was looking for. I messed around a little this morning before work, and it's working great so far, thanks!
rarrum

Re: Text wrapping with Magick++

Post by rarrum »

Ok, this is rendering things correctly. However I still have another issue: How can I anticipate the height of the image needed to hold the text for a given image width, so I can set the image to the correct size? I'd rather not have to do something like allocate an image that's absurdly tall then detect where the lower edge of the text is and crop it down, as that would be rather expensive.
el_supremo
Posts: 1015
Joined: 2005-03-21T21:16:57-07:00

Re: Text wrapping with Magick++

Post by el_supremo »

I don't understand why you'd do that. I need to see your code.
In my example, MagickWand is only given the pixel width of the image and it fills the text into that space. Then the code gets the width and height of the resulting image and mallocs the amount of buffer space required for that specific image size.

Pete
Sorry, my ISP shutdown all personal webspace so my MagickWand Examples in C is offline.
See my message in this topic for a link to a zip of all the files.
rarrum

Re: Text wrapping with Magick++

Post by rarrum »

Oh woops, that's my bad there. When I was filling in the parameters in my code I passed a temporary estimated value I made up... I just noticed that you're passing 0. I think that will be perfect. Thanks again!
Post Reply