Как сохранить текстуру как файл изображения с помощью библиотек, связанных с OpenGL?

Основная идея моего кода - нарисовать сцену, используя как текстуру, так и геометрическую модель. Текстура получается из «.RAW», а геометрическая модель - из набора треугольников из триангуляции Делоне.

Теперь я могу распечатать результат на экране и сохранить отображаемый результат как изображение - «Печать экрана». Я использую freeglut, чтобы сделать это.

Проблема в том, что я использую входные изображения с высоким разрешением. Но выходное изображение будет иметь то же разрешение, что и мой экран - 1366x768 (это не сравнивается с исходным изображением - 8956x6708).

Кто-нибудь знает, как сохранить текстуру, отображаемую на экране, прямо в файл? Без использования подхода «Print Screen».

Я не думаю, что смогу справиться с этой ситуацией с помощью freeglut.


person ricãO    schedule 06.07.2015    source источник
comment
Freeglut не имеет к этому никакого отношения. В GL вы можете использовать закадровые буферы кадров для рендеринга, и вы, конечно, можете прочитать их и записать в какой-нибудь файл изображения. 8956x6708 легко поддерживается современными графическими процессорами, но даже если вы достигнете некоторого предела, вы можете выполнить плиточное приложение.   -  person derhass    schedule 06.07.2015
comment
TR - библиотека рендеринга плиток OpenGL   -  person genpfault    schedule 06.07.2015
comment
Спасибо за оперативный ответ. Я изучу это еще немного и попытаюсь отобразить мои результаты в закадровом буфере кадра - FBO, верно? Я нашел эти ссылки, которые могут помочь: Framebuffer_Object и Framebuffer_Object_Examples.   -  person ricãO    schedule 06.07.2015


Ответы (2)


Этот ответ показывает, как я читаю изображение (.raw), вставляю его содержимое в объект Framebuffer и сохраняю его в файл .ppm - без «снимка экрана». Итак, выходное изображение имеет то же разрешение, что и входное.

Я использовал библиотеку GLEW для работы с объектом Framebuffer.

Надеюсь, это кому-нибудь поможет ...

Вот мой код:

* (Я удалил часть кода, чтобы сосредоточиться только на теме вопроса. Поэтому есть некоторые переменные, которые не имеют смысла!)

#include <windows.h>
#define  GLEW_STATIC

#include <GL/glew.h>
#include <GL/glut.h>
#include <GL/freeglut.h>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <cstdio>
#include <string>

#define width       2464
#define height      1648

/// Global Variables
static  GLuint texture;
GLuint  fb = 1; ///Frame-buffer Object

/// Headers
GLuint  raw_texture_load();
void    FBO_2_PPM_file();

/// Functions
GLuint raw_texture_load()
{
    GLuint texture;
    unsigned char *data;
    FILE *file;

    // open texture data
    file = fopen("C:\\Dataset\\1_4.raw", "rb");
    if (file == NULL) return 0;

    // allocate buffer
    data = (unsigned char*) malloc(width * height * 3);

    // read texture data
    fread(data, width * height * 3, 1, file);
    fclose(file);

    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

    /// Texture
    // allocate a texture name
    glGenTextures(1, &texture);
    // select our current texture
    glBindTexture(GL_TEXTURE_2D, texture);
    // select modulate to mix texture with color for shading
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_DECAL);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_DECAL);
    // when texture area is small, bilinear filter the closest mipmap
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
    // when texture area is large, bilinear filter the first mipmap
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    // texture should tile
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    // build our texture mipmapst
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
    // free buffer
    free(data);

    return texture;
}

void render()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_TEXTURE_2D);
    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);

    glBindTexture(GL_TEXTURE_2D, texture);

    glFlush();
    glDisable(GL_TEXTURE_2D);

    ///FBO
    glGenFramebuffers(1, &fb);
    glBindFramebuffer(GL_FRAMEBUFFER, fb);
    //Attach 2D texture to this FBO
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);

    /// Saving the results from the FBO (fb) to a PPM image file
    FBO_2_PPM_file();
}

void init()
{
    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_SMOOTH);

    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    glEnable(GL_DEPTH_TEST);

    texture = raw_texture_load();

    render();
}

void FBO_2_PPM_file()
{
    FILE    *output_image;
    int     output_width, output_height;

    output_width = width;
    output_height = height;

    /// READ THE PIXELS VALUES from FBO AND SAVE TO A .PPM FILE
    int             i, j, k;
    unsigned char   *pixels = (unsigned char*)malloc(output_width*output_height*3);

    /// READ THE CONTENT FROM THE FBO
    glReadBuffer(GL_COLOR_ATTACHMENT0);
    glReadPixels(0, 0, output_width, output_height, GL_RGB, GL_UNSIGNED_BYTE, pixels);

    output_image = fopen("C:\\Dataset\\output.ppm", "wt");
    fprintf(output_image,"P3\n");
    fprintf(output_image,"# Created by Ricao\n");
    fprintf(output_image,"%d %d\n",output_width,output_height);
    fprintf(output_image,"255\n");

    k = 0;
    for(i=0; i<output_width; i++)
    {
        for(j=0; j<output_height; j++)
        {
            fprintf(output_image,"%u %u %u ",(unsigned int)pixels[k],(unsigned int)pixels[k+1],
                                             (unsigned int)pixels[k+2]);
            k = k+3;
        }
        fprintf(output_image,"\n");
    }
    free(pixels);
}

int main(int argc, char *argv[])
{
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
    glutInitWindowSize(300, 1);
    glutCreateWindow("...");
    glutHideWindow();

    /// Checking GLEW library
    glewExperimental=TRUE;
    GLenum err=glewInit();

    if(err!=GLEW_OK)
    {
        printf("glewInit failed, aborting.");
        printf("\tError: %s\n\n",glewGetErrorString(err));
        system("pause");
    }

    if (GLEW_EXT_framebuffer_object != GL_TRUE)
    {
        printf("\n\n\t ** Error! GLEW_EXT_framebuffer_object != GL_TRUE \n\n");
        system("pause");
    }

    ///Executing the rendering process
    init();

    return 0;
}
person ricãO    schedule 28.07.2015

Когда вы просто выполняете рендеринг в фреймбуфер, эта функция

void glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *data);

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

Дополнительную информацию можно найти в этой документации glReadPixels.

Извините, но для сохранения файла нет одной библиотеки, которая сохраняет во всех форматах, но я использую lodepng, он сохраняет и загружать файлы png, этот формат является наиболее подходящим для удерживаемой графики, на мой взгляд, вы можете его проверить.

person David De Anda    schedule 04.08.2015