Bilinear interpolation
Please make everyone (including yourself) a favor :


Declare your variable in the smallest possible scope. Also define them as your declare them if you can (and you usually can).
Indent your code properly.


Then you'd get something like :

unsigned char *slow_rescale(unsigned char *src, int src_x, int src_y, int dest_x, int dest_y)
{
    unsigned char* dst=(unsigned char *)calloc(dest_x*dest_y*3,sizeof(unsigned char));   // Allocate and clear destination image
    if (!dst) return(NULL); // Unable to allocate image

    double step_x=(double)(src_x-1)/(double)(dest_x-1);
    double step_y=(double)(src_y-1)/(double)(dest_y-1);

    for (int x=0;x&lt;dest_x;x++) // Loop over destination image
    {
        for (int y=0;y&lt;dest_y;y++)
        {
            double fx=x*step_x;
            double fy=y*step_y;
            double dx=fx-(int)fx;
            double dy=fy-(int)fy;

            unsigned char R1,R2,R3,R4; // Colours at the four neighbours
            unsigned char G1,G2,G3,G4;
            unsigned char B1,B2,B3,B4;

            getPixel(src,floor(fx),floor(fy),src_x,&amp;R1,&amp;G1,&amp;B1); // get N1 colours
            getPixel(src,ceil(fx),floor(fy),src_x,&amp;R2,&amp;G2,&amp;B2); // get N2 colours
            getPixel(src,floor(fx),ceil(fy),src_x,&amp;R3,&amp;G3,&amp;B3); // get N3 colours
            getPixel(src,ceil(fx),ceil(fy),src_x,&amp;R4,&amp;G4,&amp;B4);  // get N4 colours
            // Interpolate to get T1 and T2 colours
            double RT1=(dx*R2)+(1-dx)*R1;
            double GT1=(dx*G2)+(1-dx)*G1;
            double BT1=(dx*B2)+(1-dx)*B1;
            double RT2=(dx*R4)+(1-dx)*R3;
            double GT2=(dx*G4)+(1-dx)*G3;
            double BT2=(dx*B4)+(1-dx)*B3;
            // Obtain final colour by interpolating between T1 and T2
            unsigned char R=(unsigned char)((dy*RT2)+((1-dy)*RT1));
            unsigned char G=(unsigned char)((dy*GT2)+((1-dy)*GT1));
            unsigned char B=(unsigned char)((dy*BT2)+((1-dy)*BT1));
            // Store the final colour
            setPixel(dst,x,y,dest_x,R,G,B);
        }
    }
    return(dst);
}
void getPixel(unsigned char *image, int x, int y, int sx, unsigned char *R, unsigned char *G, unsigned char *B)
{
    // Get the colour at pixel x,y in the image and return it using the provided RGB pointers
    // Requires the image size along the x direction!
    *(R)=*(image+((x+(y*sx))*3)+0);
    *(G)=*(image+((x+(y*sx))*3)+1);
    *(B)=*(image+((x+(y*sx))*3)+2);
}

void setPixel(unsigned char *image, int x, int y, int sx, unsigned char R, unsigned char G, unsigned char B)
{
    // Set the colour of the pixel at x,y in the image to the specified R,G,B
    // Requires the image size along the x direction!
    *(image+((x+(y*sx))*3)+0)=R;
    *(image+((x+(y*sx))*3)+1)=G;
    *(image+((x+(y*sx))*3)+2)=B;
}


Then, try to compute things once and only once when possible and you'll get something like :

unsigned char *slow_rescale(unsigned char *src, int src_x, int src_y, int dest_x, int dest_y)
{
    unsigned char* dst=(unsigned char *)calloc(dest_x*dest_y*3,sizeof(unsigned char));   // Allocate and clear destination image
    if (!dst) return(NULL); // Unable to allocate image

    double step_x=(double)(src_x-1)/(double)(dest_x-1);
    double step_y=(double)(src_y-1)/(double)(dest_y-1);

    for (int x=0;x&lt;dest_x;x++) // Loop over destination image
    {
        double fx=x*step_x;
        double dx=fx-(int)fx;
        int ffx = floor(fx);
        int cfx = ceil(fx);
        for (int y=0;y&lt;dest_y;y++)
        {
            double fy=y*step_y;
            double dy=fy-(int)fy;
            int ffy = floor(fy);
            int cfy = ceil(fy);

            unsigned char R1,R2,R3,R4,G1,G2,G3,G4,B1,B2,B3,B4;

            getPixel(src, (ffx + ffy*src_x)*3, &amp;R1,&amp;G1,&amp;B1); // get N1 colours
            getPixel(src, (cfx + ffy*src_x)*3, &amp;R2,&amp;G2,&amp;B2); // get N2 colours
            getPixel(src, (ffx + cfy*src_x)*3, &amp;R3,&amp;G3,&amp;B3); // get N3 colours
            getPixel(src, (cfx + cfy*src_x)*3, &amp;R4,&amp;G4,&amp;B4); // get N4 colours
            // Interpolate to get T1 and T2 colours
            double RT1 = dx*R2 + (1-dx)*R1;
            double GT1 = dx*G2 + (1-dx)*G1;
            double BT1 = dx*B2 + (1-dx)*B1;
            double RT2 = dx*R4 + (1-dx)*R3;
            double GT2 = dx*G4 + (1-dx)*G3;
            double BT2 = dx*B4 + (1-dx)*B3;
            // Obtain final colour by interpolating between T1 and T2
            unsigned char R = dy*RT2 + (1-dy)*RT1;
            unsigned char G = dy*GT2 + (1-dy)*GT1;
            unsigned char B = dy*BT2 + (1-dy)*BT1;
            // Store the final colour
            setPixel(dst, (x + y*dest_x)*3,R,G,B);
        }
    }
    return(dst);
}

inline void getPixel(unsigned char *image, int offset, unsigned char *R, unsigned char *G, unsigned char *B)
{
    *R=image[offset+0];
    *G=image[offset+1];
    *B=image[offset+2];
}

inline void setPixel(unsigned char *image, int offset, unsigned char R, unsigned char G, unsigned char B)
{
    image[offset+0]=R;
    image[offset+1]=G;
    image[offset+2]=B;
}


I'd expect this to be much much faster than your original code and to do roughtly the same thing (I have have introduced errors though).