Reputation: 442
I need to get all the pixels data of an image in a string, with each pixel taking 6 characters, 2 for each RGB channel, i'm storing them in HEX, so the 0-255 can be written as 00-FF, so, for example, an all white pixel would be "ffffff", and an all black one "000000".
This is the code i currently have, using OpenCV, it is taking around 300ms for a 288x160 image:
Mat image = imread("image.jpg");
resize(image, image, Size(288, 160));
Vec3b buf;
stringstream ss;
auto start = high_resolution_clock::now();
for (int i = 0; i < image.rows; i++) {
for (int j = 0; j < image.cols; j++) {
buf = image.at<Vec3b>(i, j);
ss << hex << setfill('0') << setw(2) << (int) buf[0] << setw(2) << (int) buf[1] << setw(2) << (int) buf[2];
}
}
string output = ss.str();
auto stop = high_resolution_clock::now();
auto duration = duration_cast<milliseconds>(stop - start);
cout << "Execution time: " << duration.count() << " ms" << endl;
Is there any other better/faster way to do it? I know that the concept itself is not very efficient, but i really need to get a string out of it, 300ms is not that bad tbh, but the faster, the better
Upvotes: 0
Views: 283
Reputation: 596387
If speed is an issue, then get rid of the stringstream
altogether and just fill the string
manually using some bit-shifting to calculate the hex digits, eg:
Mat image = imread("image.jpg");
resize(image, image, Size(288, 160));
const char *hexDigits = "0123456789abcdef";
auto start = high_resolution_clock::now();
string output((image.rows * image.cols) * 6, '\0');
size_t idx = 0;
for (int i = 0; i < image.rows; ++i) {
for (int j = 0; j < image.cols; ++j) {
Vec3b &buf = image.at<Vec3b>(i, j);
for(int k = 0; k < 3; ++k) {
uchar ch = buf[k];
output[idx++] = hexDigits[(ch >> 4) & 0x0F];
output[idx++] = hexDigits[ch & 0x0F];
}
}
}
auto stop = high_resolution_clock::now();
auto duration = duration_cast<milliseconds>(stop - start);
cout << "Execution time: " << duration.count() << " ms" << endl;
Alternatively, this loop might shave off a few extra milliseconds, by not having to call image.at()
for every individual pixel:
for (int i = 0; i < image.rows; ++i) {
Vec3b *buf = image.ptr<Vec3b>(i, 0);
const Vec3b* buf_end = buf + image.cols;
while (buf != buf_end) {
for(int k = 0; k < 3; ++k) {
uchar ch = (*buf)[k];
output[idx++] = hexDigits[(ch >> 4) & 0x0F];
output[idx++] = hexDigits[ch & 0x0F];
}
++buf;
}
}
Upvotes: 4