Официальный форум СВД Встраиваемые Системы
12 Августа, 2020, 06:40:16 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.

Войти
 
 
 Сайт СВД ВС  Начало   Помощь Поиск Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: Создать скриншот программно  (Прочитано 1067 раз)
chuzhik
Пользователь

Сообщений: 51


« : 22 Февраля, 2018, 11:16:15 »

Здравствуйте

Задача - пользователь нажимает кнопку в нашей программе, программа делает скриншот экрана, сохраняет картинку в файл.

Подскажите, как из программы сделать скриншот экрана. QNX 6.5, Photon.

Или стоит сразу пробовать ставить Qt?

Записан
Андрей Докучаев
Сотрудник СВД ВС
Ветеран

Сообщений: 847



WWW
« Ответ #1 : 22 Февраля, 2018, 12:02:45 »

Тут есть несколько вариантов. Какой графический драйвер используется в системе?
Записан

chuzhik
Пользователь

Сообщений: 51


« Ответ #2 : 30 Декабря, 2019, 11:31:41 »

Добрый день

Извините, долго не отвечал, пришлось переключиться на другие проекты.

Драйвер dldevg-radeon.so


Попытался запустить snapshot из консоли - не получается, только с графикой.

Через PgReadScreenSize попытался - не понимаю, как сохранить результат в
файл. PxWriteImage почему-то не работает.

Я так понимаю, есть вариант через OffScreen, но пока до него руки не дошли.
Записан
chuzhik
Пользователь

Сообщений: 51


« Ответ #3 : 09 Января, 2020, 09:59:20 »


Добрый день.

Вроде нашел решение при помощи PgReadScreen(). Оказалось, функция
PxWriteImage() работает, но нужно define добавить.

Кому интересно, вот такая конструкция должна быть:


#define PX_IMAGE_MODULES
#define PX_PHIMAGE_SUPPORT
#define PX_BMP_SUPPORT
#include <photon/PxImage.h>

Полный код метода снятия скриншота вот такой:

     char* fname = "/tmp/qwe.bmp";

     int len;
     char* mem;
     PhImage_t *image;
     PhRect_t rect = { { 0,0 }, {1000,1000 } };


     if((len = PgReadScreenSize(&rect)) <= 0)
     {
         printf("if((len = PgReadScreenSize(&rect)) <= 0)\n");
         return -1;
     }

     if( !(mem = (char*)PgShmemCreate(len, NULL)))
     {
         printf("if( !(mem = (char*)PgShmemCreate(len, NULL)))\n");
         return -1;
     }

     if(image = PgReadScreen(&rect, mem))
     {

         printf("if(image = PgReadScreen(&rect, mem))\n");
         PxWriteImage(fname, image, NULL, PX_IMAGE_BMP, 0);
     }

     PgShmemDestroy(mem);


Но сделать скриншот всего экрана не получается. При
PgReadScreenSize(&rect) для прямоугольника 1024х1024 получается ошибка
ENXIO - "There was no graphics driver present to capture the specified
rectangle." А реальный экран еще больше.

Подскажите, пожалуйста, куда двигаться дальше. Я так понимаю, либо
искать другой драйвер, либо другой программный путь.

Драйвер radeon: dldevg-radeon.so. 1280Х1024, глубина цвета 16М.

Записан
Андрей Докучаев
Сотрудник СВД ВС
Ветеран

Сообщений: 847



WWW
« Ответ #4 : 09 Января, 2020, 11:02:18 »

Добрый день!

Попытался запустить snapshot из консоли - не получается, только с графикой.

Не понимаю написанного. Что в точности означат "не получается, только с графикой"?

Но сделать скриншот всего экрана не получается. При
PgReadScreenSize(&rect) для прямоугольника 1024х1024 получается ошибка
ENXIO - "There was no graphics driver present to capture the specified
rectangle." А реальный экран еще больше.

Подскажите, пожалуйста, куда двигаться дальше. Я так понимаю, либо
искать другой драйвер, либо другой программный путь.

Драйвер radeon: dldevg-radeon.so. 1280Х1024, глубина цвета 16М.

Полагаю, что драйвер devg-radeon.so или все-таки что-то иное? Ошибка ENXIO говорит о том, что не найден регион, покрывающий весь прямоугольник. Может быть указали область отличную от [0;0] -> [1023;1023]?
Записан

