# Screen grabber program



## balanga (Feb 10, 2019)

Does anyone have a recommendation for a screen grabber program? ie something which will capture part of the screen as an image...


----------



## Spartrekus (Feb 10, 2019)

balanga said:


> Does anyone have a recommendation for a screen grabber program? ie something which will capture part of the screen as an image...


pkg install scrot


export DISPLAY=:0
scrot   image.png


man scrot 
(check -s )


----------



## aragats (Feb 10, 2019)

`import` from graphics/ImageMagick6 (actually there are several packages for ImageMagick, but it doesn't matter which one for your purpose).
For a part of screen:
	
	



```
import /tmp/screenshot.png
```
For whole screen:
	
	



```
import -w root /tmp/screenshot.png
```


----------



## dch (Feb 10, 2019)

graphics/maim and deskutils/lumina-screenshot are both excellent. I use `alias grab "maim -s /tmp/(date -u +%Y%m%d-%H%M).png"` all the time to select a portion of screen and have it put in a datetime sorted named tmp file.


----------



## Spartrekus (Feb 10, 2019)

aragats said:


> `import` from graphics/ImageMagick6 (actually there are several packages for ImageMagick, but it doesn't matter which one for your purpose).
> For a part of screen:
> 
> 
> ...


I noticed that you like heavy installation. But Imagemagick is bloated.
Better to use something lightweight.

there are many like scrot...

what about just using x11 library itself?
I made once a small application in c that copy the desktop using lib x11 only.


----------



## aragats (Feb 10, 2019)

Spartrekus said:


> I noticed that you like heavy installation. But Imagemagick is bloated.



I don't.
I need ImageMagick for other purposes (to convert between formats).
You can build (or select a different package) with options you need.


----------



## olli@ (Feb 10, 2019)

Indeed, ImageMagick is a very useful set of tools for manipulating graphics. I always install it, alongside with the `netpbm` tools (port graphics/netpbm). They complement each other nicely.

However, for making screenshots I prefer to use the “grab” feature of `xv` (graphics/xv).


----------



## Spartrekus (Feb 11, 2019)

The X11 force shall be with You always 


```
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "x11framegrab.h"
#include <X11/Xlib.h>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <unistd.h>

Display *display = 0;
Screen * screen = 0;
Window rootWindow = 0;
XWindowAttributes xwa;

uint8_t * buffer;
int width, height;

const char * output_formats[MAX_OUTPUT_FORMATS];
int (*output_format_writer[MAX_OUTPUT_FORMATS])( );
int output_format_count;
int quality = -1;


static int handler(Display * d, XErrorEvent *e    )
{
    fprintf( stderr, "FAIL: %p\n", d ) ;
    exit( -5 );
}


int CapScreen()
{
    int lx, ly;
    static int did_set_handler;

    if( !did_set_handler )
    {
        XSetErrorHandler( handler );
    }

    if( !display )
    {
        display = XOpenDisplay( 0 );
           screen = XDefaultScreenOfDisplay(display);
        rootWindow = DefaultRootWindow(display);
        XGetWindowAttributes(display, rootWindow, &xwa);
    }

    width = xwa.width;
    height = xwa.height;

    XImage * m = XGetImage( display, rootWindow, 0, 0, width, height, AllPlanes, XYPixmap);

    if( m->bitmap_pad != 32 )
    {
        fprintf( stderr, "Bad bitmap pad\n" );
        return -1;
    }

    uint8_t * bp = buffer = malloc( width * height * 3 );
    for( ly = 0; ly < height; ly++ )
    {
        for( lx = 0; lx < width; lx++ )
        {
            uint32_t px = XGetPixel( m, lx, ly );
            //(*(pb++)) = (px>>16) | (px&0xff00) | ((px&0xff)<<16);
            (*bp++) = px>>16;
            (*bp++) = px>>8;
            (*bp++) = px;
        }
    }
    XDestroyImage( m );
    return 0;
}



int main( int argc, char ** argv )
{
    int i;
    int showhelp = 0;
    char c;
    const char * outformat = "ppm";
    const char * outfile = 0;
    int rescale = 0;
    outputf = stdout;

    while( (c = getopt( argc, argv, "s:q:o:f:h?" )) != -1 )
    {
        switch( c )
        {
        case 's':
            if( optarg )
            {
                rescale = atoi( optarg );
            }
            else
            {
                rescale = 1;
            }
        case 'q':
            if( optarg )
            {
                quality = atoi( optarg );
            }
            else
            {
                fprintf( stderr, "-q expects parameter.\n" );
            }
            break;
        case 'o':
            outfile = optarg;
            break;
        case 'f':
            outformat = optarg;
            break;
        case '?': case 'h':
        default:
            showhelp = 1;
        }
    }

    if( showhelp || !outfile )
    {
        fprintf( stderr, "x11framegrab - grab x11 frames to files or stdio. Parameters:\n" );
        fprintf( stderr, "  -o [outfile, use - for stdout, REQUIRED field]\n" );
        fprintf( stderr, "  -f [format, default .ppm] available formats are:\n    " );
        for( i = 0; i < output_format_count; i++ )
            fprintf( stderr, "%s%c", output_formats[i], ((i+1)!=output_format_count)?',':'\n' );
        fprintf( stderr, "  -q [quality, if applicable, 1 = bad, 2 = ok, 3 = good]\n" );
        fprintf( stderr, "  -s [rescale quantity, # of times to divide by 2]\n" );
        return -5;
    }
    if( CapScreen() )
    {
        fprintf( stderr, "Fatal error capturing screen.\n" );
        return -1;
    }

    if( strcmp( outfile, "-" ) == 0 )
    {
        outputf = stdout;
    }
    else
    {
        outputf = fopen( outfile, "wb" );
    }

    if( !outputf )
    {
        fprintf( stderr, "Error: Could not open file \"%s\" for writing.\n", outfile );
        return -8;
    }

    int newwidth = width;
    int newheight = height;
    while( rescale > 0 )
    {
        newwidth = (width+1) / 2;
        newheight = (height+1) / 2;
        uint8_t * newbuffer = malloc( newwidth * newheight * 3 );
        int x, y;
        for( y = 0; y < newheight; y++ )
        {
            for( x = 0; x < newwidth; x++ )
            {
                int comp, val;
                for( comp = 0; comp < 3; comp++ )
                {
                    val = 0;
                    val += buffer[((y*2+0)*width+(x*2+0))*3+comp];
                    val += buffer[((y*2+0)*width+(x*2+1))*3+comp];
                    val += buffer[((y*2+1)*width+(x*2+0))*3+comp];
                    val += buffer[((y*2+1)*width+(x*2+1))*3+comp];
                    val = (val+2)>>2; //Prevent darkening bias.
                    newbuffer[(x+y*newwidth)*3+comp] = val;
                }
            }
        }

        width = newwidth;
        height = newheight;
        free( buffer );
        buffer = newbuffer;
        rescale--;
    }


    for( i = 0; i < output_format_count; i++ )
    {
        if( strcmp( outformat, output_formats[i] ) == 0 )
        {
            //Match
            return output_format_writer[i]( );
        }
    }

    fprintf( stderr, "Error: Could not find output format driver: %s\n", outformat );
    return -1;
}
```


----------



## aragats (Feb 11, 2019)

Where is x11framegrab.h?
Also, your program grabs the entire screen, what if I need just a region?


----------



## olli@ (Feb 11, 2019)

balanga said:


> Does anyone have a recommendation for a screen grabber program? ie something which will capture part of the screen as an image...


By the way, there is also x11/xgrab. But chances are that you already have a graphics program or toolset installed that is also capable of doing screen shots (Gimp, ImageMagick, xv, …).


----------



## Deleted member 30996 (Feb 11, 2019)

I use graphics/gimp for screenshots since I already have it installed. You can capture the active window or full screen.


----------



## Spartrekus (Feb 12, 2019)

likely xv or scrot are the best bet.

clang + Xorg is a nice method, since it offers to have full control (with simple code).


----------

