I had to do the-same thing and my image data was already in char
array format and was arriving from a network and a plugin source. The current answer shows how to do this but it requires copying the data into a vector first which is a waste of time and resources.
This is possible to do directly without creating a copy of it. You were so close with your imdecode(Mat(jpegBuffer), 1);
code in your question.
You need to use the constructor overload for the Mat
class below:
Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
To create this Mat
, pass 1
to the rows, the size of the array to the cols, CV_8UC1
to the type and the char array itself to the data param. Pass this Mat
to the cv::imdecode
function with the mat as the first param and CV_LOAD_IMAGE_UNCHANGED
as the second param.
Basic example:
char *buffer = dataFromNetwork;
int bufferLength = sizeOfDataFromNetwork;
cv::Mat matImg;
matImg = cv::imdecode(cv::Mat(1, bufferLength, CV_8UC1, buffer), CV_LOAD_IMAGE_UNCHANGED);
Complete Example (Reads file named "test.jpg" into char array and uses imdecode
to decode the data from the char array then displays it):
#include <iostream>
#include <fstream>
#include <opencv2/highgui.hpp>
#include <string>
using namespace std;
int main()
{
// Open image file to read from
char imgPath[] = "./test.jpg";
ifstream fileImg(imgPath, ios::binary);
fileImg.seekg(0, std::ios::end);
int bufferLength = fileImg.tellg();
fileImg.seekg(0, std::ios::beg);
if (fileImg.fail())
{
cout << "Failed to read image" << endl;
cin.get();
return -1;
}
// Read image data into char array
char* buffer = new char[bufferLength];
fileImg.read(buffer, bufferLength);
// Decode data into Mat
cv::Mat matImg;
matImg = cv::imdecode(cv::Mat(1, bufferLength, CV_8UC1, buffer), cv::IMREAD_UNCHANGED);
// Create Window and display it
namedWindow("Image from Char Array", cv::WINDOW_AUTOSIZE);
if (!(matImg.empty()))
{
imshow("Image from Char Array", matImg);
}
cv::waitKey(0);
delete[] buffer;
return 0;
}