Войти
ПрограммированиеФорумОбщее

как сделать скриншот в linux

Страницы: 1 2 Следующая »
#0
5:07, 21 янв. 2008

сорь за глупый вопрос, просто вот решил поставить линукс, взял gcc и написал маленькую прогу (интерфейс сделал свой на opengl - тк в linux ничерта не знаю, слышал про gtk, qt; но поступил по своему) и вот пришло время свой курсовик показать а мне бы видео сделать - придумал делать скрины рабочего стола (мне именно весь стол нужен а не окно проги) ну а потом из скринов я собрал бы видео.
вобшем нужен маленький кусочек кода на си, который грабил бы активный рабочий стол в массивчик (и запихивал в файл типа raw, без заголовков) под виндой делал GetDiBits(); а в linux хз или поможет просто кто подскажет как сделать скриншот или хотяб функцию которую юзать нужно или линку дайте а то искал с пару часов ненашел =(. Пытался найти исходники проги (Ksnapshot), которая делает скрин по кнопке print-screen и в png пихает но чет недобрался до них.


#1
11:31, 21 янв. 2008

http://tips.webdesign10.com/how-to-take-a-screenshot-on-ubuntu-linux

первая ссылка в гугле

#2
14:18, 21 янв. 2008

ksnapshot в состав kdegraphics входит :)

#3
16:33, 21 янв. 2008

chak
Lord Stalker

мне примерещилось или автор темы хотел кусочек программного кода на си?

#4
16:55, 21 янв. 2008

Если интерфейс на GL - почему бы не применить glReadPixels?

Правка: сорри, невнимательно читал
Правка2: смотри imagemagick, там более-менее понятно. Ещё тулза есть, дампающая содержимое окна вроде в xpm, но название вспомнить не могу

#5
17:13, 21 янв. 2008

Юзаем XWD, а потом конвертируем. из мана

xwd - dump an image of an X window

$xwd -root > 1.xwd
$xwdtopnm 1.xwd > 1.pnm

Потом это всё заворачивеам в вызов system

for (blah-blah-blah) {
    /*! \todo смену имён файлов дописать */
    system("xwd -root > 1.xwd && xwdtopnm 1.xwd > 1.pnm");
    usleep(1000);
}

ЗЫ: ну вот как-то так. На поиск проги ушло минут пять, потом ещё минут пять курил маны. Дольше всего оформлял пост.

#6
17:31, 21 янв. 2008

=A=L=X=
>chak
>Lord Stalker
>мне примерещилось или автор темы хотел кусочек программного кода на си?
Ну так сделайте системный вызов...

#7
17:56, 21 янв. 2008

chak
При чём тут syscalls?

TankSoft
Угу, xwd я и имел в виду, совсем забыл название.. Только это будет дико медленно, т.к. нужно снимать видео
Так вот, сорец там понятный и не большой. Реальное чтение идёт через XGetImage
А вообще, может хватит xvidcap'а?

#8
19:33, 21 янв. 2008

keltar
Угу медленно

time  xwd -root | xwdtopnm > 1.pnm
0.01user 0.06system 0:01.09elapsed 7%CPU
Та вроде Asteraceae'у скринов достаточно. Впринципе конвертирование можно сделать после:
time  xwd -root > /dev/null0.01
user 0.02system 0:00.64elapsed 6%CPU
#9
5:28, 23 янв. 2008

TankSoft: попробовал как ты рекомендовал, и правда медленно вышло .. очень ..

keltar: прогу XVidCap тож мучал, результат тоже... опять медленно, он сжимает все в mpeg а нуна в raw для послед обработки..

Вот сам сидел дня 2 мозговал, мозговал и вот чего придумал:


#include <stdio.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <sys/time.h>

