#include <stdio.h>
#include <math.h>
#include <X11/Intrinsic.h>
    
#define min(x, y) (x > y ? y : x)
#define max(x, y) (x < y ? y : x)
#define DataSize(bytes_per_line, height, depth, format)\
(format == ZPixmap ? bytes_per_line * height : bytes_per_line * height * depth)

typedef struct {
    Position *x, *y;
    Dimension *width, *height;
} Table;

XImage *ScaleImage(src, width, height)
    XImage *src;
    double width, height;
{
    XImage *dst;
    Table table;
    
    Position x, y, w, h;
    Pixel pixel;
     
    fprintf(stderr, "Scaling %lf %lf...\n", width, height);

    /*
     * Create a copy of src image with new
     * width, height, bytes_per_line and data
     */
    dst = (XImage *) XtMalloc(sizeof(XImage));
    bcopy(src, dst, sizeof(XImage));
    dst->width = max(rint(width * src->width), 1);
    dst->height = max(rint(height * src->height), 1);
    dst->bytes_per_line = ceil(dst->width * src->bytes_per_line 
			       / (double) src->width);
    dst->data = XtMalloc(sizeof(char) * DataSize(dst->bytes_per_line,
						 dst->height, 
						 dst->depth,
						 dst->format));
    /*
     * It would be nice to check if width or height < 1.0 and
     * average the skipped pixels. Though it is slow as it is now.
     */
    if (width == 1.0 && height == 1.0)
	bcopy(src->data, dst->data, DataSize(dst->bytes_per_line,
					     dst->height,
					     dst->depth,
					     dst->format));
    else {
	table.x = (Position *) XtMalloc(sizeof(Position) * src->width);
	table.y = (Position *) XtMalloc(sizeof(Position) * src->height);
	table.width = (Dimension *) XtMalloc(sizeof(Dimension) * src->width);
	table.height = (Dimension *) XtMalloc(sizeof(Dimension) * src->height);
	
	for (x = 0; x < src->width; x++) {
	    table.x[x] = rint(width * x);
	    table.width[x] = rint(width * (x + 1)) - rint(width * x);
	}
	for (y = 0; y < src->height; y++) {
	    table.y[y] = rint(height * y);
	    table.height[y] = rint(height * (y + 1)) - rint(height * y);
	}
	
	for (x = 0; x < src->width; x++)
	    for (y = 0; y < src->height; y++) {
		pixel = XGetPixel(src, x, y);
		for (w = 0; w < table.width[x]; w++)
		    for (h = 0; h < table.height[y]; h++) {
			XPutPixel(dst, 
				  table.x[x] + w, 
				  table.y[y] + h, 
				  pixel);
		    }
	    }
	
	XtFree(table.x);
	XtFree(table.y);
	XtFree(table.width);
	XtFree(table.height);
    }
    
    return (dst);
}
