The cv::Mat
type holds a decoded image. Thus you cannot ask QImage
to decode it again using the loadFromData()
method.
You need to set up an image with format matching the element type, retrieved using Mat::type()
, then either copy the raw data from the matrix to the image, or set up a QImage
header for the data. In OpenCV terminology, a "header" means an object that doesn't hold its own data.
The code below sets up a header QImage
.
QMap<int, QImage::Format> fmtMap;
fmtMap.insert(CV8_UC4, QImage::Format_ARGB32);
fmtMap.insert(CV_8UC3, QImage::Format_RGB888)
// We should convert to a color image since 8-bit indexed images can't be painted on
cv::Mat mat = cv::imread("C:\\testimages\\img1.png", CV_LOAD_IMAGE_COLOR);
Q_ASSERT(fmtMap.contains(cvImage.type());
Q_ASSERT(mat.isContinuous());
QImage img(cvImage.data, cvImage.cols, cvImage.rows, fmtMap[cvImage.type()]);
// The matrix *must* outlive the image, otherwise the image will access a dangling pointer to data
It may be easier to load the image using QImage
, and then create a header matrix for it.
QMap<QImage::Format, int> fmtMap;
fmtMap.insert(QImage::Format_ARGB32, CV8_UC4);
fmtMap.insert(QImage::Format_RGB32, CV8_UC4);
fmtMap.insert(QImage::Format_RGB888, CV_8UC3);
QImage img;
img.load("C:\\testimages\\img1.png");
Q_ASSERT(fmtMap.contains(img.format()));
cv::Mat mat(img.height(), img.width(), fmtMap[img.format()], img.bits());
// The image *must* outlive the matrix, otherwise the matrix will access a dangling pointer to data