我尝试使用Qt 5.7在c ++中编写应用程序,基本上它应该是一个websocket服务器,使用qwebsocket,能够将使用opencv详细说明的图像发送到HTML客户端。我想要做的是在base64中编码图像,传输并在客户端上将编码的字符串放在图像标记的src中。 只是为了测试,我可以正确发送/接收短信,因此websocket架构正在运行,但我有一些图像问题。这是我的代码片段:
服务器
cv::Mat imgIn;
imgIn = cv::imread("/home/me/color.png",CV_LOAD_IMAGE_COLOR);
QByteArray Img((char*)(imgIn.data),imgIn.total()*imgIn.elemSize());
QByteArray Img64 = Img.toBase64();
pClient->sendBinaryMessage(Img64);
客户端
<img id="ItemPreview" src="" style="border:5px solid black" />
...
websocket.binaryType = "arraybuffer";
websocket.onmessage = function (evt) {
console.log( "Message received :", evt.data );
document.getElementById("ItemPreview").src = "data:image/png;base64," + evt.data;
};
我认为大多数问题都在服务器中,因为我从图像中获得的base64序列与我从在线转换器image / base64获得的序列不同。 在客户端上,我在控制台中收到此错误,但未显示任何内容:
data:image / png; base64,[object ArrayBuffer]:1 GET data:image / png; base64,[object ArrayBuffer] net :: ERR_INVALID_URL
任何提示?
解
感谢您的建议,我可以提供工作代码:
服务器
imgIn = cv::imread("/home/me/color.png", CV_LOAD_IMAGE_UNCHANGED);
std::vector<uchar> buffer;
cv::imencode(".png",imgIn,buffer);
std::string s = base64_encode(buffer.data(),buffer.size());
pClient->sendTextMessage(QString::fromStdString(s));
客户端
删除了这一行:
websocket.binaryType = "arraybuffer";
服务器中的base64编码使用以下代码完成:
答案 0 :(得分:2)
服务器中的这一行:
imgIn = cv::imread("/home/me/color.png",CV_LOAD_IMAGE_COLOR);
解码 PNG格式的图像,并将其作为像素数据的加载放入内存中(加上可能还有一些行填充,您不会考虑,见下文)。那就是你的base64编码。
客户端中的这一行:
document.getElementById("ItemPreview").src = "data:image/png;base64," + evt.data;
期待PNG图片,但这并不是您发送的内容;你只是推出了大量的原始像素数据,没有任何尺寸或步幅或格式信息或其他任何内容。
如果您的客户想要PNG,您将不得不使用类似imencode
的内容将PNG数据写入内存缓冲区,而base64则对其进行编码。
另一个需要注意的重要事项是解码图像可能有行填充...每行末尾的几个字节用于存储器对齐目的。因此,每个图像行的实际长度可能超过图像的宽度乘以每个像素的大小(以字节为单位)。这意味着这个操作:
QByteArray Img((char*)(imgIn.data),imgIn.total()*imgIn.elemSize());
事实上,可能不会将整个图像缓冲区包裹在QByteArray
中。有多种方法可以检查图像的步幅/步长,但您最好阅读cv::Mat
文档,因为我不值得在这里重复这些文档。这只有在您进行原始字节级图像处理时才有意义,就像您在这里一样。如果您使用imencode
,则无需担心此事。