0

I'm trying to save a texture in tiff file from an other thread. But the only result i get is a white picture, I think it come from the glcontext ( because it's not possible to have one glcontext for several thread). That's why i've tried to create two glcontext and share the display context. But still i don't have the gl texture. I can't get the texture from the second opengl context . I'm tring to do that because at the end the texture will be a video stream from a camera . Here is my context creation :

static  PIXELFORMATDESCRIPTOR pfd =
                {
                    sizeof(PIXELFORMATDESCRIPTOR),              // Size Of This Pixel Format Descriptor
                    1,                                          // Version Number
                    PFD_DRAW_TO_WINDOW |                        // Format Must Support Window
                    PFD_SUPPORT_OPENGL |                        // Format Must Support OpenGL
                    PFD_DOUBLEBUFFER,                           // Must Support Double Buffering
                    PFD_TYPE_RGBA,                              // Request An RGBA Format
                    8,                                          // Select Our Color Depth
                    0, 0, 0, 0, 0, 0,                           // Color Bits Ignored
                    0,                                          // No Alpha Buffer
                    0,                                          // Shift Bit Ignored
                    0,                                          // No Accumulation Buffer
                    0, 0, 0, 0,                                 // Accumulation Bits Ignored
                    16,                                         // 16Bit Z-Buffer (Depth Buffer)  
                    0,                                          // No Stencil Buffer
                    0,                                          // No Auxiliary Buffer
                    PFD_MAIN_PLANE,                             // Main Drawing Layer
                    0,                                          // Reserved
                    0, 0, 0                                     // Layer Masks Ignored
                };

                GLuint PixelFormat;
                // create the pixel pixel format descriptor
                PixelFormat = ChoosePixelFormat(dc, &pfd);
                //  set the pixel format descriptor
                SetPixelFormat(dc, PixelFormat, &pfd);
                gl = wglCreateContext(dc);
                gl2 = wglCreateContext(dc);
                wglShareLists(gl, gl2);
                wglMakeCurrent(dc, gl);
                GLenum g= glewInit();
                wglewInit();
                loadImage();
                rec = new Recorder(dc,gl2);
                rec->Start_StopRecord(text, true);

Here is the code to save to tiff file :

    Recorder::Recorder(HDC &hdc, HGLRC &_gl)
{
    isStarted = false;
    dc = hdc;
    gl = _gl;
}


Recorder::~Recorder()
{
    if (isStarted) {
        isStarted = false;
        recordThread.join();
        CloseTifFile();
        delete mp_fileTifIn;
    }
}

void Recorder::Start_StopRecord(GLuint Texture, bool launched){
    if (launched) {
        if (isStarted) {
            wglMakeCurrent(dc, gl);
            isStarted = false;
            recordThread.join();
            CloseTifFile();
            pixels.release();
        }
        else {
            isStarted = true;
            //wglMakeCurrent(NULL, NULL);
            //RecordShot(&Texture);
            recordThread = std::thread(&Recorder::RecordShot, this,&Texture);
        }
    }
}
void Recorder::RecordShot(GLuint* texture){
    wglMakeCurrent(dc, gl);

    OpenTifFile(*texture);

    pixels = std::unique_ptr<int>(new int[width*height]);

        //while (isStarted) {
            WriteTif8Bits(*texture);
            WriteDirectory();
            //Sleep(16);
        //}
        pixels.release();
}

void Recorder::OpenTifFile(GLuint &Texture){
    char* filename="../test3.tiff";
    glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_HEIGHT,&height);
    glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_WIDTH,&width);
    mp_fileTifIn = TIFFOpen(filename,"w");

}

void Recorder::CloseTifFile(){
    TIFFClose(mp_fileTifIn);
}
/*
 * Open Sub data for a Tiff file (allow multiple picture in one tif file)
 */
void Recorder::WriteDirectory(){
    TIFFWriteDirectory(mp_fileTifIn);
}

