qt: unable to read image from url - qt

I have two list of images to be downloaded from network. I use qnetworkaccessmanager to get image from url. But on the reply slot there is no image data with the reply. :( I am not able to figure out where am I going wrong.. If someone is able to figure out, it would be helpful :)
void SyncDialog::getImages()
{
qDebug() << Q_FUNC_INFO << "Invoked";
int groupMasterCount = mSyncMasterData.groupMasterList.count();
qDebug() << Q_FUNC_INFO << "groupmastercout" << groupMasterCount;
for (int i = 0 ; i < groupMasterCount; ++i)
{
GroupMaster groupItem = mSyncMasterData.groupMasterList.at(i);
QNetworkReply *reply =
mImageGetNwMgr.get(QNetworkRequest(QUrl(groupItem.image)));
reply->setProperty("name", QVariant("G_" + groupItem.groupCode));
connect(reply, SIGNAL(readyRead()), this, SLOT(saveImage()));
qDebug() << Q_FUNC_INFO << "get call reply" << reply->readAll();
qDebug() << Q_FUNC_INFO << "get url" << groupItem.image;
mSyncMasterData.groupMasterList[i].image.clear();
#ifdef Q_OS_WIN
mSyncMasterData.groupMasterList[i].image = "C:/POS/Images/G_"
+groupItem.groupCode;
#else
mSyncMasterData.groupMasterList[i].image = "/mnt/sdcard/POS/Images/G_"
+groupItem.groupCode;
#endif
}
int itemMasterCount = mSyncMasterData.itemMasterList.count();
qDebug() << Q_FUNC_INFO << "itemmastercout" << itemMasterCount;
for (int i = 0 ; i < itemMasterCount; ++i)
{
ItemMaster item = mSyncMasterData.itemMasterList.at(i);
QNetworkReply *reply =
mImageGetNwMgr.get(QNetworkRequest(QUrl(item.imagePath)));
reply->setProperty("name", QVariant("I_" + item.itemCode));
connect(reply, SIGNAL(readyRead()), this, SLOT(saveImage()));
qDebug() << Q_FUNC_INFO << "get call reply" << reply->readAll();
qDebug() << Q_FUNC_INFO << "get url" << item.imagePath;
mSyncMasterData.itemMasterList[i].imagePath.clear();
#ifdef Q_OS_WIN
mSyncMasterData.itemMasterList[i].imagePath = "C:/POS/Images/I_"
+item.itemCode;
#else
mSyncMasterData.itemMasterList[i].imagePath = "/mnt/sdcard/POS/Images/G_"
+item.itemCode;
#endif
}
qDebug() << Q_FUNC_INFO << "Exits";
}
In my slot I save images , but in reply->readAll gives me ""
void SyncDialog::saveImage()
{
qDebug() << Q_FUNC_INFO << "Invoked";
QObject *senderObj = sender();
QNetworkReply *reply = qobject_cast<QNetworkReply*>(senderObj);
QImage* img2 = new QImage();
img2->loadFromData(reply->readAll());
qDebug() << Q_FUNC_INFO << "image nw reply" << reply->readAll();
QString imageName = reply->property("name").toString();
qDebug() << Q_FUNC_INFO << "imageName" << imageName;
if(img2->isNull())
{
qDebug() << Q_FUNC_INFO << "image is null";
return;
}
#ifdef Q_OS_WIN
img2->save("C:/POS/Images/" + imageName);
#else
img2->save("/mnt/sdcard/POS/Images/" + imageName);
#endif
qDebug() << Q_FUNC_INFO << "Exits";
}
Also I see in logs "libpng error: Read Error" and the slot is invoked multiple times...

