void execp_dump_geometry(void *obj, int indent) { Execp *execp = obj; if (execp->backend->has_icon && execp->backend->icon) { Imlib_Image tmp = imlib_context_get_image(); imlib_context_set_image(execp->backend->icon); fprintf(stderr, "%*sIcon: x = %d, y = %d, w = %d, h = %d\n", indent, "", execp->frontend->iconx, execp->frontend->icony, imlib_image_get_width(), imlib_image_get_height()); if (tmp) imlib_context_set_image(tmp); } fprintf(stderr, "%*sText: x = %d, y = %d, w = %d, align = %s, text = %s\n", indent, "", execp->frontend->textx, execp->frontend->texty, execp->frontend->textw, execp->backend->centered ? "center" : "left", execp->backend->text); }
/* draw a white (background) border around image, overwriting image contents * beneath border*/ Imlib_Image white_border(Imlib_Image *source_image, int bdwidth) { Imlib_Image new_image; /* construct filtered image here */ Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int x,y; /* coordinates of upper left corner of rectangles */ /* save pointer to current image */ current_image = imlib_context_get_image(); /* create a new image */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); new_image = imlib_clone_image(); /* assure border width has a legal value */ if(bdwidth > width/2) bdwidth = width/2; if(bdwidth > height/2) bdwidth = height/2; /* draw white (background) rectangle around new image */ for(x=0, y=0; x<bdwidth; x++, y++) { imlib_context_set_image(new_image); ssocr_set_color(BG); imlib_image_draw_rectangle(x, y, width-2*x, height-2*y); } /* restore image from before function call */ imlib_context_set_image(current_image); /* return filtered image */ return new_image; }
/* crop image */ Imlib_Image crop(Imlib_Image *source_image, int x, int y, int w, int h) { Imlib_Image new_image; /* construct filtered image here */ Imlib_Image current_image; /* save image pointer */ int width, height; /* source image dimensions */ /* save pointer to current image */ current_image = imlib_context_get_image(); /* get width and height of source image */ imlib_context_set_image(*source_image); width = imlib_image_get_width(); height = imlib_image_get_height(); /* get sane values */ if(x < 0) x = 0; if(y < 0) y = 0; if(x >= width) x = width - 1; if(y >= height) y = height - 1; if(x + w > width) w = width - x; if(y + h > height) h = height - x; /* create the new image */ imlib_context_set_image(*source_image); new_image = imlib_create_cropped_image(x, y, w, h); /* restore image from before function call */ imlib_context_set_image(current_image); /* return filtered image */ return new_image; }
/* draw a fore- or background pixel */ void draw_pixel(Imlib_Image *image, int x, int y, fg_bg_t color) { Imlib_Image *current_image; /* save current image */ current_image = imlib_context_get_image(); imlib_context_set_image(image); ssocr_set_color(color); imlib_image_draw_pixel(x,y,0); imlib_context_set_image(current_image); }
/* set pixels that have at least mask pixels around it set (including the * examined pixel itself) to black (foreground), all other pixels to white * (background) */ Imlib_Image set_pixels_filter(Imlib_Image *source_image, double thresh, luminance_t lt, int mask) { Imlib_Image new_image; /* construct filtered image here */ Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int x,y,i,j; /* iteration variables */ int set_pixel; /* should pixel be set or not? */ Imlib_Color color; int lum; /* luminance value of pixel */ /* save pointer to current image */ current_image = imlib_context_get_image(); /* create a new image */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); new_image = imlib_clone_image(); /* check for every pixel if it should be set in filtered image */ for(x=0; x<width; x++) { for(y=0; y<height; y++) { set_pixel=0; for(i=x-1; i<=x+1; i++) { for(j=y-1; j<=y+1; j++) { if(i>=0 && i<width && j>=0 && j<height) { /* i,j inside image? */ imlib_image_query_pixel(i, j, &color); lum = get_lum(&color, lt); if(is_pixel_set(lum, thresh)) { set_pixel++; } } } } /* set pixel if at least mask pixels around it are set */ if(set_pixel >= mask) { draw_fg_pixel(new_image, x, y); } else { draw_bg_pixel(new_image, x, y); } } } /* restore image from before function call */ imlib_context_set_image(current_image); /* return filtered image */ return new_image; }
/* mirror image horizontally or vertically */ Imlib_Image mirror(Imlib_Image *source_image, mirror_t direction) { Imlib_Image new_image; /* construct filtered image here */ Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int x,y; /* iteration variables / target coordinates */ Imlib_Color color_return; /* for imlib_query_pixel() */ /* save pointer to current image */ current_image = imlib_context_get_image(); /* create a new image */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); new_image = imlib_clone_image(); /* create mirrored image */ if(direction == HORIZONTAL) { for(x = width-1; x>=0; x--) { for(y = 0; y < height; y++) { imlib_image_query_pixel(width - 1 - x, y, &color_return); imlib_context_set_image(new_image); imlib_context_set_color(color_return.red, color_return.green, color_return.blue, color_return.alpha); imlib_image_draw_pixel(x,y,0); imlib_context_set_image(*source_image); } } } else if(direction == VERTICAL) { for(x = 0; x < width; x++) { for(y = height-1; y >= 0; y--) { imlib_image_query_pixel(x, height - 1 - y, &color_return); imlib_context_set_image(new_image); imlib_context_set_color(color_return.red, color_return.green, color_return.blue, color_return.alpha); imlib_image_draw_pixel(x,y,0); imlib_context_set_image(*source_image); } } } /* restore image from before function call */ imlib_context_set_image(current_image); /* return filtered image */ return new_image; }
/* rotate the image */ Imlib_Image rotate(Imlib_Image *source_image, double theta) { Imlib_Image new_image; /* construct filtered image here */ Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int x,y; /* iteration variables / target coordinates */ int sx,sy; /* source coordinates */ Imlib_Color color_return; /* for imlib_query_pixel() */ /* save pointer to current image */ current_image = imlib_context_get_image(); /* create a new image */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); new_image = imlib_clone_image(); /* convert theta from degrees to radians */ theta = theta / 360 * 2.0 * M_PI; /* create rotated image * (some parts of the original image will be lost) */ for(x = 0; x < width; x++) { for(y = 0; y < height; y++) { sx = (x-width/2) * cos(theta) + (y-height/2) * sin(theta) + width/2; sy = (y-height/2) * cos(theta) - (x-width/2) * sin(theta) + height/2; if((sx >= 0) && (sx <= width) && (sy >= 0) && (sy <= height)) { imlib_image_query_pixel(sx, sy, &color_return); imlib_context_set_image(new_image); imlib_context_set_color(color_return.red, color_return.green, color_return.blue, color_return.alpha); } else { imlib_context_set_image(new_image); ssocr_set_color(BG); } imlib_image_draw_pixel(x,y,0); imlib_context_set_image(*source_image); } } /* restore image from before function call */ imlib_context_set_image(current_image); /* return filtered image */ return new_image; }
/* compute dynamic threshold value from the rectangle (x,y),(x+w,y+h) of * source_image */ double get_threshold(Imlib_Image *source_image, double fraction, luminance_t lt, int x, int y, int w, int h) { Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int xi,yi; /* iteration variables */ Imlib_Color color; int lum; /* luminance of pixel */ double minval=(double)MAXRGB, maxval=0.0; /* save pointer to current image */ current_image = imlib_context_get_image(); /* get image dimensions */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); /* special value -1 for width or height means image width/height */ if(w == -1) w = width; if(h == -1) h = width; /* assure valid coordinates */ if(x+w > width) x = width-w; if(y+h > height) y = height-h; if(x<0) x=0; if(y<0) y=0; /* find the threshold value to differentiate between dark and light */ for(xi=0; (xi<w) && (xi<width); xi++) { for(yi=0; (yi<h) && (yi<height); yi++) { imlib_image_query_pixel(x+xi, y+yi, &color); lum = get_lum(&color, lt); if(lum < minval) minval = lum; if(lum > maxval) maxval = lum; } } /* restore image from before function call */ imlib_context_set_image(current_image); return (minval + fraction * (maxval - minval)) * 100 / MAXRGB; }
/* shear the image * the top line is unchanged * the bottom line is moved offset pixels to the right * the other lines are moved yPos*offset/(height-1) pixels to the right * white pixels are inserted at the left side */ Imlib_Image shear(Imlib_Image *source_image, int offset) { Imlib_Image new_image; /* construct filtered image here */ Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int x,y; /* iteration variables */ int shift; /* current shift-width */ Imlib_Color color_return; /* for imlib_query_pixel() */ /* save pointer to current image */ current_image = imlib_context_get_image(); /* create a new image */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); new_image = imlib_clone_image(); /* move every line to the right */ for(y=1; y<height; y++) { shift = y * offset / (height-1); /* copy pixels */ for(x=width-1; x>=shift; x--) { imlib_image_query_pixel(x-shift, y, &color_return); imlib_context_set_image(new_image); imlib_context_set_color(color_return.red, color_return.green, color_return.blue, color_return.alpha); imlib_image_draw_pixel(x,y,0); imlib_context_set_image(*source_image); } /* fill with background */ for(x=0; x<shift; x++) { draw_bg_pixel(new_image, x, y); } } /* restore image from before function call */ imlib_context_set_image(current_image); /* return filtered image */ return new_image; }
/* get maximum luminance value */ double get_maxval(Imlib_Image *source_image, int x, int y, int w, int h, luminance_t lt) { Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int xi,yi; /* iteration variables */ Imlib_Color color; /* Imlib2 RGBA color structure */ int lum = 0; int maxval = 0; /* save pointer to current image */ current_image = imlib_context_get_image(); /* get image dimensions */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); /* special value -1 for width or height means image width/height */ if(w == -1) w = width; if(h == -1) h = width; /* assure valid coordinates */ if(x+w > width) x = width-w; if(y+h > height) y = height-h; if(x<0) x=0; if(y<0) y=0; /* find the minimum value in the image */ for(xi=0; (xi<w) && (xi<width); xi++) { for(yi=0; (yi<h) && (yi<height); yi++) { imlib_image_query_pixel(xi, yi, &color); lum = clip(get_lum(&color, lt),0,255); if(lum > maxval) maxval = lum; } } /* restore image from before function call */ imlib_context_set_image(current_image); return maxval; }
/* save image to file */ void save_image(const char *image_type, Imlib_Image *image, const char *fmt, const char *filename, int flags) { const char *tmp; Imlib_Image *current_image; Imlib_Load_Error save_error=0; const char *const stdout_file = "/proc/self/fd/1"; current_image = imlib_context_get_image(); imlib_context_set_image(image); /* interpret - as STDOUT */ if(strcmp("-", filename) == 0) filename = stdout_file; /* get file format for image */ if(fmt) { /* use provided format string */ tmp = fmt; } else { /* use file name extension */ tmp = strrchr(filename, '.'); if(tmp) tmp++; } if(tmp) { if(flags & VERBOSE) fprintf(stderr, "using %s format for %s image\n", tmp, image_type); imlib_image_set_format(tmp); } else { /* use png as default */ if(flags & VERBOSE) fprintf(stderr, "using png format for %s image\n", image_type); imlib_image_set_format("png"); } /* write image to disk */ if(flags & VERBOSE) fprintf(stderr, "writing %s image to file %s\n", image_type, filename); imlib_save_image_with_error_return(filename, &save_error); if(save_error && save_error != IMLIB_LOAD_ERROR_NONE) { fprintf(stderr, "error saving image file %s\n", filename); report_imlib_error(save_error); } imlib_context_set_image(current_image); }
/* ww and wh are the width and height of the rectangle used to find the * threshold value */ Imlib_Image dynamic_threshold(Imlib_Image *source_image,double t,luminance_t lt, int ww, int wh) { Imlib_Image new_image; /* construct filtered image here */ Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int x,y; /* iteration variables */ Imlib_Color color; int lum; double thresh; /* save pointer to current image */ current_image = imlib_context_get_image(); /* create a new image */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); new_image = imlib_clone_image(); /* check for every pixel if it should be set in filtered image */ for(x=0; x<width; x++) { for(y=0; y<height; y++) { imlib_image_query_pixel(x, y, &color); lum = get_lum(&color, lt); thresh = get_threshold(source_image, t/100.0, lt, x-ww/2, y-ww/2, ww, wh); if(is_pixel_set(lum, thresh)) { draw_fg_pixel(new_image, x, y); } else { draw_bg_pixel(new_image, x, y); } } } /* restore image from before function call */ imlib_context_set_image(current_image); /* return filtered image */ return new_image; }
/* turn image to grayscale */ Imlib_Image grayscale(Imlib_Image *source_image, luminance_t lt) { Imlib_Image new_image; /* construct grayscale image here */ Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int x,y; /* iteration variables */ Imlib_Color color; /* Imlib2 color structure */ int lum=0; /* save pointer to current image */ current_image = imlib_context_get_image(); /* create a new image */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); new_image = imlib_clone_image(); /* transform image to grayscale */ for(x=0; x<width; x++) { for(y=0; y<height; y++) { imlib_context_set_image(*source_image); imlib_image_query_pixel(x, y, &color); imlib_context_set_image(new_image); lum = clip(get_lum(&color, lt),0,255); imlib_context_set_color(lum, lum, lum, color.alpha); imlib_image_draw_pixel(x, y, 0); } } /* restore image from before function call */ imlib_context_set_image(current_image); /* return filtered image */ return new_image; }
/* determine threshold by an iterative method */ double iterative_threshold(Imlib_Image *source_image, double thresh, luminance_t lt, int x, int y, int w, int h) { Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int xi,yi; /* iteration variables */ Imlib_Color color; int lum; /* luminance of pixel */ unsigned int size_white, size_black; /* size of black and white groups */ unsigned long int sum_white, sum_black; /* sum of black and white groups */ unsigned int avg_white, avg_black; /* average values of black and white */ double old_thresh; /* old threshold computed by last iteration step */ double new_thresh; /* new threshold computed by current iteration step */ int thresh_lum; /* luminance value of threshold */ /* normalize threshold (was given as a percentage) */ new_thresh = thresh / 100.0; /* save pointer to current image */ current_image = imlib_context_get_image(); /* get image dimensions */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); /* special value -1 for width or height means image width/height */ if(w == -1) w = width; if(h == -1) h = width; /* assure valid coordinates */ if(x+w > width) x = width-w; if(y+h > height) y = height-h; if(x<0) x=0; if(y<0) y=0; /* find the threshold value to differentiate between dark and light */ do { thresh_lum = MAXRGB * new_thresh; old_thresh = new_thresh; size_black = sum_black = size_white = sum_white = 0; for(xi=0; (xi<w) && (xi<width); xi++) { for(yi=0; (yi<h) && (yi<height); yi++) { imlib_image_query_pixel(xi, yi, &color); lum = get_lum(&color, lt); if(lum <= thresh_lum) { size_black++; sum_black += lum; } else { size_white++; sum_white += lum; } } } if(!size_white) { fprintf(stderr, "iterative_threshold(): error: no white pixels\n"); imlib_context_set_image(current_image); return thresh; } if(!size_black) { fprintf(stderr, "iterative_threshold(): error: no black pixels\n"); imlib_context_set_image(current_image); return thresh; } avg_white = sum_white / size_white; avg_black = sum_black / size_black; new_thresh = (avg_white + avg_black) / (2.0 * MAXRGB); /*fprintf(stderr, "iterative_threshold(): new_thresh = %f\n", new_thresh);*/ } while(fabs(new_thresh - old_thresh) > EPSILON); /* restore image from before function call */ imlib_context_set_image(current_image); return new_thresh * 100; }
/* gray stretching, i.e. lum<t1 => lum=0, lum>t2 => lum=100, * else lum=((lum-t1)*MAXRGB)/(t2-t1) */ Imlib_Image gray_stretch(Imlib_Image *source_image, double t1, double t2, luminance_t lt) { Imlib_Image new_image; /* construct filtered image here */ Imlib_Image current_image; /* save image pointer */ int height, width; /* image dimensions */ int x,y; /* iteration variables */ Imlib_Color color; int lum; /* luminance value of pixel */ /* do nothing if t1>=t2 */ if(t1 >= t2) { fprintf(stderr, "error: gray_stretch(): t1=%.2f >= t2=%.2f\n", t1, t2); exit(99); } /* check if 0 < t1,t2 < MAXRGB */ if(t1 <= 0.0) { fprintf(stderr, "error: gray_stretch(): t1=%.2f <= 0.0\n", t1); exit(99); } if(t2 >= MAXRGB) { fprintf(stderr, "error: gray_stretch(): t2=%.2f >= %d.0\n", t2, MAXRGB); exit(99); } /* save pointer to current image */ current_image = imlib_context_get_image(); /* create a new image */ imlib_context_set_image(*source_image); height = imlib_image_get_height(); width = imlib_image_get_width(); new_image = imlib_clone_image(); /* gray stretch image */ for(x=0; x<width; x++) { for(y=0; y<height; y++) { imlib_image_query_pixel(x, y, &color); lum = get_lum(&color, lt); imlib_context_set_image(new_image); if(lum<=t1) { imlib_context_set_color(0, 0, 0, color.alpha); } else if(lum>=t2) { imlib_context_set_color(MAXRGB, MAXRGB, MAXRGB, color.alpha); } else { imlib_context_set_color(clip(((lum-t1)*255)/(t2-t1),0,255), clip(((lum-t1)*255)/(t2-t1),0,255), clip(((lum-t1)*255)/(t2-t1),0,255), color.alpha); } imlib_image_draw_pixel(x, y, 0); imlib_context_set_image(*source_image); } } /* restore image from before function call */ imlib_context_set_image(current_image); /* return filtered image */ return new_image; }
/* * Load & display image */ void qiv_load_image(qiv_image *q) { /* Don't initialize most variables here, initialize them after load_next_image: */ struct stat st; const char *image_name; Imlib_Image *im; struct timeval load_before, load_after; char is_stat_ok; /* Used to omit slow disk operations if image_file doesn't exist or isn't * a file. */ char is_maybe_image_file; char is_first_error = 1; load_next_image: is_stat_ok = 0; is_maybe_image_file = 1; image_name = image_names[image_idx]; gettimeofday(&load_before, 0); if (imlib_context_get_image()) imlib_free_image(); q->real_w = q->real_h = -2; q->has_thumbnail = FALSE; if (!do_omit_load_stat) { is_stat_ok = 0 == stat(image_name, &st); is_maybe_image_file = is_stat_ok && S_ISREG(st.st_mode); } current_mtime = is_stat_ok ? st.st_mtime : 0; im = NULL; if (thumbnail && fullscreen && (is_stat_ok || maxpect)) { char *th_image_name = is_maybe_image_file ? get_thumbnail_filename(image_name, &is_maybe_image_file) : NULL; if (th_image_name) { im = imlib_load_image(th_image_name); if (im && maxpect) { get_image_dimensions(image_name, th_image_name, &q->real_w, &q->real_h); } free(th_image_name); th_image_name = NULL; } } if (im) { /* We have a dumb thumbnail in im. */ if (maxpect) { current_mtime = 0; q->has_thumbnail = TRUE; /* Now im still has the thumbnail image. Keep it. */ } else { /* Use the real, non-thumbnail image instead. */ imlib_context_set_image(im); imlib_free_image(); im = is_maybe_image_file ? imlib_load_image((char*)image_name) : NULL; } } else { im = is_maybe_image_file ? imlib_load_image((char*)image_name) : NULL; } if (!im) { /* error */ q->error = 1; q->orig_w = 400; q->orig_h = 300; if (to_root || to_root_t || to_root_s) { fprintf(stderr, "qiv: cannot load background_image\n"); qiv_exit(1); } /* Shortcut to speed up lots of subsequent load failures. */ if (is_first_error) { check_size(q, TRUE); if (first) { setup_win(q); first = 0; } gdk_window_set_background(q->win, &error_bg); gdk_beep(); is_first_error = 0; } /* TODO(pts): Avoid the slow loop of copying pointers around in update_image_on_error. */ update_image_on_error(q); /* This is a shortcut to avoid stack overflow in the recursion of * qiv_load_image -> update_image -> qiv_load_image -> update_image -> ... * if there are errors loading many subsequent images. */ goto load_next_image; } if (thumbnail && !q->has_thumbnail && q->real_w < 0 && is_maybe_image_file) { FILE *f = fopen(image_name, "rb"); if (f) { get_real_dimensions_fast(f, &q->real_w, &q->real_h); fclose(f); } } /* Retrieve image properties */ imlib_context_set_image(im); q->error = 0; q->orig_w = imlib_image_get_width(); q->orig_h = imlib_image_get_height(); if (q->orig_w >= (1 << 23) / q->orig_h) { /* Workaround for Imlib2 1.4.6 on Ubuntu Trusty: PNG images with an * alpha channel and pixel count >= (1 << 23) are displayed as black. * imlib_image_query_pixel returns the correct value, but * imlib_render_pixmaps_for_whole_image_at_size renders only black * pixels if unzoomed. */ Imlib_Color c; /* Without this call, imlib_image_set_has_alpha(0) is too early, and * it has no effect. */ imlib_image_query_pixel(0, 0, &c); imlib_image_set_has_alpha(0); } #ifdef HAVE_EXIF if (autorotate) { transform( q, orient( image_name)); } #endif check_size(q, TRUE); if (first) { setup_win(q); first = 0; } /* desktop-background -> exit */ if (to_root || to_root_t || to_root_s) { set_desktop_image(q); if(slide) return; else qiv_exit(0); } gdk_window_set_background(q->win, &image_bg); if (do_grab || (fullscreen && !disable_grab) ) { gdk_keyboard_grab(q->win, FALSE, CurrentTime); gdk_pointer_grab(q->win, FALSE, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK, NULL, NULL, CurrentTime); } gettimeofday(&load_after, 0); /* load_elapsed used by update_image. */ load_elapsed = ((load_after.tv_sec + load_after.tv_usec / 1.0e6) - (load_before.tv_sec + load_before.tv_usec / 1.0e6)); update_image(q, FULL_REDRAW); // if (magnify && !fullscreen) { // [lc] // setup_magnify(q, &magnify_img); // update_magnify(q, &magnify_img, FULL_REDRAW, 0, 0); // } }