void Recorder::WriteTif8Bits(GLuint &Texture){
    //Setup Tiff Configuration
    TIFFSetField(mp_fileTifIn,TIFFTAG_IMAGEWIDTH,width);
    TIFFSetField(mp_fileTifIn,TIFFTAG_IMAGELENGTH,height);
    TIFFSetField(mp_fileTifIn,TIFFTAG_SAMPLESPERPIXEL,4);
    TIFFSetField(mp_fileTifIn,TIFFTAG_BITSPERSAMPLE,8);
    TIFFSetField(mp_fileTifIn,TIFFTAG_ROWSPERSTRIP,TIFFDefaultStripSize(mp_fileTifIn,width));
    TIFFSetField(mp_fileTifIn,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
    TIFFSetField(mp_fileTifIn,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
    TIFFSetField(mp_fileTifIn, TIFFTAG_COMPRESSION, COMPRESSION_NONE);
    TIFFSetField(mp_fileTifIn, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
    glBindTexture(GL_TEXTURE_2D,Texture);
    assert(glGetError() == GL_NO_ERROR);

    glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_BYTE,pixels.get());
    assert(glGetError() == GL_NO_ERROR);
    //Image Reversal
    Reverse(pixels.get(), height, width);

    //Write one picture
    /*for (int row = 0; row < height; row++) {
        TIFFWriteScanline(mp_fileTifIn, pixels.get(), row, 0);
        lineChange(pixels.get(), width);
    }*/
    TIFFWriteEncodedStrip(mp_fileTifIn, 0, pixels.get(), height*width * sizeof(int));
}
void Recorder::lineChange(int* pointer, int width) {
    pointer -= width;
}
void Recorder::Reverse(int* pointer, int height, int width) {
    pointer += (height - 1) * width;
}

And here is the loadImages function

int loadImage() {
wglMakeCurrent(dc, gl);
cv::Mat image;
image = cv::imread(std::string("C:/Users/Public/Pictures/Sample Pictures/Desert.jpg"), CV_LOAD_IMAGE_COLOR);
if (!image.data)
    return -1;
cvNamedWindow("try", cv::WINDOW_AUTOSIZE);
cv::imshow("try", image);
cv::flip(image, image, 0);
glGenTextures(1, &text);
GLenum g=glGetError();
glBindTexture(GL_TEXTURE_2D, text);
assert(glGetError() == GL_NO_ERROR);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, image.cols, image.rows, 0, GL_BGR, GL_UNSIGNED_BYTE, image.ptr());
return 0;

}

Here is a test project where i'm loading a picture with opencv and i try to save it in an other thread : https://mega.nz/#!SBMUnJRI!dLC_l9hmCkhIDDUaygHuq4Kw2SKIuxRE7m19md74p0k

To run the project you need Opencv and glew, libtiff is already packaged inside If you think somethink is missing for this post, i invite you to comment it before downgrade as i'm following my subject

miyoku
  • 107
  • 1
  • 13
  • So you try to load a jpg image with OpenCV and store it in an OpenGL texture if I understand correctly? – Dynamitos Jul 10 '17 at 14:00
  • For the test project yes. When i will succeed to save an opengl texture, it won't come from a jpg but a video stream from a camera . ( that's why i try to save the picture loaded with opencv to tiff, it's for testing purpose. The real goal is save an opengl texture. – miyoku Jul 10 '17 at 14:03
  • `pixels` must be of size `width x heigh x 4` of `char` (unsigned byte). That's what you are setting your `glTexImage` command. – Ripi2 Jul 10 '17 at 15:45
  • I don't think it's a bad allocation issue. Because if you uncomment the call to recordshot and comment the launching of the thread which launch recordshot, it save the picture correctly. So I'm guessing that the issue come from the multithreading. I think i don't get how to share the texture between two thread (so two opengl context with `wglsharelist`) – miyoku Jul 10 '17 at 20:17
  • I'm still on this issue, actually, i'm looking to the displaylist. I think i don't use wglsharelist correctly. Do i have to create a new list with all the drawing instruction in order to share the texture? ( I'm asking because it's not really written in the doc : https://msdn.microsoft.com/fr-fr/library/windows/desktop/dd374390%28v=vs.85%29.aspx) – miyoku Jul 11 '17 at 07:23

1 Answers1

0

I finally solved my problem by doing all opengl action in one thread ( i retrieve the image and display it in one thread, and i save it in another, which doesn't need an openglcontext) An other thing that were confusing me is a bad configuration of

glGetTexImage(GL_TEXTURE_2D,0,GL_RGBA,GL_UNSIGNED_BYTE,this->rec[0].pixels.get());

But my textures are GL_TEXTURE_RECTANGLE_NV, that's why i had only a white picture sometimes.

miyoku
  • 107
  • 1
  • 13