Xlib - Rotation and interpolation of pixmap - Performance problems

I need to rotate a pixmap in XLib with some kind of interpolation to reduce the aliasing.

I came up with the following code, which uses bilinear interpolation. It works fine: the rotated image looks perfect, but unfortunately it takes 5 or 6 seconds for each rotation. (in a 300x300, 16 colours pixmap)

The following is the code I am using:

#define CONST (double)((double)180/M_PI)

        cx = attrib.width/2;
        cy = attrib.height/2;

        unsigned long tleft_p, tright_p, bleft_p, bright_p;
        unsigned long background_p;
        XColor tleft_c, tright_c, bleft_c, bright_c;


        Display *dpy = XtDisplay(w);
        Colormap cmap = DefaultColormap(dpy, DefaultScreen(dpy));


        for (y=1; y<attrib.height; y++) {
                for (x=1; x<attrib.width; x++) {
                        XColor mycol;
                        int xx, yy, floor_x, floor_y, ceil_x, ceil_y;
                        float dist, ang, true_x, true_y, delta_x, delta_y;
                        float tred, tgreen, tblue, bred, bgreen, bblue;
                        int red, green, blue;

                        /* rotation */
                        xx = x - attrib.width/2;
                        yy = y - attrib.height/2;
                        true_x = (double)xx * cos((double)deg/CONST) + (double)yy * sin((double)deg/CONST);
                        true_y = (double)xx * -sin((double)deg/CONST) + (double)yy * cos((double)deg/CONST);
 
                        true_x += attrib.height/2;
                        true_y += attrib.width/2;
        
                        floor_x = (int)floor(true_x);
                        floor_y = (int)floor(true_y);
                        ceil_x = (int)ceil(true_x);
                        ceil_y = (int)ceil(true_y);
        
                        delta_x = true_x - (double)floor_x;
                        delta_y = true_y - (double)floor_y;
        
                        tleft_p = XGetPixel(src, floor_x, floor_y);
                        tright_p = XGetPixel(src, ceil_x, floor_y);
                        bleft_p = XGetPixel(src, floor_x, ceil_y);
                        bright_p = XGetPixel(src, ceil_x, ceil_y);
        
                        tleft_c.pixel = tleft_p;
                        tright_c.pixel= tright_p;
                        bleft_c.pixel = bleft_p;
                        bright_c.pixel= bright_p;
                        XQueryColor(dpy, cmap, &tleft_c);
                        XQueryColor(dpy, cmap, &tright_c); 
                        XQueryColor(dpy, cmap, &bleft_c);
                        XQueryColor(dpy, cmap, &bright_c);

                        /* interpolation */
                        /* tred = top red,  bred = bottom red ... */
                        tred = (1-delta_x)* (int)tleft_c.red + delta_x * tright_c.red;
                        tgreen = (1-delta_x)* (int)tleft_c.green + delta_x * tright_c.green;
                        tblue = (1-delta_x)* (int)tleft_c.blue + delta_x * tright_c.blue;

                        bred = (1-delta_x) * (int)bleft_c.red + delta_x * (int)bright_c.red;
                        bgreen = (1-delta_x)*(int)bleft_c.green+delta_x * (int)bright_c.green;
                        bblue = (1-delta_x)* (int)bleft_c.blue+ delta_x * (int)bright_c.blue;

                        red = (int)round((1-delta_y) * tred + delta_y * bred);
                        green = (int)round((1-delta_y) * tgreen + delta_y * bgreen);
                        blue = (int)round((1-delta_y) * tblue + delta_y * bblue);

                        if (red < 0) red = 0;
                        if (green<0) green=0;
                        if (blue<0)  blue =0;
                        if (blue>65535) blue=65535;
                        if (green>65535) green=65535;
                        if (red>65535) red=65535;

                        mycol.red = red;
                        mycol.green=green;
                        mycol.blue=blue;
                        XAllocColor(dpy, cmap, &mycol);

                        XPutPixel(dest, x, y, mycol.pixel);
                }
        }

I attached a working test program, if you wish to try it.
You should link with:

-lXm -lXt -lX11 -lXp -lXext -lXpm -lm

It requires Motif widget toolkit.

Could you suggest a way to get a reasonable speed?

Thank you very much for your kind help.
--mghis

P.S.: Sorry for my bad English: I'm not a native speaker.

Aside from algorithmic changes (and those usually result in the best speeding up) I see that sine and cosine functions are called repetitively, so I'd call them once and store result in a local double variable, then use those variables in your formulas, like so:

 
 cos_var = cos((double)deg/CONST);
 sin_var = sin((double)deg/CONST);
 true_x = true_x = (double)xx * cos_var + (double)yy * sin_var;
 etc...
 

Thank you, migurus, for your reply.
It did speed it up a bit, but I noticed the problem is mainly in the XAllocColor() call. In fact, if I remove that call and always put a black pixel, (still calculating the values), the program runs at less than half a second per rotation.

However I really don't know to get rid of XAllocColor().

I am writing pixels to an XImage. Is there a way to access directly the RGB values of each pixel?

How are you creating the "dest" XImage? You should probably manipulate the data sent to XCreateImage directly, before calling XCreateImage() to create the dest image.

Src and dest are created with:

src = XGetImage(dpy, pix, 0, 0, width, height, AllPlanes, ZPixmap);
dest = XGetImage(dpy, pix, 0, 0, width, height, AllPlanes, ZPixmap);

They are both XImages of the Pixmap I need to rotate.

Here's an example of a program that rotates huge images almost instantly:

Simple Image Viewer for Linux/X11: Xiv | Blog L�Ordikc