Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. [SOLVED] save QVector<QImage> to QDataStream and read back
Forum Updated to NodeBB v4.3 + New Features

[SOLVED] save QVector<QImage> to QDataStream and read back

Scheduled Pinned Locked Moved General and Desktop
20 Posts 2 Posters 10.0k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • C Offline
    C Offline
    chebhou
    wrote on last edited by
    #1

    I'm trying to save and load QVector<QImage> to a file with QDataStream using this code :

    for saving
    @
    QFile file("students_dataset.dat");
    file.open(QIODevice::WriteOnly);
    QDataStream out(&file);
    out << qimgvect ;
    file.flush();
    file.close();
    @

    for loading

    @
    QFile file("students_dataset.dat");
    file.open(QIODevice::ReadOnly);
    QDataStream in(&file);
    QVector<QImage> qimgvect;
    in >> qimgvect;
    file.close();
    @

    but i get a weird result :
    !http://i.stack.imgur.com/9lJb1.png(saveed)! saved
    !http://i.stack.imgur.com/sMsnL.png(loaded)! loaded

    what is wrong with this code?
    is there a better way to do it ?

    1 Reply Last reply
    0
    • F Offline
      F Offline
      Francknos
      wrote on last edited by
      #2

      I use the same code with more complicated "structure" with images B&W and for me it's work. However I limited with 53 images in my datastream but i think it's size of my images which are too big (10800*480) ...

      1 Reply Last reply
      0
      • F Offline
        F Offline
        Francknos
        wrote on last edited by
        #3

        Some idea:
        I pass the size of my vector in my stream at wirte. And after the contents:
        @
        QFile file("students_dataset.dat");
        file.open(QIODevice::ReadOnly);
        QDataStream in(&file);
        int nbImages =-1;
        in >> nbImages;
        QVector<QImage> qimgvect;
        for(int i=0; i<nbImages ;i++)
        {
        QImage img;
        in >> img;
        qimgvect.append(img);
        }
        file.close();
        @

        Try this...

        1 Reply Last reply
        0
        • C Offline
          C Offline
          chebhou
          wrote on last edited by
          #4

          thank you for replay , but do you mean that the problem is in the
          @ QDataStream << Qvector<T> @

          not in QImage

          the image size is only 70x70 and i was testing with few images

          1 Reply Last reply
          0
          • F Offline
            F Offline
            Francknos
            wrote on last edited by
            #5

            No no I didn't say that the problem is in QVector but for a my progress dialog I use this code.
            Try it and say me something.

            1 Reply Last reply
            0
            • C Offline
              C Offline
              chebhou
              wrote on last edited by
              #6

              thanks for help, I have tried as you suggested but i got the same results
              here is the saving part :
              @
              QFile file("students_dataset.dat");
              file.open(QIODevice::WriteOnly);
              QDataStream out(&file);
              qimgvect.clear();
              int nbImages = qimgvect.size();
              out << nbImages;
              for(int i=0; i<nbImages ;i++)
              {
              QImage img = qimgvect.value(i);
              out << img;
              }
              file.flush();
              file.close();
              @

              I think the problem is in the image format ( indexed8) but I'm not that good to figure it out

              1 Reply Last reply
              0
              • F Offline
                F Offline
                Francknos
                wrote on last edited by
                #7

                Oh ! of course ! By default the format is RGB32bit
                try this:

                @
                QVector<QRgb> grayscale;
                for (int i = 0; i < 256; ++i)
                grayscale.append(qRgb(i, i, i));

                QFile file("students_dataset.dat");
                file.open(QIODevice::ReadOnly);
                QDataStream in(&file);
                int nbImages =-1;
                in >> nbImages;
                QVector<QImage> qimgvect;
                for(int i=0; i<nbImages ;i++)
                {
                QImage img;
                in >> img;
                img = img.conconvertToFormat(QImage::Format_Indexed8,grayscale);
                qimgvect.append(img);
                }
                file.close();
                @

                1 Reply Last reply
                0
                • C Offline
                  C Offline
                  chebhou
                  wrote on last edited by
                  #8

                  thanks that was a great step ahead , do I need to change the format also before saving because the result is :
                  !http://i.stack.imgur.com/Y8LLI.png(result)!

                  1 Reply Last reply
                  0
                  • F Offline
                    F Offline
                    Francknos
                    wrote on last edited by
                    #9

                    If you want use QImage with B&W You must fill image with grayscale !!!

                    When you write your image :
                    @QVector<QRgb> grayscale;
                    for (int i = 0; i < 256; ++i)
                    grayscale.append(qRgb(i, i, i));

                    QImage img;
                    img.fill(grayscale);
                    // And now your can write in your image with img.setPixel(x,y,0..255);
                    @

                    1 Reply Last reply
                    0
                    • C Offline
                      C Offline
                      chebhou
                      wrote on last edited by
                      #10

                      sorry for taking long , the original image is already in (indexed8) format and it's filled before so i'm asking if i should convert it to RGB32 before saving , any suggestion would be appreciated, thanks

                      1 Reply Last reply
                      0
                      • F Offline
                        F Offline
                        Francknos
                        wrote on last edited by
                        #11

                        No you don't have to convert before saving can you send me your code ?

                        1 Reply Last reply
                        0
                        • C Offline
                          C Offline
                          chebhou
                          wrote on last edited by
                          #12

                          do i post it here or send it in another way ?

                          1 Reply Last reply
                          0
                          • F Offline
                            F Offline
                            Francknos
                            wrote on last edited by
                            #13

                            you can send me francknos[at]gmail.com

                            1 Reply Last reply
                            0
                            • C Offline
                              C Offline
                              chebhou
                              wrote on last edited by
                              #14

                              @
                              void savedata(const std::vectorcv::Mat* MatVect,const std::vector<int>* intVect){
                              QFile file("students_dataset.dat");
                              file.open(QIODevice::WriteOnly);
                              QDataStream out(&file);
                              qimgvect.clear();
                              for (size_t i = 0; i < MatVect->size(); ++i) {
                              cv::Mat matt = MatVect->at(i);
                              QImage img= Mat2QImage(matt);
                              qimgvect.push_back(img);
                              }
                              QVector<int> qintvect = QVector<int>::fromStdVector(*intVect);

                                  int nbImages = qimgvect.size();
                                  out << nbImages;
                                  for(int i=0; i<nbImages ;i++)
                                  {
                                      QImage img = qimgvect.value(i);
                                      out << img;
                                  }
                                  out  << qintvect;
                                  file.flush();
                                  file.close();
                                  return;
                              

                              }

                              void loadData(std::vectorcv::Mat* MatVect,std::vector<int>* intVect){
                              QFile file("students_dataset.dat");
                              file.open(QIODevice::ReadOnly);
                              QDataStream in(&file);
                              qimgvect.clear();
                              MatVect->clear();
                              QVector<int> qintvect ;
                              int nbImages =-1;
                              QVector<QRgb> grayscale;
                              for (int i = 0; i < 256; ++i) grayscale.append(qRgb(i, i, i));

                              in >> nbImages;
                              for(int i=0; i<nbImages ;i++)
                              {
                                   QImage img;
                                   in >> img;
                                   img = img.convertToFormat(QImage::Format_Indexed8,grayscale);
                                   qimgvect.push_back(img);
                              }
                              in >> qintvect;
                              
                              for (size_t i = 0; i < qimgvect.size(); ++i) {
                                  QImage img = qimgvect.value(i);
                                  cv::Mat matt = QImage2Mat(img);
                                  MatVect->push_back(matt);
                              }
                              *intVect  = qintvect.toStdVector();
                              file.close();
                              return;
                              

                              }
                              @

                              1 Reply Last reply
                              0
                              • F Offline
                                F Offline
                                Francknos
                                wrote on last edited by
                                #15

                                Are you sure that
                                @QImage img= Mat2QImage(matt);@
                                construct a Image Index_8 ?
                                try qDebug on each pixel of img and look if all pixel are between 0 and 255.
                                Or try to convert in written:
                                @
                                for (size_t i = 0; i < MatVect->size(); ++i)
                                {
                                cv::Mat matt = MatVect->at(i);
                                QImage img= Mat2QImage(matt).convertToFormat(QImage::Format_Indexed8,grayscale);
                                qimgvect.push_back(img);
                                }
                                @

                                1 Reply Last reply
                                0
                                • C Offline
                                  C Offline
                                  chebhou
                                  wrote on last edited by
                                  #16

                                  Here is the the function :
                                  @
                                  QImage Mat2QImage(cv::Mat const& src)
                                  {
                                  cv::Mat temp; // make the same cv::Mat
                                  src.copyTo(temp);
                                  QImage dest((const uchar *) temp.data, temp.cols, temp.rows, temp.step, QImage::Format_Indexed8);
                                  dest.bits(); // enforce deep copy
                                  return dest;
                                  }
                                  @
                                  I've converted them as you suggested also I've checked using
                                  @qDebug() << QString::number(img.isGrayscale());@

                                  the result was always 1
                                  all the image have the same effect : image repeated 4 times horizontally inside itself like shown :
                                  !http://i.stack.imgur.com/Y8LLI.png(img)!
                                  thanks again for your help

                                  1 Reply Last reply
                                  0
                                  • F Offline
                                    F Offline
                                    Francknos
                                    wrote on last edited by
                                    #17

                                    try this function :
                                    @
                                    /* OpenCV ===========================================================================/
                                    QImage cvtCvMat2QImage(const cv::Mat & image, bool isBgr)
                                    {
                                    QImage qtemp;
                                    if(!image.empty() && image.depth() == CV_8U)
                                    {
                                    if(image.channels()==3)
                                    {
                                    const unsigned char * data = image.data;
                                    if(image.channels() == 3)
                                    {
                                    qtemp = QImage(image.cols, image.rows, QImage::Format_RGB32);
                                    for(int y = 0; y < image.rows; ++y, data += image.cols
                                    image.elemSize())
                                    {
                                    for(int x = 0; x < image.cols; ++x)
                                    {
                                    QRgb * p = ((QRgb*)qtemp.scanLine (y)) + x;
                                    if(isBgr)
                                    {
                                    *p = qRgb(data[x * image.channels()+2], data[x * image.channels()+1], data[x * image.channels()]);
                                    }
                                    else
                                    {
                                    *p = qRgb(data[x * image.channels()], data[x * image.channels()+1], data[x * image.channels()+2]);
                                    }
                                    }
                                    }
                                    }
                                    }
                                    else if(image.channels() == 1)
                                    {
                                    // mono grayscale
                                    qtemp = QImage(image.data, image.cols, image.rows, image.cols, QImage::Format_Indexed8).copy();
                                    QVector<QRgb> my_table;
                                    for(int i = 0; i < 256; i++) my_table.push_back(qRgb(i,i,i));
                                    qtemp.setColorTable(my_table);
                                    }
                                    else
                                    {
                                    printf("Wrong image format, must have 1 or 3 channels\n");
                                    }
                                    }
                                    return qtemp;
                                    }

                                    cv::Mat cvtQImage2CvMat(const QImage & image)
                                    {
                                    cv::Mat cvImage;
                                    if(!image.isNull() && image.depth() == 32 && image.format() == QImage::Format_RGB32)
                                    {
                                    // assume RGB (3 channels)
                                    int channels = 3;
                                    cvImage = cv::Mat(image.height(), image.width(), CV_8UC3);
                                    unsigned char * data = cvImage.data;
                                    for(int y = 0; y < image.height(); ++y, data+=cvImage.cols*cvImage.elemSize())
                                    {
                                    for(int x = 0; x < image.width(); ++x)
                                    {
                                    QRgb rgb = image.pixel(x, y);
                                    data[x * channels+2] = qRed(rgb); //r
                                    data[x * channels+1] = qGreen(rgb); //g
                                    data[x * channels] = qBlue(rgb); //b
                                    }
                                    }
                                    }
                                    else
                                    {
                                    printf("Failed to convert image : depth=%d(!=32) format=%d(!=%d)\n", image.depth(), image.format(), QImage::Format_RGB32);
                                    }
                                    return cvImage;
                                    }

                                    QImage cvtIplImage2QImage(const IplImage * image)
                                    {
                                    QImage qtemp;
                                    if (image && image->depth == IPL_DEPTH_8U && cvGetSize(image).width>0)
                                    {
                                    const char * data = image->imageData;
                                    qtemp= QImage(image->width, image->height,QImage::Format_RGB32);

                                        for(int y = 0; y < image->height; ++y, data +=image->widthStep )
                                        {
                                            for(int x = 0; x < image->width; ++x)
                                            {
                                                uint *p = (uint*)qtemp.scanLine (y) + x;
                                                *p = qRgb(data[x * image->nChannels+2], data[x * image->nChannels+1],data[x * image->nChannels]);
                                            }
                                        }
                                    }
                                    else if(image && image->depth != IPL_DEPTH_8U)
                                    {
                                        printf("Wrong iplImage format, must be 8_bits\n");
                                    }
                                    return qtemp;
                                    

                                    }

                                    // Returned image must be released explicitly (using cvReleaseImage()).
                                    IplImage * cvtQImage2IplImage(const QImage & image)
                                    {
                                    IplImage * iplTmp = 0;
                                    if(!image.isNull() && image.depth() == 32 && image.format() == QImage::Format_RGB32)
                                    {
                                    // assume RGB (3 channels)
                                    int channels = 3;
                                    iplTmp = cvCreateImage(cvSize(image.width(), image.height()), IPL_DEPTH_8U, channels);
                                    char * data = iplTmp->imageData;
                                    for(int y = 0; y < image.height(); ++y, data+=iplTmp->widthStep)
                                    {
                                    for(int x = 0; x < image.width(); ++x)
                                    {
                                    QRgb rgb = image.pixel(x, y);
                                    data[x * channels+2] = qRed(rgb); //r
                                    data[x * channels+1] = qGreen(rgb); //g
                                    data[x * channels] = qBlue(rgb); //b
                                    }
                                    }
                                    }
                                    else
                                    {
                                    printf("Failed to convert image : depth=%d(!=32) format=%d(!=%d)\n", image.depth(), image.format(), QImage::Format_RGB32);
                                    }
                                    return iplTmp;
                                    }
                                    @

                                    1 Reply Last reply
                                    0
                                    • C Offline
                                      C Offline
                                      chebhou
                                      wrote on last edited by
                                      #18

                                      thank you Francknos for keeping up with me, I have tried converting the image before saving and it did solve the problem
                                      @ img = img.convertToFormat(QImage::Format_ARGB32); @

                                      Here is the saving part now :
                                      @
                                      QFile file("students_dataset.dat");
                                      file.open(QIODevice::WriteOnly);
                                      QDataStream out(&file);
                                      qimgvect.clear();
                                      int nbImages = qimgvect.size();
                                      out << nbImages;
                                      for(int i=0; i<nbImages ;i++)
                                      {
                                      QImage img = qimgvect.value(i);
                                      img = img.convertToFormat(QImage::Format_ARGB32);
                                      out << img;
                                      }
                                      file.flush();
                                      file.close();
                                      @
                                      Format_ARGB32 is the reason for the effect in the result ( 4 channels )
                                      I'll try to elemenate the for loop and post back .
                                      thank you !

                                      1 Reply Last reply
                                      0
                                      • F Offline
                                        F Offline
                                        Francknos
                                        wrote on last edited by
                                        #19

                                        Glad it's works !!

                                        1 Reply Last reply
                                        0
                                        • C Offline
                                          C Offline
                                          chebhou
                                          wrote on last edited by
                                          #20

                                          SO Here is the final solution :
                                          for saving grayscale Qimage through *QDataStream * convert it to Format_ARGB32 then save it, for loading convert it back to Format_Indexed8 :
                                          saving code
                                          @
                                          QFile file("students_dataset.dat");
                                          file.open(QIODevice::WriteOnly);
                                          QDataStream out(&file);
                                          //converting to ARGB32
                                          foreach (QImage img, qimgvect) {
                                          img = img.convertToFormat(QImage::Format_ARGB32);
                                          }
                                          // saving to QDataStream
                                          out << qimgvect ;
                                          file.flush();
                                          file.close();
                                          @
                                          for loading
                                          @
                                          QFile file("students_dataset.dat");
                                          file.open(QIODevice::ReadOnly);
                                          QDataStream in(&file);
                                          QVector<QImage> qimgvect;
                                          // loading images vector from QDatastream
                                          in >> qimgvect;
                                          // converting to grayscale
                                          QVector<QRgb> grayscale;
                                          for (int i = 0; i < 256; ++i) grayscale.append(qRgb(i, i, i));
                                          for (int i, i < qimgvect.size(),i++) {
                                          QImage img = qimgvect.at(i).convertToFormat(QImage::Format_Indexed8,grayscale);
                                          qimgvect.push_back(img);
                                          }
                                          file.close();
                                          @

                                          I think even QImage with other Formats will face the same problem since it is assumed that the default format is Format_ARGB32

                                          1 Reply Last reply
                                          0

                                          • Login

                                          • Login or register to search.
                                          • First post
                                            Last post
                                          0
                                          • Categories
                                          • Recent
                                          • Tags
                                          • Popular
                                          • Users
                                          • Groups
                                          • Search
                                          • Get Qt Extensions
                                          • Unsolved