#include #include #include #include #include #include #include "config.h" typedef enum { Full, Fill, Center, Tile } ImageMode; void usage (char *commandline) { printf (PACKAGE_STRING " - " DESCRIPTION "\n" "\n" "Syntaxis: %s [command1 [arg1..]] [command2 [arg1..]]..." "\n" "Gradients:\n" " -add Add color to range using distance 1\n" " -addd Add color to range using custom distance\n" " -gradient Render gradient using specified angle\n" " -clear Clear the color range\n" "\n" "Solid:\n" " -solid Render a solid using the specified color\n" "\n" "Image files:\n" " -center Render an image centered on screen\n" " -tile Render an image tiled\n" " -full Render an image maximum aspect\n" " -fill Render an image strechted\n" "\n" "Manipulations:\n" " -tint Tint the current image\n" " -blur Blur the current image\n" " -sharpen Sharpen the current image\n" " -contrast Adjust contrast of current image\n" " -brightness Adjust brightness of current image\n" " -gamma Adjust gamma level of current image\n" " -flipv Flip the current image vertically\n" " -fliph Flip the current image horizontally\n" " -flipd Flip the current image diagonally\n" "\n" "Misc:\n" " -alpha Adjust alpha level for colors and images\n" " -write Write current image to file\n" "\n" "Colors are in the #rrbbgg or #rrggbbaa format.\n" "\n" "Send bugreports to: " PACKAGE_BUGREPORT "\n" "\n", commandline); } // Globals: Display *display; int screen; // Adapted from fluxbox' bsetroot int setRootAtoms (Pixmap pixmap) { Atom atom_root, atom_eroot, type; unsigned char *data_root, *data_eroot; int format; unsigned long length, after; atom_root = XInternAtom (display, "_XROOTMAP_ID", True); atom_eroot = XInternAtom (display, "ESETROOT_PMAP_ID", True); // doing this to clean up after old background if (atom_root != None && atom_eroot != None) { XGetWindowProperty (display, RootWindow (display, screen), atom_root, 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, &data_root); if (type == XA_PIXMAP) { XGetWindowProperty (display, RootWindow (display, screen), atom_eroot, 0L, 1L, False, AnyPropertyType, &type, &format, &length, &after, &data_eroot); if (data_root && data_eroot && type == XA_PIXMAP && *((Pixmap *) data_root) == *((Pixmap *) data_eroot)) { XKillClient (display, *((Pixmap *) data_root)); } } } atom_root = XInternAtom (display, "_XROOTPMAP_ID", False); atom_eroot = XInternAtom (display, "ESETROOT_PMAP_ID", False); if (atom_root == None || atom_eroot == None) return 0; // setting new background atoms XChangeProperty (display, RootWindow (display, screen), atom_root, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pixmap, 1); XChangeProperty (display, RootWindow (display, screen), atom_eroot, XA_PIXMAP, 32, PropModeReplace, (unsigned char *) &pixmap, 1); return 1; } typedef struct { int r, g, b, a; } Color, *PColor; int getHex (char c) { switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': return c - '0'; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': return c - 'A' + 10; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': return c - 'a' + 10; default: return 0; } } int parse_color (char *arg, PColor c, int a) { if (arg[0] != '#') return 0; if ((strlen (arg) != 7) && (strlen (arg) != 9)) return 0; c->r = getHex (arg[1]) * 16 + getHex (arg[2]); c->g = getHex (arg[3]) * 16 + getHex (arg[4]); c->b = getHex (arg[5]) * 16 + getHex (arg[6]); c->a = a; if (strlen (arg) == 9) c->a = getHex (arg[7]) * 16 + getHex (arg[8]); return 1; } int load_image (ImageMode mode, const char *arg, int rootW, int rootH, int alpha, Imlib_Image rootimg) { int imgW, imgH, o; Imlib_Image buffer = imlib_load_image (arg); if (!buffer) return 0; imlib_context_set_image (buffer); imgW = imlib_image_get_width (), imgH = imlib_image_get_height (); if (alpha < 255) { // Create alpha-override mask imlib_image_set_has_alpha (1); Imlib_Color_Modifier modifier = imlib_create_color_modifier (); imlib_context_set_color_modifier (modifier); DATA8 red[256], green[256], blue[256], alph[256]; imlib_get_color_modifier_tables (red, green, blue, alph); for (o = 0; o < 256; o++) alph[o] = (DATA8) alpha; imlib_set_color_modifier_tables (red, green, blue, alph); imlib_apply_color_modifier (); imlib_free_color_modifier (); } imlib_context_set_image (rootimg); if (mode == Fill) { imlib_blend_image_onto_image (buffer, 0, 0, 0, imgW, imgH, 0, 0, rootW, rootH); } else if (mode == Full) { double aspect = ((double) rootW) / imgW; int top, left; if ((int) (imgH * aspect) > rootH) aspect = (double) rootH / (double) imgH; top = (rootH - (int) (imgH * aspect)) / 2; left = (rootW - (int) (imgW * aspect)) / 2; imlib_blend_image_onto_image (buffer, 0, 0, 0, imgW, imgH, left, top, (int) (imgW * aspect), (int) (imgH * aspect)); } else { int left = (rootW - imgW) / 2, top = (rootH - imgH) / 2; if (mode == Tile) { int x, y; for (; left > 0; left -= imgW); for (; top > 0; top -= imgH); for (x = left; x < rootW; x += imgW) for (y = top; y < rootH; y += imgH) imlib_blend_image_onto_image (buffer, 0, 0, 0, imgW, imgH, x, y, imgW, imgH); } else { imlib_blend_image_onto_image (buffer, 0, 0, 0, imgW, imgH, left, top, imgW, imgH); } } imlib_context_set_image (buffer); imlib_free_image (); imlib_context_set_image (rootimg); return 1; } int main (int argc, char **argv) { Visual *vis; Colormap cm; Display *_display; Imlib_Context *context; Imlib_Image image; int width, height, depth, i, alpha; Pixmap pixmap; Imlib_Color_Modifier modifier = NULL; _display = XOpenDisplay (NULL); for (screen = 0; screen < ScreenCount (_display); screen++) { display = XOpenDisplay (NULL); context = imlib_context_new (); imlib_context_push (context); imlib_context_set_display (display); vis = DefaultVisual (display, screen); cm = DefaultColormap (display, screen); width = DisplayWidth (display, screen); height = DisplayHeight (display, screen); depth = DefaultDepth (display, screen); pixmap = XCreatePixmap (display, RootWindow (display, screen), width, height, depth); imlib_context_set_visual (vis); imlib_context_set_colormap (cm); imlib_context_set_drawable (pixmap); imlib_context_set_color_range (imlib_create_color_range ()); image = imlib_create_image (width, height); imlib_context_set_image (image); imlib_context_set_color (0, 0, 0, 255); imlib_image_fill_rectangle (0, 0, width, height); imlib_context_set_dither (1); imlib_context_set_blend (1); alpha = 255; for (i = 1; i < argc; i++) { if (modifier != NULL) { imlib_apply_color_modifier (); imlib_free_color_modifier (); } modifier = imlib_create_color_modifier (); imlib_context_set_color_modifier (modifier); if (strcmp (argv[i], "-alpha") == 0) { if ((++i) >= argc) { fprintf (stderr, "Missing alpha\n"); continue; } if (sscanf (argv[i], "%i", &alpha) == 0) { fprintf (stderr, "Bad alpha (%s)\n", argv[i]); continue; } } else if (strcmp (argv[i], "-solid") == 0) { Color c; if ((++i) >= argc) { fprintf (stderr, "Missing color\n"); continue; } if (parse_color (argv[i], &c, alpha) == 0) { fprintf (stderr, "Bad color (%s)\n", argv[i]); continue; } imlib_context_set_color (c.r, c.g, c.b, c.a); imlib_image_fill_rectangle (0, 0, width, height); } else if (strcmp (argv[i], "-clear") == 0) { imlib_free_color_range (); imlib_context_set_color_range (imlib_create_color_range ()); } else if (strcmp (argv[i], "-add") == 0) { Color c; if ((++i) >= argc) { fprintf (stderr, "Missing color\n"); continue; } if (parse_color (argv[i], &c, alpha) == 0) { fprintf (stderr, "Bad color (%s)\n", argv[i - 1]); continue; } imlib_context_set_color (c.r, c.g, c.b, c.a); imlib_add_color_to_color_range (1); } else if (strcmp (argv[i], "-addd") == 0) { Color c; int distance; if ((++i) >= argc) { fprintf (stderr, "Missing color\n"); continue; } if ((++i) >= argc) { fprintf (stderr, "Missing distance\n"); continue; } if (parse_color (argv[i - 1], &c, alpha) == 0) { fprintf (stderr, "Bad color (%s)\n", argv[i - 1]); continue; } if (sscanf (argv[i], "%i", &distance) == 0) { fprintf (stderr, "Bad distance (%s)\n", argv[i]); continue; } imlib_context_set_color (c.r, c.g, c.b, c.a); imlib_add_color_to_color_range (distance); } else if (strcmp (argv[i], "-gradient") == 0) { int angle; if ((++i) >= argc) { fprintf (stderr, "Missing angle\n"); continue; } if (sscanf (argv[i], "%i", &angle) == 0) { fprintf (stderr, "Bad angle (%s)\n", argv[i]); continue; } imlib_image_fill_color_range_rectangle (0, 0, width, height, angle); } else if (strcmp (argv[i], "-fill") == 0) { if ((++i) >= argc) { fprintf (stderr, "Missing image\n"); continue; } if (load_image (Fill, argv[i], width, height, alpha, image) == 0) { fprintf (stderr, "Bad image (%s)\n", argv[i]); continue; } } else if (strcmp (argv[i], "-full") == 0) { if ((++i) >= argc) { fprintf (stderr, "Missing image\n"); continue; } if (load_image (Full, argv[i], width, height, alpha, image) == 0) { fprintf (stderr, "Bad image (%s)\n", argv[i]); continue; } } else if (strcmp (argv[i], "-tile") == 0) { if ((++i) >= argc) { fprintf (stderr, "Missing image\n"); continue; } if (load_image (Tile, argv[i], width, height, alpha, image) == 0) { fprintf (stderr, "Bad image (%s)\n", argv[i]); continue; } } else if (strcmp (argv[i], "-center") == 0) { if ((++i) >= argc) { fprintf (stderr, "Missing image\n"); continue; } if (load_image (Center, argv[i], width, height, alpha, image) == 0) { fprintf (stderr, "Bad image (%s)\n", argv[i]); continue; } } else if (strcmp (argv[i], "-tint") == 0) { Color c; DATA8 r[256], g[256], b[256], a[256]; int j; if ((++i) >= argc) { fprintf (stderr, "Missing color\n"); continue; } if (parse_color (argv[i], &c, 255) == 0) { fprintf (stderr, "Bad color\n"); continue; } imlib_get_color_modifier_tables (r, g, b, a); for (j = 0; j < 256; j++) { r[j] = (DATA8) (((double) r[j] / 255.0) * (double) c.r); g[j] = (DATA8) (((double) g[j] / 255.0) * (double) c.g); b[j] = (DATA8) (((double) b[j] / 255.0) * (double) c.b); } imlib_set_color_modifier_tables (r, g, b, a); } else if (strcmp (argv[i], "-blur") == 0) { int intval; if ((++i) >= argc) { fprintf (stderr, "Missing value\n"); continue; } if (sscanf (argv[i], "%i", &intval) == 0) { fprintf (stderr, "Bad value (%s)\n", argv[i]); continue; } imlib_image_blur (intval); } else if (strcmp (argv[i], "-sharpen") == 0) { int intval; if ((++i) >= argc) { fprintf (stderr, "Missing value\n"); continue; } if (sscanf (argv[i], "%i", &intval) == 0) { fprintf (stderr, "Bad value (%s)\n", argv[i]); continue; } imlib_image_sharpen (intval); } else if (strcmp (argv[i], "-contrast") == 0) { double dblval; if ((++i) >= argc) { fprintf (stderr, "Missing value\n"); continue; } if (sscanf (argv[i], "%lf", &dblval) == 0) { fprintf (stderr, "Bad value (%s)\n", argv[i]); continue; } imlib_modify_color_modifier_contrast (dblval); } else if (strcmp (argv[i], "-brightness") == 0) { double dblval; if ((++i) >= argc) { fprintf (stderr, "Missing value\n"); continue; } if (sscanf (argv[i], "%lf", &dblval) == 0) { fprintf (stderr, "Bad value (%s)\n", argv[i]); continue; } imlib_modify_color_modifier_brightness (dblval); } else if (strcmp (argv[i], "-gamma") == 0) { double dblval; if ((++i) >= argc) { fprintf (stderr, "Missing value\n"); continue; } if (sscanf (argv[i], "%lf", &dblval) == 0) { fprintf (stderr, "Bad value (%s)\n", argv[i]); continue; } imlib_modify_color_modifier_gamma (dblval); } else if (strcmp (argv[i], "-flipv") == 0) { imlib_image_flip_vertical (); } else if (strcmp (argv[i], "-fliph") == 0) { imlib_image_flip_horizontal (); } else if (strcmp (argv[i], "-flipd") == 0) { imlib_image_flip_diagonal (); } else if (strcmp (argv[i], "-write") == 0) { if ((++i) >= argc) { fprintf (stderr, "Missing filename\n"); continue; } imlib_save_image (argv[i]); } else { usage (argv[0]); imlib_free_image (); imlib_free_color_range (); if (modifier != NULL) { imlib_context_set_color_modifier (modifier); imlib_free_color_modifier (); modifier = NULL; } XFreePixmap (display, pixmap); exit (1); } } if (modifier != NULL) { imlib_context_set_color_modifier (modifier); imlib_apply_color_modifier (); imlib_free_color_modifier (); modifier = NULL; } imlib_render_image_on_drawable (0, 0); imlib_free_image (); imlib_free_color_range (); if (setRootAtoms (pixmap) == 0) fprintf (stderr, "Couldn't create atoms...\n"); XKillClient (display, AllTemporary); XSetCloseDownMode (display, RetainTemporary); XSetWindowBackgroundPixmap (display, RootWindow (display, screen), pixmap); XClearWindow (display, RootWindow (display, screen)); XFlush (display); XSync (display, False); imlib_context_pop (); imlib_context_free (context); } return 0; }