Opengl_сделать_скриншот_проблема

Вопросы программирования и использования среды Lazarus.

Модератор: Модераторы

Opengl_сделать_скриншот_проблема

Сообщение mildok » 27.05.2013 20:35:39

WinXP SP3, Lazarus.

Задача: сделать средствами Lazarus'а и Opengl скриншот.

Что странно: в интернете видел кучу таких примеров:

Код: Выделить всё
  w:=1024;
  h:=768;
  bpp:=32;
    glReadBuffer( GL_FRONT );
    glReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, bits);   


После чего в bits должен оказаться скриншот - не работает пробовал на разных машинах - в bits оказывается чёрный экран. Также пробовал:
Код: Выделить всё
  w:=1024;
  h:=768;
  bpp:=32;
    glReadBuffer( GL_BACK );
    glReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, bits);


glFlush(); glFinish(); ставил перед выполнением glReadPixels - всё равно чёрный экран получаем.

Как заработало:
Код: Выделить всё
  w:=1024;
  h:=768;
  bpp:=32;

  glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH);
  glutInitWindowSize(w, h);     

  glutInitWindowPosition(0, 0);
  wingl:=glutCreateWindow('OpenGL Tutorial :: First Program');   

    glReadBuffer( GL_FRONT );
    glReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, bits);

    glutDestroyWindow(wingl);


Но с косяком (скриншот смотри во вложении) Сверху чёрная полоса снизу и справа муар...

Собственно более полный код:
Код: Выделить всё
  w:=1024;
  h:=768;
  bpp:=32;

                    glFlush(); glFinish();

  glutInitDisplayMode(GLUT_DOUBLE or GLUT_RGB or GLUT_DEPTH);
  glutInitWindowSize(w, h);
  glutInitWindowPosition(0, 0);
  wingl:=glutCreateWindow('OpenGL Tutorial :: First Program');

  ZeroMemory(@Binfo, sizeof(BITMAPINFO));
  OneCTpokaInBytes:=w*(bpp div 8);

  BInfo.bmiHeader.biBitCount := bpp;
  //3agaeM LLIupuHy
  BInfo.bmiHeader.biWidth := w;
  //минус нужен, чтобы перевернуть картинку, потому что см. выше как в дин. памяти всё пишется
  BInfo.bmiHeader.biHeight := h;

  if ((BInfo.bmiHeader.biBitCount = 0) or (BInfo.bmiHeader.biWidth = 0) or
    (BInfo.bmiHeader.biHeight = 0)) then
  begin
    form1.Caption := '..)=..Получены некорректные данные ширины/высоты/глубины..=(..';
    exit;
  end;

  with BInfo.bmiHeader do
  begin
    //Длина структуры BInfo
    biSize := sizeof(BITMAPINFOHEADER);
    //Должно равняться 1(думаю в будущем будет 2ух и 3ез плоскостное =D )
    biPlanes := 1;
    //noJIy4uJIu y}I{e B oTJIago4HoM npuH9Tuu;
    biCompression := BI_RGB;
    //abs, потому что biHeight, см. выше величина отрицательная
    //pa3Mep должен быть в байтах поэтому глубину(она в битах) делим на 8
    biSizeImage := (biWidth*abs(biHeight)*(biBitCount div 8));
  end;

  //Создаём буферную бмпишку в которую и будут складироваться данные
  //С помощью CreateDIBSection мы указываем переменную bits, где на самом деле находится картинка
    tmpbmp:=Graphics.TBitmap.Create;
    tmpbmp.Handle:=CreateDIBSection(tmpbmp.canvas.handle,BInfo,DIB_RGB_COLORS,bits,0,0);

    glReadBuffer( GL_FRONT );
    // GL_BGR - 0x80E0
    // GL_BGRA - 0x80E1
    // I dont know why GL_BGRA and GL_BGR not define in uses gl, glu, glut
    glReadPixels( 0, 0, w, h, $80E1, GL_UNSIGNED_BYTE, bits);

    tmpbmp.SaveToFile('asd.bmp');

    tmpbmp.Free;
    glutDestroyWindow(wingl);     


