Page 1 of 1
Text wrapping with Magick++
Posted: 2010-08-22T20:57:49-07:00
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.
Re: Text wrapping with Magick++
Posted: 2010-08-23T22:12:08-07:00
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?
Re: Text wrapping with Magick++
Posted: 2010-08-24T09:57:39-07:00
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
Re: Text wrapping with Magick++
Posted: 2010-08-24T22:15:24-07:00
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);
Re: Text wrapping with Magick++
Posted: 2010-08-29T19:28:54-07:00
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?
Re: Text wrapping with Magick++
Posted: 2010-09-08T22:16:28-07:00
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.
Re: Text wrapping with Magick++
Posted: 2010-09-09T07:50:52-07:00
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
Re: Text wrapping with Magick++
Posted: 2010-09-09T09:50:48-07:00
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!
Re: Text wrapping with Magick++
Posted: 2010-09-09T20:56:42-07:00
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.
Re: Text wrapping with Magick++
Posted: 2010-09-10T09:48:22-07:00
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
Re: Text wrapping with Magick++
Posted: 2010-09-10T20:33:19-07:00
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!