% xwd -root | convert - screenshot.pngSome post-processing is needed if one wants an image of part of the visible screen.
% scrot -sand selected a rectangle. This gave correct output:
% import screenshot.pngyields
with a black rectangle. The problem seems to be that import tries to get this part of the image from an obscured window, instead of from the window that lies on top in the stacking order. If one has many windows, as I always have, then import almost never gives a correct screenshot. One can fix the problem by moving away (or closing) all other windows, so that there is nothing below the part that is screenshotted.
Others have reported the same bug. E.g. Big black square, Taken screenshot is all black, Black box on import, Import returning mostly black images, Black rectangles appearing in screenshots. Slackware documents this as a known ImageMagick problem:
This problem is also well-known and has existed for years (I saw a 2004 bug report). See also, e.g., Screen capture problem, Offset issue, PNG offset problem. It helps to add the +repage option to the invocation of import. (Sometimes this option has to be given twice.) If you have to deal with such a broken image produced by import, zoom out in gimp until the part with bad offset appears, and then move it back into place. There are various utilities to repair broken import output. An ImageMagick solution is
% convert +repage screenshot_bad.png screenshot_ok.png
% import ss0.png % convert X: ss0a.pngdo approximately the same, and are equally broken:
and
(with similar hand-selected screenshot areas - roughly the same visible screen as above, but a different stacking order of the windows).
diff -ur ImageMagick-6.8.0-6/wand/import.c ImageMagick-6.8.0-6a/wand/import.c --- ImageMagick-6.8.0-6/wand/import.c 2011-12-19 02:54:26.000000000 +0100 +++ ImageMagick-6.8.0-6a/wand/import.c 2013-01-10 00:21:19.000000000 +0100 @@ -381,7 +381,7 @@ image_info->density=XGetResourceInstance(resource_database,GetClientName(), "density",(char *) NULL); resource_value=XGetResourceInstance(resource_database,GetClientName(), - "descend","True"); + "descend","False"); ximage_info.descend=IsMagickTrue(resource_value); resource_value=XGetResourceInstance(resource_database,GetClientName(), "frame","False");
A larger patch fixes the main problems with the recursive descent, both in import and in the X: source for convert. It also applies to ImageMagick-6.8.1-9.
diff -ur ImageMagick-6.8.0-6/magick/xwindow.c ImageMagick-6.8.0-6a/magick/xwindow.c --- ImageMagick-6.8.0-6/magick/xwindow.c 2012-10-14 15:40:22.000000000 +0200 +++ ImageMagick-6.8.0-6a/magick/xwindow.c 2013-01-10 22:17:09.000000000 +0100 @@ -4114,10 +4114,10 @@ (window_info[i].visual == window_info[id].visual) && (window_info[i].colormap == window_info[id].colormap)) { - if ((window_info[id].bounds.x1 <= window_info[i].bounds.x1) || - (window_info[id].bounds.x1 >= window_info[i].bounds.x2) || - (window_info[id].bounds.y1 <= window_info[i].bounds.y1) || - (window_info[id].bounds.y1 >= window_info[i].bounds.y2)) + if ((window_info[id].bounds.x1 < window_info[i].bounds.x1) || + (window_info[id].bounds.x2 > window_info[i].bounds.x2) || + (window_info[id].bounds.y1 < window_info[i].bounds.y1) || + (window_info[id].bounds.y2 > window_info[i].bounds.y2)) { /* Eliminate windows not circumscribed by their parent. @@ -4195,22 +4195,12 @@ if ((window_info[id].visual == window_info[j].visual) && (window_info[id].colormap == window_info[j].colormap)) { - if ((window_info[id].bounds.x1 <= window_info[j].bounds.x1) || - (window_info[id].bounds.x1 >= window_info[j].bounds.x2) || - (window_info[id].bounds.y1 <= window_info[j].bounds.y1) || - (window_info[id].bounds.y1 >= window_info[j].bounds.y2)) + if ((window_info[id].bounds.x1 >= window_info[j].bounds.x1) && + (window_info[id].bounds.x2 <= window_info[j].bounds.x2) && + (window_info[id].bounds.y1 >= window_info[j].bounds.y1) && + (window_info[id].bounds.y2 <= window_info[j].bounds.y2)) import=MagickFalse; } - else - if ((window_info[id].visual != window_info[j].visual) || - (window_info[id].colormap != window_info[j].colormap)) - { - if ((window_info[id].bounds.x2 > window_info[j].bounds.x1) && - (window_info[id].bounds.x1 < window_info[j].bounds.x2) && - (window_info[id].bounds.y2 > window_info[j].bounds.y1) && - (window_info[id].bounds.y1 < window_info[j].bounds.y2)) - import=MagickTrue; - } if (import == MagickFalse) continue; /*
The offset information that made GIMP unhappy is removed by the following.
diff -ur ImageMagick-6.8.1-9/magick/xwindow.c ImageMagick-6.8.1-9a/magick/xwindow.c --- ImageMagick-6.8.1-9/magick/xwindow.c 2012-12-07 14:14:16.000000000 +0100 +++ ImageMagick-6.8.1-9a/magick/xwindow.c 2013-01-11 15:39:45.000000000 +0100 @@ -5071,6 +5061,12 @@ (size_t) window_name.nitems+1); (void) XFree((void *) window_name.value); } + if (image != (Image *) NULL) + { + /* forget that this was part of a larger image */ + image->page.width = image->page.height = 0; + image->page.x = image->page.y = 0; + } } if (ximage_info->silent == MagickFalse) {I don't know whether there are also reasons to keep it.