Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.144.33.41] |
|
Сообщ.
#1
,
|
|
|
Пытаюсь заскриншотить экран, нашел функцию glReadPixels. Если кому интересно, вот ее прототип:
void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid * data); Согласно описанию, функция возвращает указатель на данные в GLvoid *data, однако мне кажется, что нулевой указатель не похож на смысл ее существования. Я сначала думал, что какая-то ошибка, попробовал вызвать glGetError #include <GL/gl.h> using namespace std; int main() { GLvoid *data; glReadPixels(0,0,1920,1080,GL_BGR,GL_UNSIGNED_BYTE,data); cout << glGetError() << endl << data << endl; } ОС:Ubuntu Компилятор:gcc |
Сообщ.
#2
,
|
|
|
Здрасьте-приехали. У тебя есть фреймбуфер, из которого она что-то вменяемое могла бы вернуть?
|
Сообщ.
#3
,
|
|
|
Извиняюсь, в ОпенГЛ я новичок Намек понял, прочел туториал про фреймбуфера. Добавил glGenFramebuffers и glBindFramebuffer. Чем дальше в лес, тем больше дров: кол-во мистики зашкалило -- можно теперь, опубликоваться в местные газеты. Я нашел, что вышеупомянутые функции упоминаются в glext.h и gl_mangle.h и добавил их. Однако компилятор все равно отказывается находить их декларацию. Не зная, что еще придумать, я просто вручную вписал их прототипы в код -- все равно с библиотекой слинкуются, должны работать. Однако линкер моего мнения не разделил и вежливо, без мата, отказался линковать. Как-то так:
constantine@constantine-N61Ja:~/Projects/OCVTut/bin/Debug$ g++ test1.cpp -lGL -g /tmp/ccMKpXsk.o: In function `main': /home/constantine/Projects/OCVTut/bin/Debug/test1.cpp:13: undefined reference to `glGenFramebuffers(int, unsigned int*)' /home/constantine/Projects/OCVTut/bin/Debug/test1.cpp:14: undefined reference to `glBindFramebuffer(int, unsigned int*)' collect2: ошибка: выполнение ld завершилось с кодом возврата 1 constantine@constantine-N61Ja:~/Projects/OCVTut/bin/Debug$ nm -D /usr/lib/x86_64-linux-gnu/libGL.so|grep glGenFramebuffers 000000000004a3e0 T glGenFramebuffers 000000000004a3e0 T glGenFramebuffersEXT Я вообще думал, что может с кодировкой какие-то проблемы -- я сначала код функции просто скопировал с браузера. Но нет, я уже и вручную переписал и даже копировал с терминала, то, что выше привел, тщетно. В-общем код сейчас выглядит так: #include <GL/gl.h> #include <GL/glext.h> #include <iostream> //#include <GL/gl_mangle.h> using namespace std; void glBindFramebuffer(GLsizei n, GLuint *framebuffers); void glGenFramebuffers(GLsizei n, GLuint *ids); int main() { GLuint* ids=0; glGenFramebuffers(1,ids); glBindFramebuffer( GL_READ_FRAMEBUFFER, ids ); glReadPixels(0,0,1920,1080,GL_BGR,GL_UNSIGNED_BYTE,ids); if(!ids)cout << "No buffer" << endl; } constantine@constantine-N61Ja:~/Projects/OCVTut/bin/Debug$ g++ test1.cpp -lGL -g test1.cpp: В функции «int main()»: test1.cpp:16:57: ошибка: нет декларации «mglReadPixels» в этой области видимости Добавляет к именам OpenGL функций букву m и радостно сообщает, что таких не существует. |
Сообщ.
#4
,
|
|
|
Мощно gl-функции к скриншоту экрана не имеют никакого отношения. Делайте через GetDC, CreateCompatibleBitmap, SelectObject и GetDIBits.
Если не получится, позже набросаю пример. |
Сообщ.
#5
,
|
|
|
Просто я выбрал OpenGL, чтобы можно было потом приложение перекомпилировать под винду. И здесь, у меня на Убунте оно тоже работало. GetDC исключительно виндовая функция, и, наверное, у иксов есть свой аналог -- но это уже кроссплатформенным, увы, не будет.
Хотя, если решения не найду, придется пользоваться ими. |
Сообщ.
#6
,
|
|
|
А, точно, убунту не заметил
В любом случае OpenGL в данном случае нужен не более, чем функции работы с сетью, например. Из готовых кроссплатформенных решений есть, например, Qt (QDesktopWidget + grabWindow). Но если скриншот это одна (или одна из немногих) некроссплатформенных фич, то проще ее написать самому, используя платформозависимые функции. |
Сообщ.
#7
,
|
|
|
В-общем попробовал написать на QT: самый минимум кода, и он умудряется все равно валиться
#include <QtCore> #include <QtGui> #include <iostream> int main(int argc, char* argv[]) { std::cout << (int)QApplication::desktop()->winId(); } QWidget: Must construct a QApplication before a QPaintDevice Аварийный останов (сделан дамп памяти) Гугл сказал что такие проблемы обычно бывают при запуске дебаг версии, я перекомпилировал в релиз -- ничего не изменилось. Пока вынужден оставить свои скитания по пустыне проб и ошибок, чуть попозже продолжу) |
Сообщ.
#8
,
|
|
|
Цитата самый минимум кода, Вы откуда это взяли? Цитата и он умудряется все равно валиться а с чего-бы оно должно работать? читаем доку: QApplication::QApplication А вообще, вам ошибка говорит, что делать |
Сообщ.
#9
,
|
|
|
Цитата OpenGL @ +1. К тому же ваш, just-a-guest, особый ОС-вариант займёт в пределе 30 Кб, а с Qt выльется в 30 Мб. И нафига? Но если скриншот это одна (или одна из немногих) некроссплатформенных фич, то проще ее написать самому, используя платформозависимые функции. |
Сообщ.
#10
,
|
|
|
Прошу прощения, за столь долгий перерыв; итак, по результатам голосования среди меня и меня, самым бесполезным хидером объявляется glext.h, поприветствуем победителя. Именно благодаря ему, у меня возникала ошибка, и именно он обладатель функций, объявления которых все равно пришлось переписывать.
Собственно проблема крылась в манглинге имен функций. Честно говоря до сих пор знал об этом весьма абстрактно. С++ по тех. причинам переименовывает функции на стадии препроцессинга, причем способ меняется от компилятора к компилятору. И, для линковки с внешней библиотекой конкретной функции, нужно запретить ее переименование с помощью extern "C"{}. Удивительно: эта директива в glext.h есть, но, почему то не работает. Видимо какой-то баг препроцессора gcc. Я решил продолжить с OpenGL, дабы не изобретать велосипед и теперь вернулся к самому началу темы, код #include <GL/gl.h> #include <iostream> using namespace std; extern "C"{ void glBindFramebuffer(GLsizei n, GLuint *framebuffers); void glGenFramebuffers(GLsizei n, GLuint *ids); } int main() { GLuint* ids=0; glGenFramebuffers(1,ids); glBindFramebuffer( GL_READ_FRAMEBUFFER, ids ); glReadPixels(0,0,1280,800,GL_BGR,GL_UNSIGNED_BYTE,ids); if(!ids)cout << "No buffer!" << endl; } Что я неправильно делаю? UPD: ну, т.е, насколько я теперь уже понял, glReadPixels должен писать в заранее созданный мной массив, размером WIDTHxHEIGHTx3. Я конечно его не создавал, но, в любом случае программа должна вылетать при попытке записи по нулевому указателю *ids; посколько этого не происходит, glReadPixels не работает. |
Сообщ.
#11
,
|
|
|
Во-первых, сказано же уже, что к скриншоту экрана glReadPixels не имеет никакого отношения. Во-вторых, даже если вам нужен скрин окна opengl - вы не сможете получить от gl-функций ничего до его создания. Ну и в-третьих glBindFramebuffer это из совсем другой оперы. Добавлено Цитата Славян @ +1. К тому же ваш, just-a-guest, особый ОС-вариант займёт в пределе 30 Кб, а с Qt выльется в 30 Мб. И нафига? Под убунтой обычно qt линкуется динамически (а библиотеки часто уже есть в системе), поэтому на размер исполняемого файла не влияет. А если учесть, что qt это кроссплатформенные окна и куча полезных классов, то оно вполне можжет быть оправданным. |
Сообщ.
#12
,
|
|
|
OpenGL, спасибо, я понял... Просто google выдает множество ссылок по вопросу OpenGL screenshot, это меня ввело в заблуждение. Насколько я понимаю glReadPixels может сделать снимок только созданного лично мной окна. Помечаю вопрос решенным.
|
Сообщ.
#13
,
|
|
|
Цитата OpenGL @ Спасибо. Не знал. Под убунтой обычно qt линкуется динамически (а библиотеки часто уже есть в системе), поэтому на размер исполняемого файла не влияет. А если учесть, что qt это кроссплатформенные окна и куча полезных классов, то оно вполне можжет быть оправданным. |