Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Сохранение QGLWidget 
V
    Опции темы
math64
Дата 4.9.2015, 12:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



пробую сохранить так
Код

    QImage image = glWidget->grabFrameBuffer();
    image.save(fileName);

или так
Код

    QPixmap pixmap = glWidget->renderPixmap();
    pixmap.save(fileName);

в обоих случаях программа вылетает. Не могу понять почему.
(рисуется кубик из примера Textures)

PM   Вверх
Amp
Дата 4.9.2015, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 886
Регистрация: 17.2.2009

Репутация: 7
Всего: 17



Из какого места вызываешь? 
PM MAIL   Вверх
math64
Дата 4.9.2015, 22:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Из слота  saveAction, после получения имени файла через QFileDialog.
Ну и в примерах texture и grabber есть анимация - у меня её нет.

Это сообщение отредактировал(а) math64 - 7.9.2015, 08:06
PM   Вверх
math64
Дата 7.9.2015, 08:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Вот так:
Код

void MainWindow::on_actionSave_triggered()
{
    //QImage image = glWidget->grabFrameBuffer();
    //qDebug() << image.size();

    QPixmap pixmap = glWidget->renderPixmap();
    qDebug() << pixmap.size();

    QString fileName =
            QFileDialog::getSaveFileName(this,
                                         "Save Image", ".", "Image(*.png *.jpg *.jpeg *.bmp)");
    if (fileName.isEmpty())
        return;
    qDebug() << fileName;

    //image.save(fileName);
    pixmap.save(fileName);
}

GLWidget.cpp:
Код

#include "glwidget.h"

#include <QtOpenGL>

#include <math.h>

GLWidget::GLWidget(QWidget *parent) :
    QGLWidget(parent)
{
    xRot = 0;
    yRot = 0;
    zRot = 0;
}

GLWidget::~GLWidget()
{

}

QSize GLWidget::minimumSizeHint() const
{
    return QSize(50, 50);
}

QSize GLWidget::sizeHint() const
{
    return QSize(400, 400);
}

static void qNormalizeAngle(int &angle)
{
    while (angle < 0)
        angle += 360 * 16;
    while (angle > 360 * 16)
        angle -= 360 * 16;
}

void GLWidget::setXRotation(int angle)
{
    qNormalizeAngle(angle);
    if (angle != xRot) {
        xRot = angle;
        emit xRotationChanged(angle);
        updateGL();
    }
}

void GLWidget::setYRotation(int angle)
{
    qNormalizeAngle(angle);
    if (angle != yRot) {
        yRot = angle;
        emit yRotationChanged(angle);
        updateGL();
    }
}

void GLWidget::setZRotation(int angle)
{
    qNormalizeAngle(angle);
    if (angle != zRot) {
        zRot = angle;
        emit zRotationChanged(angle);
        updateGL();
    }
}

void GLWidget::initializeGL()
{
    makeObject();

    qglClearColor(Qt::lightGray);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_CULL_FACE);
    glEnable(GL_TEXTURE_2D);

    glEnable(GL_DEPTH_TEST);
    glEnable(GL_NORMALIZE);
}

void GLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -10.0);
    glRotatef(xRot / 16.0, 1.0, 0.0, 0.0);
    glRotatef(yRot / 16.0, 0.0, 1.0, 0.0);
    glRotatef(zRot / 16.0, 0.0, 0.0, 1.0);

    glVertexPointer(3, GL_FLOAT, 0, vertices.constData());
    glTexCoordPointer(2, GL_FLOAT, 0, texCoords.constData());
    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_TEXTURE_COORD_ARRAY);

    for (int i = 0; i < 6; ++i) {
        glBindTexture(GL_TEXTURE_2D, textures[i]);
        glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4);
    }
}

void GLWidget::resizeGL(int width, int height)
{
    int side = qMin(width, height);
    glViewport((width - side) / 2, (height - side) / 2, side, side);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glOrtho(-0.5, +0.5, -0.5, +0.5, 4.0, 15.0);
    glMatrixMode(GL_MODELVIEW);
}

void GLWidget::mousePressEvent(QMouseEvent *event)
{
    lastPos = event->pos();
}

void GLWidget::mouseMoveEvent(QMouseEvent *event)
{
    int dx = event->x() - lastPos.x();
    int dy = event->y() - lastPos.y();

    if (event->buttons() & Qt::LeftButton) {
        setXRotation(xRot + 8 * dy);
        setYRotation(yRot + 8 * dx);
    } else if (event->buttons() & Qt::RightButton) {
        setXRotation(xRot + 8 * dy);
        setZRotation(zRot + 8 * dx);
    }
    lastPos = event->pos();
}