Теория почему не работает: glutCreateWindow - создаёт окно у которого есть заголовок и рамка - заголовок на скриншоте отображает чёрным, муар - это рамка.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
mildok
новенький
 
Сообщения: 22
Зарегистрирован: 08.05.2010 14:09:36

Re: Opengl_сделать_скриншот_проблема

Сообщение zub » 27.05.2013 22:31:06

>>Задача: сделать средствами Lazarus'а и Opengl скриншот.
что значит сделать скриншот? glReadPixels копирует содержимое opengl окна в память. Создаешь gl контекст, рисуешь в него, копируешь полученное изобращение с видеокарты в системную память с помощью glReadPixels. При этом никакие сторонние окна и рамки окон не копируются. Для получения "скриншота" как во вложении нужно использовать другие методы, OpenGL предназначен совсем для другого
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26

Re: Opengl_сделать_скриншот_проблема

Сообщение mildok » 27.05.2013 23:11:07

zub, благодарю за Ваш ответ.

Мною были перепробованы такие способы создания взятия скриншотов как:
- BitBlt - медленный; StrechBlt - тоже медленный и изображение страшное;
- Зеркальный_драйвер (он же mirror driver). Всё понравилось работает быстро, но есть минусы: отключает Aero(ИМХО ещё отключает аппаратное ускорение), под Windows 7 64 и далее необходимо покупать и подписывать драйвер - иначе Windows данный драйвер отторгает. Одна лицензия стоит 15.000 руб. в год - а я не настолько богат. Есть способ послать исходные коды на ReactOS и может там согласятся подписать бесплатно, но эт как-то не круто - если что поменяется - опять людей просить подписывать? Можно отключить проверку подписи, но не всем же объяснять как это делать - и это опять же не круто... Ах да ещё кое что - в Windows 8 зерк. драйверы выпилены http://msdn.microsoft.com/en-us/library/windows/hardware/ff568315(v=vs.85).aspx вместо них некий Duplication Api как я понимаю, но сиё мне не осилить однако. Итого mirror driver - прикольно но не выход.
- есть ещё Directx 11 под Windows 7 (да под которую дорого mirror driver за 15.000) - но вот никак не могу найти пример со скриншоттингом Directx 11 и wrapper'ы для Directx 11 под Lazarus.

Итохо - решил попробовать Opengl, который кроссплатформенный и как я понимаю многими производителями видеокарт поддерживаемый - а поэтому со скриншоттингом-то обыкновенным уж должен справиться эффективно? Или нет?

Вообщем: почему чёрный экран на примерах которые описаны вначале; или почему сверху чёрная полоса, а справа и снизу муар на примере описанном в конце?
mildok
новенький
 
Сообщения: 22
Зарегистрирован: 08.05.2010 14:09:36

Re: Opengl_сделать_скриншот_проблема

Сообщение zub » 27.05.2013 23:38:29

>>а поэтому со скриншоттингом-то обыкновенным уж должен справиться эффективно? Или нет?
со скриншоттингом (в смысле получения "картинки" рабочего стола)-нет. вообще никак.
>>очему чёрный экран на примерах которые описаны вначале
потому что glReadPixels не копирует десктоп. он копирует содержимое окна текущего контекста OpenGL. насколько я понимаю созданного контекста у тебя нет
>>или почему сверху чёрная полоса, а справа и снизу муар на примере описанном в конце?
см. предидущий пункт. за исключением что здесь контекст и окно есть, но в окне ничего не отрендерено. По идее должен был скопироваться "мусор" или нули. то что появилось какоето изображение - проблемы конкретного видеодрайвера на конкретной машине, полосы - это следы от декораций окна (т.к. glReadPixels работает только с клиентской областью окна). На другой машине будет скопирован мусор или "пусто", и это не баг - это неверное использование opengl
zub
долгожитель
 
Сообщения: 2887
Зарегистрирован: 14.11.2005 23:51:26


Вернуться в Lazarus

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 243

Рейтинг@Mail.ru