I have a jpeg image in buffer jpegBuffer. I'm trying to pass it to cv::imdecode function:
Mat matrixJprg = imdecode(Mat(jpegBuffer), 1);
I get this error:
/home/richard/Desktop/richard/client/src/main.cc:108: error: no matching function for call to ‘cv::Mat::Mat(char*&)’
This is how I fill jpegBuffer:
FILE* pFile;
long lSize;
char * jpegBuffer;
pFile = fopen ("img.jpg", "rb");
if (pFile == NULL)
{
exit (1);
}
// obtain file size.
fseek (pFile , 0 , SEEK_END);
lSize = ftell (pFile);
rewind (pFile);
// allocate memory to contain the whole file.
jpegBuffer = (char*) malloc (lSize);
if (jpegBuffer == NULL)
{
exit (2);
}
// copy the file into the buffer.
fread (jpegBuffer, 1, lSize, pFile);
// terminate
fclose (pFile);
So, OpenCV can always read JPEGs, PNGs, and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers.
Python cv2. imdecode() function is used to read image data from a memory cache and convert it into image format. This is generally used for loading the image efficiently from the internet. Syntax: cv2.imdecode(buf,flags)
cv.imencode. Encodes an image into a memory buffer. buf = cv. imencode(ext, img) buf = cv. imencode(ext, img, 'OptionName', optionValue, ...)
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):
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_LOAD_IMAGE_UNCHANGED);
//Create Window and display it
namedWindow("Image from Char Array", CV_WINDOW_AUTOSIZE);
if (!(matImg.empty()))
{
imshow("Image from Char Array", matImg);
}
waitKey(0);
delete[] buffer;
return 0;
}
Mat has no constructor that takes a char* argument. Try this instead:
std::ifstream file("img.jpg");
std::vector<char> data;
file >> std::noskipws;
std::copy(std::istream_iterator<char>(file), std::istream_iterator<char>(), std::back_inserter(data));
Mat matrixJprg = imdecode(Mat(data), 1);
EDIT:
You should also take a look at LoadImageM.
If you have your data already in a char* buffer one way is to copy the data into an std::vector.
std::vector<char> data(buf, buf + size);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With