void GLWidget::makeObject()
{
    static const int coords[6][4][3] = {
        { { +1, -1, -1 }, { -1, -1, -1 }, { -1, +1, -1 }, { +1, +1, -1 } },
        { { +1, +1, -1 }, { -1, +1, -1 }, { -1, +1, +1 }, { +1, +1, +1 } },
        { { +1, -1, +1 }, { +1, -1, -1 }, { +1, +1, -1 }, { +1, +1, +1 } },
        { { -1, -1, -1 }, { -1, -1, +1 }, { -1, +1, +1 }, { -1, +1, -1 } },
        { { +1, -1, +1 }, { -1, -1, +1 }, { -1, -1, -1 }, { +1, -1, -1 } },
        { { -1, -1, +1 }, { +1, -1, +1 }, { +1, +1, +1 }, { -1, +1, +1 } }
    };

    for (int j=0; j < 6; ++j) {
        textures[j] = bindTexture
            (QPixmap(QString(":/res/side%1.png").arg(j + 1)), GL_TEXTURE_2D);
    }

    for (int i = 0; i < 6; ++i) {
        for (int j = 0; j < 4; ++j) {
            texCoords.append
                (QVector2D(j == 0 || j == 3, j == 0 || j == 1));
            vertices.append
                (QVector3D(0.2 * coords[i][j][0], 0.2 * coords[i][j][1],
                           0.2 * coords[i][j][2]));
        }
    }
}

PM   Вверх
Amp
Дата 8.9.2015, 13:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 886
Регистрация: 17.2.2009

Репутация: 7
Всего: 17



Посмотри отладчиком в каком именно месте падает. Надеюсь исходники Qt стоят?
Хоть у тебя падет и там и там, но вместо renderPixmap надежнее использовать grabFrameBuffer, т.к. последний сводится фактически к вызову glReadPixels. А renderPixmap будет повторно вызывать initializeGL(), что в твоем случае возможно и приводит к некоторым проблемам. Например пересозданию текстур, заполнению texCoords и vertices без предварительной очистки.
PM MAIL   Вверх
math64
Дата 9.9.2015, 09:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



В Windows у меня отладчик не работает - не знаю почему, когда в первый раз ставил Qt, работал.
В Linux валится на d->glcx->doneCurrent(); в QPixmap QGLWidget::renderPixmap(int w, int h, bool useContext)
или на
d->glcx->makeCurrent(); в void QGLWidget::makeCurrent() из QImage QGLWidget::grabFrameBuffer(bool withAlpha)
при этом на консоль валится
can't find linker symbol for virtual table for `QGLWidget' value
  found `QGLContext::bindTexture(QString const&)' instead

PM   Вверх
math64
Дата 9.9.2015, 15:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Была глупая ошибка.
в MainWindow::MainWindow(QWidget *parent)
вместо
Код

    glWidget = new GLWidget(this);
    setCentralWidget(glWidget);

было
Код

    GLWidget* glWidget = new GLWidget(this);
    setCentralWidget(glWidget);


PM   Вверх
math64
Дата 10.9.2015, 16:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Дополнительно: Как сохранить с прозрачным фоном?
PM   Вверх
Amp
Дата 10.9.2015, 16:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 886
Регистрация: 17.2.2009

Репутация: 7
Всего: 17



Последний аргумент glClearColor должен быть 0, и grabFrameBuffer(true)
PM MAIL   Вверх
math64
Дата 11.9.2015, 08:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



Не получается. На всякий случай проверяю на наличие прозрачных пикселей:
Код

void GLWidget::paintGL()
{
    glClearColor(0.75, 0.75, 0.75, 0);
    ...
}

void MainWindow::on_actionSave_triggered()
{
    ...
    QImage image = glWidget->grabFrameBuffer(true);
    QSize size = image.size();
    int w = size.width();
    int h = size.height();
    bool alpha = false;
    for(int y = 0; y < h; y++) {
        QRgb* s = (QRgb*)image.scanLine(y);
        for(int x = 0; x < w; x++) {
            QRgb rgb = s[x];
            if (qAlpha(rgb) != 0xFF) {
                s[x] = 0;
                alpha = true;
            }
        }
    }
    qDebug() << size << alpha;
    ...
}

QSize(209, 224) false
PM   Вверх
Amp
Дата 11.9.2015, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 886
Регистрация: 17.2.2009

Репутация: 7
Всего: 17



Приложи лучше минимальный проект.
PM MAIL   Вверх
math64
Дата 11.9.2015, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2505
Регистрация: 12.4.2007

Репутация: 23
Всего: 72



В конструкторе нужно добавить формат QGL::AlphaChannel:
Код

GLWidget::GLWidget(QWidget *parent) :
    QGLWidget(QGLFormat(QGL::AlphaChannel), parent)
{
...
}

PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С/С++: Кроссплатформенное программирование, QT/Gtk+/wxWidgets"
JackYF
Любитель
  • В заголовке темы в квадратных скобках обозначьте используемую вами библиотеку, например: [QT],[GTK],[wx].
  • Если вопрос актуален только для некоторой версии библиотеки, либо, если вы пользуетесь не самой последней версией, укажите это. Например: [QT4], [GTK2].
  • Все начинающие изучать Qt - не забудьте зайти сюда.
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • В вопросе укажите полную версию версию библиотеки, а также все дополнительные используемые программные пакеты.
  • Не забывайте пользоваться кнопкой "Код".
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, Любитель.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | С/С++: Кроссплатформенное программирование, Qt/Gtk+/wxWidgets | Следующая тема »


 




[ Время генерации скрипта: 0.0827 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.