Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

From Matrix to QImage and QPixmap



  • Hello everyone.
    First of all thanks a lot for reading this post and being able to help.

    I would like to get an image from a matrix.

    This is my code to convert from QImage to matrix:

                QPixmap img_scene(path_name_image); //Pixmap creation to add the image
                img = img_scene.toImage();
    
                 int **matrix;
    
                //Create matrix where each element will be a pixel value.
                matrix = new int *[img.width()];
                for(int i=0;i<img.width();++i)
                    matrix[i] = new int [img.height()];
    
                for(int i=0;i<img.width();++i){
                    for(int j=0;j<img.height();++j){
                        matrix[i][j]=qGray(img.pixel(i,j)) > 127 ? 0:1; //Less than 127 = 1.
                    }
                }
    

    Now i would like to convert "matrix" to a QImage. My code looks like this:

                    QImage imagen(1000,938, QImage::Format_Grayscale8);
    
                    for(int i=0;i<1000;++i){
                        for(int j=0;j<938;++j)
                            imagen.setPixel(i,j, matrix_binary[i][j]);
                    }
    

    It compile but it crashed in the last "for"..

    how can I do that?
    thanks!


  • Lifetime Qt Champion

    Hi,

    Did you check that your matrix is pointing to something valid ?

    Out of curiosity, why do you need such a matrix ?



  • @SGaist Yes, matrix values is 0 = black or 1 = white.

    I need a matrix because user can load a binary file where matrix is inside and then image has to be in a scene.


  • Lifetime Qt Champion

    I meant the matrix itself, not what its content is representing.

    Did you allocate that matrix properly ?

    On a side note, you can also use a QVector<QVector<int>> for a two dimensional storage.


  • Qt Champions 2019

    @AlvaroS I think @SGaist wanted to know whether matrix_binary is pointing to a matrix and whether it has same dimensions as the picture (1000x938). How did you initialise matrix_binary?



  • @SGaist said:

    I meant the matrix itself, not what its content is representing.

    Did you allocate that matrix properly ?

    On a side note, you can also use a QVector<QVector<int>> for a two dimensional storage.

    @jsulm said:

    @AlvaroS I think @SGaist wanted to know whether matrix_binary is pointing to a matrix and whether it has same dimensions as the picture (1000x938). How did you initialise matrix_binary?

    Matriz_binary values are 0 or 1 (white or black), now I am trying to represent that matrix in a scene with QPixmap.

    My code looks like this right now:

                    QImage imagen(1000,938, QImage::Format_Grayscale8);
    
                    for(int i=0;i<938;++i){
                        for(int j=0;j<1000;++j)
                            if (matrix_binary[i][j] == 1)
                                imagen.setPixel(i,j, qRgb(1,1,1));
                            else
                                imagen.setPixel(i,j, qRgb(0,0,0));
                    }
    
                    QPixmap pixmap_scene;
                    pixmap_scene.fromImage(imagen);
                    QGraphicsPixmapItem *item = scene->addPixmap(pixmap_scene); 
    

    but in some part before "for" it crashes....
    how can I do what I want? Maybe the format image?

    Thanks a lot



  • @AlvaroS

    Your matrix_binary allocated incorrectly. You should exchange width and height.

    like this:

    matrix = new int *[img.height()];
    for(int i=0;i<img.height();++i)
           matrix[i] = new int [img.width()];
    

    You can also use a QVector.

    like this:

    QVector<QVector<int>> matrix(img.height(), QVector<int>(img.width(), 0)); // 0 is initial value
    

  • Qt Champions 2019

    Where exactly does it crash? Did you try to debug to see what is happening?
    And still you did not answer the question regarding matrix_binary: how did you initialize it? It is clear that it contains 0/1 but that was not the question.
    And I think you should swap i and j:

    QImage imagen(1000,938, QImage::Format_Grayscale8);
    

    width=1000, height=938
    but then you do:

    for(int i=0;i<938;++i){
        for(int j=0;j<1000;++j)
            ...
            imagen.setPixel(i,j, qRgb(1,1,1)); // i is x and j is y
    


  • @Devopia53 said:

    @AlvaroS

    Your matrix_binary allocated incorrectly. You should exchange width and height.

    like this:

    matrix = new int *[img.height()];
    for(int i=0;i<img.height();++i)
           matrix[i] = new int [img.width()];
    

    You can also use a QVector.

    like this:

    QVector<QVector<int>> matrix(img.height(), QVector<int>(img.width(), 0)); // 0 is initial value
    

    If I do what you say it does not crash, but know it says:

    .
    .
    .
    QImage::setPixel: coordinate (937,991) out of range
    QImage::setPixel: coordinate (937,992) out of range
    QImage::setPixel: coordinate (937,993) out of range
    QImage::setPixel: coordinate (937,994) out of range
    QImage::setPixel: coordinate (937,995) out of range
    .
    .
    .
    

    The code now look like this:

     int vector_binary[1000*938];
    
    /*matrix binary creation*/
                    int **matrix_binary;
                    matrix_binary = new int *[938];
                    for(int i=0;i<938;++i)
                        matrix_binary[i] = new int [1000];
    
    /*read vecotr from a binary file*/
                    infile.read((char*)(vector_binary), sizeof(int)*1000*938);
    
    /*Initialitation of matrix_binary*/
                    for(int i=0;i<938;++i){
                        for(int j=0;j<1000;++j){
                            matrix_binary[i][j] = 0;
                        }
                    }
    
    /*Store the data into matrix_binary*/
                    for(int i=0;i<938;++i){
                        for(int j=0;j<1000;++j){
                            matrix_binary[i][j] = vector_binary[i*1000+j];
                            }
                    }
    
    
    
                    //From matrix to QImage to visualize
                    //Create matrix where each element will be a pixel value.
                    QImage imagen(1000,938, QImage::Format_RGB666);
                    for(int w=0;w<938;w++){
                        for(int z=0;z<1000;z++)
                            if (matrix_binary[w][z] == 1)
                                imagen.setPixel(w,z, qRgb(250,250,250));
                            else
                                imagen.setPixel(w,z, qRgb(0,0,0));
                    }
                    //QPixmap pixmap_scene;
                    QPixmap pixmap_scene = QPixmap::fromImage(imagen);
                }
            }
    

    I think that the problem is in setPixel...



  • @jsulm said:

    Where exactly does it crash? Did you try to debug to see what is happening?
    And still you did not answer the question regarding matrix_binary: how did you initialize it? It is clear that it contains 0/1 but that was not the question.
    And I think you should swap i and j:

    QImage imagen(1000,938, QImage::Format_Grayscale8);
    

    width=1000, height=938
    but then you do:

    for(int i=0;i<938;++i){
        for(int j=0;j<1000;++j)
            ...
            imagen.setPixel(i,j, qRgb(1,1,1)); // i is x and j is y
    

    Yes sorry! See my last post :)



  • However if i save pixemap_scene in a .jpeg it save me fine with the correct image...


  • Qt Champions 2019

    @AlvaroS

    QImage::setPixel: coordinate (937,991) out of range
    QImage::setPixel: coordinate (937,992) out of range
    QImage::setPixel: coordinate (937,993) out of range
    QImage::setPixel: coordinate (937,994) out of range
    QImage::setPixel: coordinate (937,995) out of range
    

    Now take a look how you initialized QImage:

    QImage imagen(1000,938, QImage::Format_Grayscale8);
    

    So, max value for y is 937 but you pass values like 991!



  • Hi! The following is still unnecessarily slow but at least it works and doesn't waste so much memory as before:

        const QPixmap pixmap("/home/user/myimage.jpg");
        ui->label->setPixmap(pixmap);
    
        const QImage image = pixmap.toImage();
        const int width = image.width();
        const int height = image.height();
        QBitArray bitArray(width*height);
    
        for (int h=0; h<height; ++h) {
            for (int w=0; w<width; ++w) {
                bitArray[h*width+w] = qGray(image.pixel(w,h)) > 127 ? 0 : 1;
            }
        }
    
        /* Do something with the bit array here */
    
        QImage monoImage(width, height, QImage::Format_Mono);
        for (int h=0; h<height; ++h) {
            for (int w=0; w<width; ++w) {
                monoImage.setPixel(w, h, bitArray.at(h*width+w));
            }
        }
    
        ui->label_2->setPixmap( QPixmap::fromImage(monoImage) );
    

Log in to reply