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.1k 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
    #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