/* Scaling Pixmap. Ryzen 5 5600x + VMware Player + Ubuntu Linux 20.04 LTS. 1920 x 1080. slow result : 0.510753 sec fast result : 0.000045 sec */ #include #include #include #include #include #include #include /* include xpm binary */ #include "bg01.xpm" #define XPM_W 640 #define XPM_H 360 #define XPM_NAME bg01_xpm /* #include "bg02.xpm" #define XPM_W 320 #define XPM_H 180 #define XPM_NAME bg02_xpm */ /* kind. 0: slow, 1: fast */ #define SCALING_KIND 1 #define WIN_X 0 #define WIN_Y 64 #define BORDER 0 #ifndef M_PI #define M_PI 3.14159265358979 #endif #define deg2rad(x) (x * M_PI / 180.0) /* get a color value from a color name */ static unsigned long get_color(Display *dpy, char *colorname) { Colormap cmap; XColor near_color, true_color; cmap = DefaultColormap(dpy, DefaultScreen(dpy)); XAllocNamedColor(dpy, cmap, colorname, &near_color, &true_color); return near_color.pixel; } /* scale Pixmap */ static void scale_pixmap(Display *dpy, Drawable win, Pixmap *src, Pixmap *dst, int src_w, int src_h, int dst_w, int dst_h) { GC gc; float xscale, yscale; int x, y; struct timespec start, end; double diff; xscale = (float)src_w / dst_w; yscale = (float)src_h / dst_h; gc = XCreateGC(dpy, win, 0, 0); XSetGraphicsExposures(dpy, gc, False); timespec_get(&start, TIME_UTC); switch (SCALING_KIND) { case 0: /* slow */ for (y = 0; y < dst_h; y++) { int sy = (int)(y * yscale); for (x = 0; x < dst_w; x++) XCopyArea(dpy, *src, *dst, gc, (int)(x * xscale), sy, 1, 1, x, y); } break; case 1: /* fast */ for (x = dst_w - 1; x >= 0; x--) XCopyArea(dpy, *src, *dst, gc, (int)(x * xscale), 0, 1, src_h, x, 0); for (y = dst_h - 1; y >= 0; y--) XCopyArea(dpy, *dst, *dst, gc, 0, (int)(y * yscale), dst_w, 1, 0, y); break; default: break; } XFreeGC(dpy, gc); timespec_get(&end, TIME_UTC); diff = (end.tv_sec + (double)end.tv_nsec / 1000000000) - (start.tv_sec + (double)start.tv_nsec / 1000000000); printf("%lf sec\n", diff); } /* update and draw */ static void update(Display *dpy, Drawable win, GC gc, double ang, Pixmap pix, Pixmap buf) { XWindowAttributes xgwa; int r, x, y; int buf_w, buf_h; /* get window attributes */ XGetWindowAttributes(dpy, win, &xgwa); buf_w = xgwa.width; /* window width */ buf_h = xgwa.height; /* window height */ scale_pixmap(dpy, win, &pix, &buf, XPM_W, XPM_H, buf_w, buf_h); r = 64; x = 0; /* x = r * cos(deg2rad(ang)); */ y = r * sin(deg2rad(ang)); /* clear window */ XClearWindow(dpy, win); /* draw image (Pixmap) */ XSetGraphicsExposures(dpy, gc, False); XCopyArea(dpy, buf, win, gc, 0, 0, buf_w, buf_h, x, y); /* copy Pixmap */ } int main(void) { Display *dpy; Window root; Window win; int screen; int display_w, display_h; XEvent evt; unsigned long black, white; XWindowAttributes xgwa; GC gc; Pixmap pix; Pixmap buf; int busy_loop; double ang; /* open display */ dpy = XOpenDisplay(NULL); root = DefaultRootWindow(dpy); screen = DefaultScreen(dpy); /* get display size */ display_w = DisplayWidth(dpy, screen); display_h = DisplayHeight(dpy, screen); printf("Screen: %d x %d\n", display_w, display_h); /* get color black and white */ white = WhitePixel(dpy, screen); black = BlackPixel(dpy, screen); /* create window */ win = XCreateSimpleWindow(dpy, root, WIN_X, WIN_Y, display_w, display_h, BORDER, white, black); XSelectInput(dpy, win, KeyPressMask | ExposureMask); XMapWindow(dpy, win); /* wait display window */ do { XNextEvent(dpy, &evt); } while (evt.type != Expose); XMoveWindow(dpy, win, WIN_X, WIN_Y); /* create graphics context */ gc = XCreateGC(dpy, win, 0, 0); XSetGraphicsExposures(dpy, gc, False); /* load image */ if (XpmCreatePixmapFromData(dpy, win, XPM_NAME, &pix, NULL, NULL)) { fprintf(stderr, "Error not load xpm."); return 1; } XGetWindowAttributes(dpy, win, &xgwa); buf = XCreatePixmap(dpy, win, display_w, display_h, xgwa.depth); XSetForeground(dpy, gc, get_color(dpy, "green")); XFillRectangle(dpy, buf, gc, 0, 0, display_w, display_h); ang = 0; busy_loop = 1; while (busy_loop) { /* event */ while (XPending(dpy)) { XNextEvent(dpy, &evt); switch (evt.type) { /* case Expose: if (evt.xexpose.count == 0) { } break; */ case KeyPress: busy_loop = 0; break; default: break; } } update(dpy, win, gc, ang, pix, buf); ang += 4.0; if (ang >= 360) ang -= 360; XFlush(dpy); usleep(16 * 1000); /* wait */ } XFreePixmap(dpy, pix); XFreePixmap(dpy, buf); XFreeGC(dpy, gc); XDestroyWindow(dpy, win); XCloseDisplay(dpy); return 0; }