[SOLVED] save QVector<QImage> to QDataStream and read back
-
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)! loadedwhat is wrong with this code?
is there a better way to do it ? -
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) ...
-
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...
-
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
-
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. -
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
-
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();
@ -
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)! -
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);
@ -
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
-
No you don't have to convert before saving can you send me your code ?
-
do i post it here or send it in another way ?
-
you can send me francknos[at]gmail.com
-
@
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;
}
@ -
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);
}
@ -
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 -
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.colsimage.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;
}
@ -
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 ! -
Glad it's works !!
-
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