Thumbnails and strange problems!

Hi!

I’m using the code below to make thumbnails. It is a modification to a widely used program using imlib2. Sorry about the formatting. I’ll explain the problem below.

#include <X11/Xlib.h>
#include <Imlib2.h>
#include <stdio.h>
#include <string.h>
#include <math.h>

#define CREATE_SHADOWS 1

int main(int argc, char **argv) {
        Display *display;
        XWindowAttributes windowattr;
        Imlib_Image image, shadow_image, icon;
        int windowid, thumbwidth, thumbheight;
	int scale_quality;
	int shadow_direction;
   	int shadow_x_offset, shadow_y_offset;
	int icon_width, icon_height;

        if ( argc != 7 ) {
       		puts("Usage: thumb WindowId ThumbWidth ThumbFile IconFile ScaleQuality ShadowDirection");
       		return 1;
   	}
        
	sscanf(argv[1], "%x", &windowid);
        sscanf(argv[2], "%d", &thumbwidth);
	sscanf(argv[5], "%d", &scale_quality);
	sscanf(argv[6], "%d", &shadow_direction);
        if ( (display = XOpenDisplay(NULL)) == NULL ) return 1;
       	
	XGetWindowAttributes(display, windowid, &windowattr);
        
	thumbheight = windowattr.height * thumbwidth / windowattr.width;

        imlib_context_set_anti_alias(1);
        imlib_context_set_display(display);
        imlib_context_set_visual(DefaultVisual(display, DefaultScreen(display)));
        imlib_context_set_colormap(DefaultColormap(display, DefaultScreen(display)));
        imlib_context_set_drawable(windowid);

        if ( scale_quality*thumbwidth < windowattr.width || scale_quality*thumbheight < windowattr.height ) 
	{
		image = imlib_create_scaled_image_from_drawable((Pixmap)0, 0, 0,windowattr.width, windowattr.height, scale_quality*thumbwidth, scale_quality*thumbheight, 1, 1);
                imlib_context_set_image(image);
                image = imlib_create_cropped_scaled_image(0, 0, scale_quality*thumbwidth, scale_quality*thumbheight,thumbwidth, thumbheight);			     				           
         } 
	else {
           	image = imlib_create_image_from_drawable((Pixmap)0, 0, 0, windowattr.width, windowattr.height, 1);
                imlib_context_set_image(image);
                image = imlib_create_cropped_scaled_image(0, 0, windowattr.width, windowattr.height,thumbwidth, thumbheight);     
        }

 	icon = imlib_load_image(argv[4]);
        imlib_context_set_image(icon);
        icon_width = imlib_image_get_width();
        icon_height  = imlib_image_get_height();
        imlib_context_set_image(image);
        imlib_blend_image_onto_image(icon, 1, 0, 0, icon_width, icon_height, 0, 0, icon_width, icon_height);

#if CREATE_SHADOWS
	shadow_image = imlib_create_image(thumbwidth+20, thumbheight+20);
//      shadow_image = imlib_create_image(thumbwidth+20, thumbheight+20);
	imlib_context_set_image(shadow_image);
	imlib_image_set_has_alpha(1);
	imlib_context_set_color(0, 0, 0, 170);
	shadow_x_offset = sin (2 * M_PI * (float)shadow_direction / 360) * 6 + 10;
	shadow_y_offset = -cos (2 * M_PI * (float)shadow_direction / 360) * 6 + 10;
	
	imlib_image_fill_rectangle(shadow_x_offset, shadow_y_offset, thumbwidth, thumbheight);
	imlib_image_blur(3);

	imlib_blend_image_onto_image(image, 1, 0, 0, thumbwidth, thumbheight, 10, 10, thumbwidth, thumbheight);
#endif

        imlib_image_set_format(strrchr(argv[3], '.')+1);
        imlib_save_image(argv[3]);

   	fprintf(stdout, "WindowStyle IconOverride, Icon %s\n", argv[3]);
        return 0;
}

Here is the config which uses the above program:

SetEnv fvwm_icon_size 200
SetEnv fvwm_icon_scale_quality 1
SetEnv fvwm_icon_shadow_direction 145
DestroyFunc Thumbnail
AddToFunc Thumbnail
+ I Raise
+ I ThisWindow (!Shaded, Iconifiable, !Iconic) PipeRead "$[FVWM_USERDIR]/scripts/thumb $[w.id] $[fvwm_icon_size] $[FVWM_USERDIR]/temp/icon.tmp.$[w.id].png $[w.miniiconfile] $[fvwm_icon_scale_quality] $[fvwm_icon_shadow_direction]"
+ I Iconify