deadarcher
Пользователь

Сообщений: 89


« Ответ #5 : 09 Января, 2020, 15:36:50 »

День добрый!
Под VMWare вроде бы картинки снимаются.
На сях Smiley  выглядит так:
Код:
#include <Ph.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <photon/PxImage.h>


#ifndef PATH_SNAP
    #define PATH_SNAP        "/home/screens/"
    #define FILE_SNAP       "scr_%d-%02d-%02d_%02d-%02d-%02d-%d.png"
#endif

#define max_rids 16
char ppath[PATH_MAX+32];


int take_snap()
{
 PhImage_t *image=NULL, *rim=NULL;
 PhRect_t rect={{0,0},{1024,768}};
 PhRid_t rids[max_rids];
 PdDirectContext_t *dc;

 int r=-1,n;
 static int psz=strlen(PATH_SNAP);

    PhWindowQueryVisible(Ph_QUERY_CONSOLE,0,0,&rect);

    memset(rids,0,sizeof(rids));
    if ((n=PdGetDevices(rids,max_rids))<1) {
        fprintf(stderr,"GetDevices err %d\n",errno);
        return -1;
    }
    if ((dc=PdCreateDirectContext())==NULL) {
        fprintf(stderr,"CreatDirectContext err %d\n",errno);
        return -1;
    }
    PdSetTargetDevice(dc,rids[0]);
    errno=0;
    if ((n=PgReadScreenSize(&rect))<1) {
        fprintf(stderr,"PgReadScreenSize(%dx%d)=%d err %d\n",rect.lr.x,rect.lr.y,n,errno);
        goto End;
    }
    if((image = (PhImage_t*)PgShmemCreate(n,NULL))==NULL)
    {
        fprintf(stderr,"PgShmemCreate(%d) err %d\n",n,errno);
        goto End;
    }
    rim=PgReadScreen(&rect,image);
    if (rim!=NULL)
    {
        unsigned long u[2];
        clock_gettime(CLOCK_REALTIME,(struct timespec *)u);
        struct tm *tm=localtime((time_t *)u);

        sprintf(ppath, PATH_SNAP "" FILE_SNAP, tm->tm_year+1900,
            tm->tm_mon, tm->tm_mday, tm->tm_hour,tm->tm_min,tm->tm_sec,(int)u[1]/1000000);
        r=PxWriteImage(ppath,image,NULL,PX_IMAGE_PNG,image->type);
        if (r)
            fprintf(stderr,"%s r=%d errno=%d\n",&ppath[psz],r,errno);
    }
    else
        fprintf(stderr,"PgReadScreen err %d\n",errno);
End:
    PdReleaseDirectContext(dc);
    PgShmemDestroy(image);
    return r;
}
Записан
chuzhik
Пользователь

Сообщений: 51


« Ответ #6 : 10 Января, 2020, 10:45:52 »

Добрый день!

Попытался запустить snapshot из консоли - не получается, только с графикой.

Не понимаю написанного. Что в точности означат "не получается, только с графикой"?



Когда я запускаю из консоли snapshot, запускается gui. Мне же нужно сделать несколько скриншотов через некоторые промежутки времени. Т. е. запустить скрипт, в котором вызывать snapshot с параметрами.  Я читал на форумах, что на 4.25 такое возможно. Но на 6.3 не получается.

Извините, пишу кратко, т к. с мобильного. С рабочего компьютера не получается залогиниться на форуме.
Записан
chuzhik
Пользователь

Сообщений: 51


« Ответ #7 : 10 Января, 2020, 10:52:50 »

Добрый день!



Но сделать скриншот всего экрана не получается. При
PgReadScreenSize(&rect) для прямоугольника 1024х1024 получается ошибка
ENXIO - "There was no graphics driver present to capture the specified
rectangle." А реальный экран еще больше.

Подскажите, пожалуйста, куда двигаться дальше. Я так понимаю, либо
искать другой драйвер, либо другой программный путь.

Драйвер radeon: dldevg-radeon.so. 1280Х1024, глубина цвета 16М.

Полагаю, что драйвер devg-radeon.so или все-таки что-то иное? Ошибка ENXIO говорит о том, что не найден регион, покрывающий весь прямоугольник. Может быть указали область отличную от [0;0] -> [1023;1023]?