//entry point
int main( int argc,char *argv[])
{

  //initialize gtk
  gtk_init(NULL,NULL);

  //get display resolution
  int width=640; //gdk_screen_width();
  int height=480; //gdk_screen_height();
  int size=width*height;

  //open target file (overwrite, if exists)
  FILE *hfile;
  hfile=fopen("flow.dat","wb+");
  if(hfile!=NULL)
  {

    //get root window
    GdkWindow *root;
    root=gdk_window_foreign_new(GDK_ROOT_WINDOW());

    //vars
    bool quit=false;      //quit flag
    int iframe=0;          //frame counter
    int length=0;          //image size
    int alpha=0;          //is alpha channel present
    int offset=0;          //total file size
    int bits=0;            //pits per pixel
    unsigned int base=0;  //start time
    unsigned int timing=0; //capture time
    struct timeval tv;    //time
    guchar *pixels;        //pixel buffer
    GdkPixbuf *buffer;    //screenshot buffer

    while (!quit)
    {
   
      //capture screen and get pixels
      buffer=gdk_pixbuf_get_from_drawable(NULL,root,NULL,0,0,0,0,width,height);
      pixels=gdk_pixbuf_get_pixels(buffer);
   
      //frame timing   
      iframe+=+1;
      gettimeofday(&tv,NULL);
      if(iframe==1)
      {
        base=tv.tv_sec*1000+tv.tv_usec/1000;
        timing=0;
      }
      else
      {
        timing=tv.tv_sec*1000+tv.tv_usec/1000-base;
      }
   
      //prepare image info
      alpha=gdk_pixbuf_get_has_alpha(buffer);
      bits=(alpha?4:3);
      length=size*bits;
      offset+=length;
   
      //write data block
      fwrite(&timing,1,sizeof(timing),hfile);
      fwrite(&width,1,sizeof(width),hfile);
      fwrite(&height,1,sizeof(height),hfile);
      fwrite(&bits,1,sizeof(bits),hfile);
      fwrite(pixels,1,length,hfile);
   
      //info
      printf("%d: frame #%d (%d x %d @rgb%s), %d kb, %d mb\n",timing,iframe,width,height,(alpha?"a":""),length/1024,offset/1048576);

      //memory cleanup
      g_object_unref(buffer);
      pixels=NULL;
      buffer=NULL;

    }

    //close file
    fclose (hfile);
  }
  else
  {
    printf("could not create output file.\n");
  }
 
  //done
  return 0;
 
}

Работает немного побыстрее но всеравно для видео медленно... на 640x800 тянет под ~15fps. Комп не особо прыткий 1.600 всего, но когда писал примерно тоже самое тока под винду залетало за 700fps =(
Есть идеи как ускорить это дело?

#10
10:47, 23 янв. 2008

Asteraceae
Попробуй использовать DevIL
вот статья http://www.gamedev.ru/articles/?id=70123
Тогда используя OpenGL можно сделать так:

// созданипе скриншота
bool OpenGLRender::CreateScreenShot(const std::string& filename) const
{
  // создаем скриншот для OpenGL окна
  ilutGLScreen();
  // сохраняем файл
  int res = ilSaveImage(static_cast<ILstring>(const_cast<char *>(filename.c_str())));
....
}
#11
10:56, 23 янв. 2008

Andrey
это только для контекста воспроизведения opengl скриншот сделан будет, а ему нужен для всего экрана

#12
11:00, 23 янв. 2008

Sokal
а... ну ясно.

Прошло более 2 лет
#13
9:29, 25 мар. 2010

Тема хоть и старая, но хотелось бы узнать - кто-то нашел ЭФФЕКТИВНОЕ решение ? Я пробовал делать скриншот с помощью XGetImage, затем с помощью ilSaveImage сохранял в файл. Но это медленно. При разрешении экрана 1440x900 на один снимок уходит до 200 mS. ( 5 fps ). Причем, тормозит именно XGetImage.

#14
13:12, 25 мар. 2010

SergK

Вообще, в композитном режиме, можно перехватывать весь вывод в окно в реальном времени.

http://ktown.kde.org/~fredrik/composite_howto.html

Смысл в том, что XGetImage --- это тяжелое наследие XLib. Сейчас нужно работать либо через XShm, либо через XRender.

P.S. А я видео с экрана сохраняю так:

$ ffmpeg -f x11grab -r 50 -s 1680x1050 -i :0.0 -sameq dump.avi

:)

Страницы: 1 2 Следующая »
ПрограммированиеФорумОбщее

Тема в архиве.