I have a vertically flipped RGBA image stored in uchar[] raw_data
, but I need it in grayscale cv::Mat
. This can be easily achieved using following code:
cv::Mat src(width, height, CV_8UC4, raw_data), tmp, dst;
cvtColor(src, tmp, CV_RGBA2GRAY);
flip(tmp, dst, 0);
However, I found out that following code is up to two times faster:
int linesize = width * 4; // 4 bytes per RGBA pixel
uchar *data_ptr = raw_data + linesize * (height-1); // ptr to last line
cv::Mat tmp(width, height, CV_8UC4, data_ptr, -linesize), dst;
cvtColor(tmp, dst, CV_RGBA2GRAY);
The trick is quite obvious: tmp
is created with pointer to last line and negative line size, so it moves back in memory when iterating over lines. This results in cvtColor
by-the-way vertical image flip. Image data is iterated over only once instead of twice, which gives aforementioned boost. I've tested it, it works, end of story.
The questions is: is there any reason to do it the first way? I'm aware, that the fourth parameter in used cv::Mat
ctor have size_t
type, so in fact this is based on pointer overflows. The code goes to different devices, including smartphones and tablets, so performance is important. On the other hand, it will be compiled to different architectures (x86, ARM), so portability must be preserved.
Thanks in advance!