无法在释放模式下从字节数组加载 QImage
Cannot load QImage from byte array in release mode
在我的应用程序中,我通过 QTcpSocket
从 Android 设备接收 JPEG
格式的图像作为字节数组。
当我在我的开发 PC 上 运行 这个应用程序时,它的工作就像一个魅力(在调试和发布模式下)。但是,我无法从另一台未安装 Qt 的 PC 上的字节数组加载 QImage
。
我在 Qt 中为我的平台包含了所有 *.dll 文件(Windows x64,msvc_2015_64)并且还安装了 Visual Studio C++ Redistributable 2015。我的应用程序启动正常(doesn '给出一些 *.dll 文件丢失的任何错误)。但是QImage
一直是空的。
起初我以为字节数组根本没有被接收,所以我检查了它的大小,发现它被正确接收了。
我正在使用此代码从 uchar
字节加载 QImage
:
void handleImageBytes(uchar *bytes, qint64 length)
{
QImage image;
image.loadFromData(bytes, length, "JPEG");
emit frameReady(image);
}
我从 QTcpSocket
:
接收到这些字节
void handleReadyRead()
{
if(this->incomingFrameLength==0){
QString data = this->client->readAll();
this->incomingFrameLength = data.toInt();
this->client->write("ok");
qDebug()<<QString("Received frame length: %1").arg(this->incomingFrameLength);
return;
}
if(this->incomingFrameLength!=0 && this->client->bytesAvailable()<this->incomingFrameLength)
return;
uchar* data = (uchar*)malloc(this->incomingFrameLength+256);
qint64 len = this->client->read((char*)data, this->incomingFrameLength+256);
qDebug() << QString("Received %1 bytes").arg(len);
handleImageBytes(data, len);
this->incomingFrameLength=0;
this->client->write("received");
qDebug()<<QString("Received frame of length %1").arg(len);
free(data);
}
如您所见,首先我收到图像的大小作为字节数组的长度。
然后我等待 QTcpSocket
的缓冲区中接收并准备好所有需要的字节。然后我创建指向具有足够大小的字节数组的指针,将传入字节加载到该数组并从上面调用 handleImageBytes
方法。
这在我的开发 PC 上一切正常(Windows 7 x64,Qt 5.7,msvc_2015_64)。
但是,当我将我的发布代码和所有必需的 *.dll 文件移动到其他未安装 Qt 的 PC 时,从字节数组加载图像不起作用。
如何解决这个问题?
如果它在您的开发系统中工作,那么您可能仍然缺少一些 DLL。不幸的是,Qt 只会针对强制性 DLL 报错,但还有其他的,即插件,它们是可选的,并且某些功能只有在它们存在时才有可能(例如读取某些图像格式)而不显示任何 DLL 缺失 错误。
复制<QTDIR>\plugins\imageformats
文件夹(其中<QTDIR>
是你的Qt版本的安装路径,例如我的C:\Qt\qt_5_6_1\msvc2010
)到你的可执行文件所在的同一目录。请注意调试和发布二进制文件混合在同一个文件夹中,因此只需复制与您的构建配置相对应的那些。
您的项目目录应如下所示:
project\
project.exe
Qt5Core.dll
Qt5Gui.dll
...
imageformats\
qgif.dll
qico.dll
qjpeg.dll
...
Qt VS Add-on 会自动将一些目录添加到路径中,这就是当 运行 来自 IDE 时它不会失败的原因。
注意: 如果您想使用 SVG 图像,您还必须复制 iconengines\qsvgicon.dll
和 Qt5Svg.dll
。
在我的应用程序中,我通过 QTcpSocket
从 Android 设备接收 JPEG
格式的图像作为字节数组。
当我在我的开发 PC 上 运行 这个应用程序时,它的工作就像一个魅力(在调试和发布模式下)。但是,我无法从另一台未安装 Qt 的 PC 上的字节数组加载 QImage
。
我在 Qt 中为我的平台包含了所有 *.dll 文件(Windows x64,msvc_2015_64)并且还安装了 Visual Studio C++ Redistributable 2015。我的应用程序启动正常(doesn '给出一些 *.dll 文件丢失的任何错误)。但是QImage
一直是空的。
起初我以为字节数组根本没有被接收,所以我检查了它的大小,发现它被正确接收了。
我正在使用此代码从 uchar
字节加载 QImage
:
void handleImageBytes(uchar *bytes, qint64 length)
{
QImage image;
image.loadFromData(bytes, length, "JPEG");
emit frameReady(image);
}
我从 QTcpSocket
:
void handleReadyRead()
{
if(this->incomingFrameLength==0){
QString data = this->client->readAll();
this->incomingFrameLength = data.toInt();
this->client->write("ok");
qDebug()<<QString("Received frame length: %1").arg(this->incomingFrameLength);
return;
}
if(this->incomingFrameLength!=0 && this->client->bytesAvailable()<this->incomingFrameLength)
return;
uchar* data = (uchar*)malloc(this->incomingFrameLength+256);
qint64 len = this->client->read((char*)data, this->incomingFrameLength+256);
qDebug() << QString("Received %1 bytes").arg(len);
handleImageBytes(data, len);
this->incomingFrameLength=0;
this->client->write("received");
qDebug()<<QString("Received frame of length %1").arg(len);
free(data);
}
如您所见,首先我收到图像的大小作为字节数组的长度。
然后我等待 QTcpSocket
的缓冲区中接收并准备好所有需要的字节。然后我创建指向具有足够大小的字节数组的指针,将传入字节加载到该数组并从上面调用 handleImageBytes
方法。
这在我的开发 PC 上一切正常(Windows 7 x64,Qt 5.7,msvc_2015_64)。 但是,当我将我的发布代码和所有必需的 *.dll 文件移动到其他未安装 Qt 的 PC 时,从字节数组加载图像不起作用。
如何解决这个问题?
如果它在您的开发系统中工作,那么您可能仍然缺少一些 DLL。不幸的是,Qt 只会针对强制性 DLL 报错,但还有其他的,即插件,它们是可选的,并且某些功能只有在它们存在时才有可能(例如读取某些图像格式)而不显示任何 DLL 缺失 错误。
复制<QTDIR>\plugins\imageformats
文件夹(其中<QTDIR>
是你的Qt版本的安装路径,例如我的C:\Qt\qt_5_6_1\msvc2010
)到你的可执行文件所在的同一目录。请注意调试和发布二进制文件混合在同一个文件夹中,因此只需复制与您的构建配置相对应的那些。
您的项目目录应如下所示:
project\
project.exe
Qt5Core.dll
Qt5Gui.dll
...
imageformats\
qgif.dll
qico.dll
qjpeg.dll
...
Qt VS Add-on 会自动将一些目录添加到路径中,这就是当 运行 来自 IDE 时它不会失败的原因。
注意: 如果您想使用 SVG 图像,您还必须复制 iconengines\qsvgicon.dll
和 Qt5Svg.dll
。