Thanks all,
I resolved the issue with few changes :)
connect(reply, SIGNAL(finished()), this, SLOT(saveImage()));
finished() makes sure complete image data is received from n/w.
QByteArray imageData = reply->readAll();
QImage *image = new QImage();
image->loadFromData(imageData);
reply->readAll() should be saved as first call clears the data after returning it.
image->save("C:/POS/Images/" + imageName + ".png"
don't forget to specify image format (either in filename or as parameter)

Related

Using 7za for unzipping with qt and cpp

I am using 7za.exe as subprocess to unzip the files with qt and cpp. I used a checkbox to include the option of recursive unzipping, the recursive option does not seem to work here. Could anyone suggest where I am doing wrong?
void MainWindow::uncompressZipFile()
{
QStringList queryArguments;
queryArguments << "e";
queryArguments << """" + choosenDir + """"+"/*.zip";
if(ui->checkBox->isChecked())
queryArguments << "-ro"+choosenDir+"/example";
queryArguments << "-o"+choosenDir+"/example";
QFileInfoList dirs;
QFileInfoList files;
for(int i=0; i < dirs.size(); i++)
{
qDebug() << "Directories listed here";
qDebug() << dirs.at(i);
}
QDirIterator it(choosenDir, QStringList() << "*.zip", QDir::Files, QDirIterator::Subdirectories);
while (it.hasNext()){
qDebug() << it.next();
ui->resultList->addItem(it.next());
}
zipperProcess.setWorkingDirectory(QCoreApplication::applicationDirPath());
qDebug() << zipperProcess.workingDirectory();
qDebug()<<queryArguments;
zipperProcess.start("7za.exe", queryArguments);
}

How can I make my waitForBytesWritten call non blocking ?

I have this function :
bool TCPClient::sendPacket(Protocol::Packet &packet)
{
if(this->tcpSocket->state() == QAbstractSocket::ConnectedState)
{
std::cout << "writing ..." << std::endl;
std::cout << sizeof(BabelPacket) + packet.dataLength << std::endl;
this->tcpSocket->write((const char *)&packet, sizeof(Protocol::BabelPacket) + packet.dataLength);
return this->tcpSocket->waitForBytesWritten(-1);
}
else
{
std::cout << "socket close" << std::endl;
return false;
}
}
But when I called it, it blocks my GUI.
Have you got an idea how I can make this call non blocking, and still have the readyRead signal triggered ?
Thanks

QAbstractVideoSurface generating A Null Image

I'm reimplemented the present method from a QAbstractVideo Surface in order to capture frames from an IP camera.
This is my reimplemented methods (the required ones):
QList<QVideoFrame::PixelFormat> CameraFrameGrabber::supportedPixelFormats(QAbstractVideoBuffer::HandleType handleType) const
{
Q_UNUSED(handleType);
return QList<QVideoFrame::PixelFormat>()
<< QVideoFrame::Format_ARGB32
<< QVideoFrame::Format_ARGB32_Premultiplied
<< QVideoFrame::Format_RGB32
<< QVideoFrame::Format_RGB24
<< QVideoFrame::Format_RGB565
<< QVideoFrame::Format_RGB555
<< QVideoFrame::Format_ARGB8565_Premultiplied
<< QVideoFrame::Format_BGRA32
<< QVideoFrame::Format_BGRA32_Premultiplied
<< QVideoFrame::Format_BGR32
<< QVideoFrame::Format_BGR24
<< QVideoFrame::Format_BGR565
<< QVideoFrame::Format_BGR555
<< QVideoFrame::Format_BGRA5658_Premultiplied
<< QVideoFrame::Format_AYUV444
<< QVideoFrame::Format_AYUV444_Premultiplied
<< QVideoFrame::Format_YUV444
<< QVideoFrame::Format_YUV420P
<< QVideoFrame::Format_YV12
<< QVideoFrame::Format_UYVY
<< QVideoFrame::Format_YUYV
<< QVideoFrame::Format_NV12
<< QVideoFrame::Format_NV21
<< QVideoFrame::Format_IMC1
<< QVideoFrame::Format_IMC2
<< QVideoFrame::Format_IMC3
<< QVideoFrame::Format_IMC4
<< QVideoFrame::Format_Y8
<< QVideoFrame::Format_Y16
<< QVideoFrame::Format_Jpeg
<< QVideoFrame::Format_CameraRaw
<< QVideoFrame::Format_AdobeDng;
}
bool CameraFrameGrabber::present(const QVideoFrame &frame)
{
//qWarning() << "A frame";
if (frame.isValid()) {
//qWarning() << "Valid Frame";
QVideoFrame cloneFrame(frame);
cloneFrame.map(QAbstractVideoBuffer::ReadOnly);
const QImage image(cloneFrame.bits(),
cloneFrame.width(),
cloneFrame.height(),
QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat()));
qWarning() << "Is created image NULL?" << image.isNull();
if (!image.isNull())
emit nextFrameAsImage(image);
cloneFrame.unmap();
return true;
}
return false;
}
And this is is how I used it:
grabber = new CameraFrameGrabber(this);
connect(grabber,&CameraFrameGrabber::nextFrameAsImage,this,&QCmaraTest::on_newFrame);
QMediaPlayer *a = new QMediaPlayer(this);
QString url = "http://Admin:1234#10.255.255.67:8008";
a->setMedia(QUrl(url));
a->setVideoOutput(grabber);
a->play();
The problem is that the image that is created is null. As far as I can tell, this can only be because the frame is valid but does not contain data.
Any ideas what the problem could be?
Important Detail: If I set the stream to a QVideoWidget and simply show that, it works just fine.
So I found out what the problem was.
This:
QVideoFrame::imageFormatFromPixelFormat(cloneFrame .pixelFormat())
Was returning invalid format because the IP cam gave the format as a YUV format which QImage can't handle. The solution was to force the format and the only one I found that did not make the program crash was: QImage::Format_Grayscale8.
With that, it worked.

QNetwork Reply from QNetworkAccessManager

The following code is from an example shows how to use QNetworkAccessManager to download things.
void Downloader::replyFinished (QNetworkReply *reply)
{
if(reply->error())
{
qDebug() << "ERROR!";
qDebug() << reply->errorString();
}
else
{
qDebug() << reply->header(QNetworkRequest::ContentTypeHeader).toString();
qDebug() << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString();
qDebug() << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong();
qDebug() << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
qDebug() << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString();
QFile *file = new QFile("C:/Qt/Dummy/downloaded.txt");
if(file->open(QFile::Append))
{
file->write(reply->readAll());
file->flush();
file->close();
}
delete file;
}
reply->deleteLater();
}
My question is do we have to call reply->deleteLater(); here? If we don't call it, when we perform QNetworkAccessManager::get() call the second time, will the QNetworkReply* in the slot be the same QNetworkReply* ?
If you don't call deleteLater(), the QNetworkReply object will be leaked and its memory not freed. A second get() call will create a new QNetworkReply object.

QNetworkAccessManager request fail (CA signed certificate)

I've got a CA signed certificate which I use for a webservices. In Chrome and Firefox everything work fine.
Now I want to write a QT-client for the webservice. But all what I get is "connection closed" after 30 seconds. If I request "https://gmail.com" or "https://www.dfn.de/" I get a proper result.
Here is my code.
void Request::send() {
QUrl url("my url");
qDebug() << "URL: " << url;
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::UserAgentHeader, userAgent);
QObject::connect(manager, &QNetworkAccessManager::authenticationRequired, this, &Request::provideAuthenication);
QObject::connect(manager, &QNetworkAccessManager::finished, this , &Request::replyFinished);
QObject::connect(manager, &QNetworkAccessManager::sslErrors, this , &Request::sslErrors);
qDebug() << "fire request";
manager->get(request);
}
void Request::provideAuthenication(QNetworkReply *, QAuthenticator *ator) {
qDebug() << "provideAuthenication";
ator->setUser("***");
ator->setPassword("***");
}
void Request::replyFinished(QNetworkReply *reply) {
if (reply->error() != QNetworkReply::NoError)
qDebug() << "Network Error: " << reply->errorString();
QVariant statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute );
QVariant statusPhrase = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute );
qDebug() << "Result: " << statusCode.toInt() << " " << statusPhrase.toString();
qDebug() << "Data: " << reply->readAll();
}
void Request::sslErrors(QNetworkReply *, const QList<QSslError> &errors) {
foreach (const QSslError &error, errors) {
qDebug() << "SSL Error: " << error.errorString();
}
}
And that is the output. No sslError! No HTTP Error!
URL: QUrl( "my url" )
Network Error: "Connection closed"
Result: 0
Data: ""
So why hangs QT or the server? Did I miss something?!
It was a misconfiguration of openjdk7 (glassfish).
The hint of Aldaviva works on serverfault for me. https://serverfault.com/questions/389197/ssl-routinesssl23-writessl-handshake-failure
To bad that QT do not throw an ssl-error.

Resources