Спасибо, это я ступил. 1279х1023 работает. С нуля же надо считать.

Снимок экрана сделал, но подтормаживает этот метод. На фоне работы несколько снимков будет делать не удобно.

Есть смысл копать в сторону OffScreen context?
Записан
Андрей Докучаев
Сотрудник СВД ВС
Ветеран

Сообщений: 847



WWW
« Ответ #8 : 10 Января, 2020, 11:06:11 »

Когда я запускаю из консоли snapshot, запускается gui

У snapshot в ЗОСРВ/QNX6 нет такого режима. В четверке, действительно, подобное можно было провернуть. Для новой графической подсистемы у нас разработан ряд утилит, позволяющих на низком уровне захватывать снимки слоев и поверхностей, доступных приложениям. Однако, для данного драйвера сейчас они применены быть не могут.

Таким образом, остается только написание своей утилитки по рекомендациям выше.


Снимок экрана сделал, но подтормаживает этот метод. На фоне работы несколько снимков будет делать не удобно.

Есть смысл копать в сторону OffScreen context?

Теоретически может стать лучше, если удастся избежать лишних копирований/преобразований/доступа к файловой системе. Однако, для точного диагноза нужно понимать что именно происходит медленно.
Записан

chuzhik
Пользователь

Сообщений: 51


« Ответ #9 : 24 Января, 2020, 05:18:37 »


Теоретически может стать лучше, если удастся избежать лишних копирований/преобразований/доступа к файловой системе. Однако, для точного диагноза нужно понимать что именно происходит медленно.

Самая медленная часть - вызов PgReadScreen(). 0.9 секунды
Записан
chuzhik
Пользователь

Сообщений: 51


« Ответ #10 : 24 Января, 2020, 05:29:10 »

Попытался сделать через offscreen. Почитал форумы, нашел вот такое решение.

PdOffscreenContext_t *offscreen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY|Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE);
unsigned char* Data = (unsigned char *)PdGetOffscreenContextPtr(offscreen_context);

К нему нужно добавить заголовок bmp-файла. Структуру заголовка нашел, типы данных заменил на uintXX_t в соответствии с размером.

Формирую заголовок.

   BMPheader bh;

   memset(&bh, 0, sizeof(bh));

   bh.bfType=0x4d42;
   bh.bfOffBits=54;
   bh.biSize=sizeof(bh);
   bh.biPlanes=1;
   bh.biBitCount=24;
   bh.biCompression=0;
   bh.biXPelsPerMeter=0;
   bh.biYPelsPerMeter=0;
   bh.biClrUsed=0;
   bh.biClrImportant=0;

   bh.biWidth=1280;
   bh.biHeight=1024;

   long Size= bh.biWidth * bh.biHeight * 3;
   bh.bfSize=Size + bh.biSize;

Цифры из заголовка проверил путем считывания заголовков bmp-файлов с диска, потому что за ряд полей структуры был не уверен. Но там нули стоят. Наделал скриншотов стандартной программой, по ним смотрел.


   FILE* fp = fopen( fname, "wb" );

   fwrite (&bh,sizeof(bh),1,fp);

   int res = fwrite (Data,Size,1,fp);

   fclose( fp );

При открытии картинки программа пишет "файл поврежден или слишком велик".
Подскажите, пожалуйста, куда дальше копать.



Записан
Андрей Докучаев
Сотрудник СВД ВС
Ветеран

Сообщений: 847



WWW
« Ответ #11 : 24 Января, 2020, 10:51:49 »

Подскажите, пожалуйста, куда дальше копать

Полагаю, что в сторону изучения формата BMP. К тому же сильно сомневаюсь, что у Вас пиксель реально 3-х байтный.
Записан

Страниц: [1]   Вверх
  Печать  
 
Перейти в:  

Powered by MySQL Powered by PHP © 2002-2020 СВД Встраиваемые Системы.
При использовании материалов сайта ссылка на forum.kpda.ru обязательна.

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines | © Aiwan. Kolobok smiles | Sitemap
Valid XHTML 1.0! Valid CSS!
Сайт СВД ВС

В последний раз google посещал эту страницу 27 Июля, 2020, 21:18:03