Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use cv::imdecode, if the contents of an image file are in a char array?

Tags:

c++

opencv

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);
like image 235
Richard Knop Avatar asked Nov 24 '10 20:11

Richard Knop


People also ask

What format is the image read in OpenCV?

So, OpenCV can always read JPEGs, PNGs, and TIFFs. On MacOSX, there is also an option to use native MacOSX image readers.

What is cv2 Imdecode?

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)

What is CV Imencode?

cv.imencode. Encodes an image into a memory buffer. buf = cv. imencode(ext, img) buf = cv. imencode(ext, img, 'OptionName', optionValue, ...)


2 Answers

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;
}
like image 138
Programmer Avatar answered Oct 12 '22 11:10

Programmer


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);
like image 35
ronag Avatar answered Oct 12 '22 10:10

ronag