Page 1 of 1

Drawing text on an angle

Posted: 2011-12-15T07:57:05-07:00
by brianp22
I am totally missing something. All I am trying to do is draw some text between 2 points. Quite often, this will be on an angle. My Google-foo has been failing me on this...

I know how to do this in GD (call gdImageStringFT) and how to do this in cairo (using pango), but I can not seem to figure it out in Magick++.

Based on the headers, I think I need to use some combination of transformOrigin/transformRotation/transformReset, but I can't seem to figure it out.

I wrote this little test program that creates 2 identical images, one with Magick++ and one with GD. I think the problem is that after I do the transformRotation, my coordinate system is wrong......

Code: Select all

#include <Magick++.h>
#include <gd.h>
#include <cstring>
#include <fstream>
#include <math.h>

gdImagePtr gdimage;
Magick::Image mimage;
char* tmpFont = "/usr/share/fonts/type1/gsfonts/n022003l.pfb";
int fontSize = 10;

double angleBetweenTwoPoints(double x1, double y1, double x2, double y2)
{
    double dx = x2 - x1;
    double dy = y2 - y1;
    double angle = 0.;

    if (dx >= -3 && dx <= 3)
        dx = 0;
    if (dy >= -3 && dy <= 3)
        dy = 0;

    if (dx != 0 && dy != 0)
        angle = atan(fabs(dy) / fabs(dx));

    if (dx == 0 && dy < 0)
        angle = M_PI_2l;
    else if (dx == 0 && dy > 0)
        angle = M_PIl + M_PI_2l;
    else if (dy == 0 && dx > 0)
        angle = 0;
    else if (dy == 0 && dx < 0)
        angle = M_PIl;
    else if (x2 > x1 && y2 > y1)
        angle = M_PIl + M_PIl - angle;
    else if (x2 < x1 && y2 < y1)
        angle += M_PI_2l;
    else if (x2 < x1 && y2 > y1)
        angle += M_PIl;

    return angle;
}

void draw(double x1, double y1, double x2, double y2, int red, int green, int blue, char* str)
{
    double angle = angleBetweenTwoPoints(x1, y1, x2, y2);
    int style[1], lineColor;

    // Define GD color
    lineColor = gdImageColorAllocate(gdimage, red, green, blue);
    style[0] = lineColor;
    gdImageSetStyle(gdimage, style, 1);
    // Define Magick color
    mimage.strokeColor(Magick::ColorRGB(red / 255.0, green / 255.0, blue / 255.0));

    // Draw GD line
    gdImageLine(gdimage, x1, y1, x2, y2, gdStyled);
    // Draw Magick line
    mimage.draw(Magick::DrawableLine(x1, y1, x2, y2));

    // Draw the GD string
    gdImageStringFT(gdimage, NULL, lineColor, tmpFont, fontSize, angle, ((x2 + x1) / 2), ((y2 + y1) / 2), str);
    // Draw the Magick string
    mimage.transformRotation((angle/ M_PI) * 180.0); // angle is in radians
    mimage.draw(Magick::DrawableText(((x2 + x1) / 2), ((y2 + y1) / 2), str));
    mimage.transformReset();
}

int main(int, char**)
{
///////////////////////////////////////
// Magick image
//
    mimage = Magick::Image(Magick::Geometry(256, 256), Magick::ColorRGB(250 / 255.0, 240 / 255.0, 230 / 255.0));
    mimage.magick("png");
    mimage.font(tmpFont);
    mimage.fontPointsize(fontSize);
// Magick image
//
///////////////////////////////////////
///////////////////////////////////////
// GD image
//
    gdimage = gdImageCreateTrueColor(256, 256);
    // first color
    int lineColor = gdImageColorAllocate(gdimage, 250, 240, 230);
    gdPoint* points = new gdPoint[4];
    points[0].x = 255;
    points[0].y = 0;
    points[1].x = 255;
    points[1].y = 255;
    points[2].x = 0;
    points[2].y = 255;
    points[3].x = 0;
    points[3].y = 0;
    gdImageFilledPolygon(gdimage, points, 4, lineColor );
    delete[] points;
// GD image
//
///////////////////////////////////////

    draw(30, 30, 255, 30, 255, 0, 0, "horz");
    draw(30, 30, 30, 255, 255, 0, 0, "vert");
    draw(0, 0, 127, 127, 0, 0, 255, "one");
    draw(127, 127, 255, 0, 0, 255, 0, "two");
    draw(0, 255, 127, 127, 255, 0, 255, "three");
    draw(127, 127, 255, 255, 0, 255, 255, "four");

    draw(255, 30, 30, 30, 255, 0, 0, "rev-horz");
    draw(30, 255, 30, 30, 255, 0, 0, "rev-vert");
    draw(127, 127, 0, 0, 0, 0, 255, "rev-one");
    draw(255, 0, 127, 127, 0, 255, 0, "rev-two");
    draw(127, 127, 0, 255, 255, 0, 255, "rev-three");
    draw(255, 255, 127, 127, 0, 255, 255, "rev-four");

    
    int imageSize;
    void* imagePtr = gdImagePngPtr(gdimage, &imageSize);
    std::ofstream ofs("gd.png");
    ofs.write(static_cast<const char *>(imagePtr), imageSize);
    ofs.close();

    mimage.write("magick.png");
}
Any help would be greatly appreciated.....

- Brian

Re: Drawing text on an angle

Posted: 2011-12-15T11:36:24-07:00
by brianp22
Followup question.

Any idea why the font looks so much worse in Magic++ than in GD? It almost looks like Magic++ is forcing the font to bold where GD isn't. I have tried 5 or 6 different GhostScript fonts and see the same thing.

- brian

Re: Drawing text on an angle

Posted: 2011-12-15T12:04:23-07:00
by magick
Verify you have Freetype support built into ImageMagick. Type
  • identify -list format
Hopefully, the TTF format says something like
  • TrueType font (Freetype 2.4.6)

Re: Drawing text on an angle

Posted: 2011-12-20T14:08:29-07:00
by brianp22
I figured out who to translate my text start point with the rotation I am placing on the image which fixed my problem.

Still not sure what is going on with the font, but I will start another thread on that (if I need to) to prevent confusion with this thread.

Thanks!

- brian