Everything should be OK, BUT there seems to be a problem somewhere. If my Firefox window size is about 1000x200 (WxH) and I iconify it, I get some very odd garbage to the upper portion of the icon. If I use regular window sizes, like 1000x600, it doesn’t happen. So what on earth is going on?? The oddest thing is that if I uncomment the line in the code the problem disappears!!! There must be a bug there but I can’t see it. Any ideas?

(Almost the same code can be found here with better formatting: viewtopic.php?t=650 )

I’m not sure, but what happens if you lower fvwm_icon_size?

the size of the window you mention is the same heigth as the icon_size. So I guess it may be trying to squeeze the 1000 pixels in 200 pixels while trying to keep the heigth.

I’ll see if this happens with me too when I use a window that has the same height as the iconsize.

[edit]
Just checked it, it works fine with me. It should keep the aspect ratio, so when using an iconsize of 200 (=width), and using a 1000x200 window, the thumbnail will only be 50px high. You can’t expect much detail in that.
I used the thumb.c that is included in bricem13’s config, I don’t know if he altered it or not.
[/edit]

Johan

fvwm_icon_size only defines the width of the icon. So basically a 1000x200 window becomes 200x40 (did you get 50?) in size. The problem is that when I use the shadow routine above, the upper portion of the shadow gets filled with noise: almost random pixels. For some windows there is anly a few pixels, for othere there might be 10 rows of noise.

You have to try the shadowed version in order to see it. Brice13’s version doesn’t have shadows. My code also works flawlessly without the shadows. But I see no bugs in the shadow code so I’m quite puzzled.

oh, sorry, but imlib_create_image() doesnt initialize the image contents (they could be garbage memory).
After “imlib_image_set_has_alpha(1);”, try something like:

DATA8 data[256]; memset(data, 0, sizeof(data)); Imlib_Color_Modifier color_modifier = imlib_create_color_modifier(); imlib_context_set_color_modifier(color_modifier); imlib_set_color_modifier_tables(NULL, NULL, NULL, data); imlib_apply_color_modifier();

Hmm, I think I’m not understanding what that is supposed to do :( Could you explain a bit? When I placed it after creating shadow_image my original window thumbnail disappeared. Shadow was fine though…

EDIT:

I DID understand it, after all. I just had to reset the color_modifier back to normal before blending the tumbnail window over the shadow. Now it works like a miracle. Thanks for your help! But HOW and WHY does it work?

And the next is still valid question:

Why can’t I just fill the created image with nothing (ie. fill it with rgba = 0)? Somehow I can’t use the next after creating the shadow_image and setting alpha to 1:

        imlib_context_set_color(0, 0, 0 , 0);
        imlib_image_fill_rectangle(0, 0, thumbwidth+20, thumbheight+20)

Do you know if there is any way to directly access the image data and set it to 0.

hehe :slight_smile:

Drawing something with an alpha channel always changes the colors relatively to the original colors… But we want to set them to absolute values (alpha=0).

So, the code maps every possible alpha value (0-255) to 0.
There are other possibilities, but I dont know any to directly access the image data :frowning:

You can reset the color modifier with imlib_context_set_color_modifier(NULL);

That seems to be the case. But for some reason I can still draw the shadow rectangle (with alpha=170 in the above code) WITHOUT reseting the modifier tables first. So it seems that the tables don’t affect everything? Damn, I wish there was a good documentation of Imlib2 somewhere. The one here is too vague and lacks a few functions.

I used imlib_reset_color_modifier();

But the good thing is that now the code does what it should do. I added also a command line options to define shadow distance and blur amount. I’ll maybe add the option to define shadow alpha and some more. The speed is still sub-par. Iconifying should happen instantly and it still seems to get a few tenths :cry:

it’s all there

void imlib_context_set_color_modifier(Imlib_Color_Modifier color_modifier):
Sets the current color modifier used for rendering pixmaps or images to a drawable or images onto other images. […]

imlib_apply_color_modifier(void):
Uses the current color modifier and modifies the current image using the mapping tables in the current color modifier.

Thanks! But the docs don’t habe description for, say,

imlib_create_scaled_image_from_drawable() etc. They do mention _drawable in some parts but is there any complete documentation available anywhere?

BTW, is there any reason you do this:

   image = imlib_create_image_from_drawable(...);
   imlib_context_set_image(image);
   image = imlib_create_cropped_scaled_image(...); 

and not this:

  image = imlib_create_scaled_image_from_drawable(...);
  //imlib_context_set_image(image);

(The imlib_context_set might not be necessary then…)

Edit:
Nevermind: it seems the imlib_create_scaled… doesn’t scale too well…

Maybe, I never searched for it, sorry…

Example: you have a 1280 pixel wide window and want a 128 pixel thumbnail.
Then imlib_create_scaled_image_from_drawable() reads every 10th pixel and copies them to the thumbnail. Because of this, it is really fast, but you lose much information.
So, my example grabs thumbnailwidth*4 pixels and then scales with antialiasing (for big windows).