Read Webp from Memory Error

Hi, I have function like this:

int GetCLAHEImage(char * image, int image_size, double clip_limit, int grid_size, int mode, char** image_out_data, int *image_out_length) {
	std::vector<char> image_data(image, image+image_size);
	auto matInfo = cv::Mat(image_data);
	cv::Mat img = cv::imdecode(cv::Mat(image_data), 1);
	applyClahe(img, clip_limit, grid_size, mode);
	std::vector<uchar> buffer;
	cv::imencode(".png", img, buffer);
	*image_out_data = new char[buffer.size()];
	*image_out_length = buffer.size();
	memcpy(*image_out_data, &buffer[0], buffer.size());
	return DE_NO_ERROR;
}

When I run it with a encoded png everything is fine, but running it with a encoded webp (image variable) I get the following error at the line of imdecode:

imdecode_(’’): can’t read data: OpenCV(4.5.2) /opencv-4.5.2/modules/imgcodecs/src/grfmt_webp.cpp:164: error: (-215:Assertion failed) data.type() == CV_8UC1 in function ‘readData’

terminate called after throwing an instance of ‘cv::Exception’
what(): OpenCV(4.5.2) /opencv-4.5.2/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function ‘cvtColor’

SIGABRT: abort
PC=0x7f2498b65ef5 m=4 sigcode=18446744073709551610

I use opencv 4.5.2, c++ and manjaro linux (error also occurs on debian and ubuntu)

The function is part of a library and I call it using cgo

	fmt.Println("image info: ", http.DetectContentType(img.ImageBytes))
        // --> returns image/webp
	imgBytesOut, err := mylib.GetCLAHEImage(img.ImageBytes, m.ClipLimit, m.TileSize, mylib.CLAHE_LAB)

with a go_wrapper:

func GetCLAHEImage(image []byte, clip_limit float64, grid_size int, mode int) ([]byte, error) {
	var ret C.int
	var retlen C.int
	bytes := C.CString("")

	ret = C.GetCLAHEImage((*C.char)(unsafe.Pointer(&image[0])), C.int(len(image)), C.double(clip_limit), C.int(grid_size), C.int(mode), &bytes, &retlen)

	result := C.GoBytes(unsafe.Pointer(bytes), retlen)
	C.free(unsafe.Pointer(bytes))

	return result, nil
}

What could be wrong here? Is there a bug in opencv?

possible. please post a webp image file for testing.

using some webp file from wikipedia, I could not reproduce this.

please reduce your code to the bare minimum that reproduces the issue.

Hey,

here is a small test code:

	std::cout<<"before testimg"<<std::endl;
	auto testimg = cv::imread("./1.webp");
	std::vector<uchar> test_buffer;
	cv::imencode(".webp", testimg, test_buffer);

	char *buf = new char[test_buffer.size()];
	memcpy(buf, test_buffer.data(), test_buffer.size());

	std::vector<char> image_data_test(buf, buf+test_buffer.size());
	cv::Mat img_test = cv::imdecode(cv::Mat(image_data_test), 1);

	std::cout<<"after testimg"<<std::endl;

and here is the webp file:

https://www.gstatic.com/webp/gallery/1.webp

1 Like

I got a “fix” or workaround (i am not sure^^)

instead of reading the char * using std:vector I do this:

cv::Mat rawData_test = cv::Mat( 1, test_buffer.size(), CV_8UC1, buf );

so the example changes to

	std::cout<<"before testimg"<<std::endl;
	auto testimg = cv::imread("./1.webp");
	std::vector<uchar> test_buffer;
	cv::imencode(".webp", testimg, test_buffer);

	char *buf = new char[test_buffer.size()];
	memcpy(buf, test_buffer.data(), test_buffer.size());

	// std::vector<char> image_data_test(buf, buf+test_buffer.size());
    cv::Mat rawData_test  =  cv::Mat( 1, test_buffer.size(), CV_8UC1, buf );
	cv::Mat img_test = cv::imdecode(cv::Mat(rawData_test), 1);

	std::cout<<"after testimg"<<std::endl;

this works

the problem seems to be that

cv::Mat(std::vector image_data_test(buf, buf+test_buffer.size())) is of type CV_8S and not CV_8UC1, but when I tried to convert it the resulting Mat was empty

the type of that temporary Mat instance is CV_8S because image_data_test has type char, which is signed.

the API expects CV_8U (same as CV_8UC1), not CV_8S

it’s best to use uint8_t to be absolutely clear about the type.

it’s also a good idea to remove as many “conversion steps” as possible… if they’re superfluous, their only effect is to give more chance for bugs to happen.

I wonder why it is working with png’s

that type check is in the webp-specific code.

1 Like