WebRTC playing webcam with Qt - qt

I use WebRTC for webcam playing (it's for testing webcam at my application before video calling). I do these next some WebRTC function:
////////////////////////
//initialization
{
webrtc::VoiceEngine* voe = VoiceEngine::Create();
webrtc::VoEBase* voeBase = VoEBase::GetInterface( voe );
voeBase->Init();
webrtc::VideoEngine* vie = VideoEngine::Create();
webrtc::ViEBase* vieBase = ViEBase::GetInterface( vie );
vieBase->Init();
webrtc::ViECapture* vieCapture = ViECapture::GetInterface( vie );
}
////////////////////////
// start webcam playing
void MainWindow::StartWebcamTest()
{
// creating window for playing webcam video
videoWidget = new Phonon::VideoWidget();
videoWidget->setFixedSize( 640, 480 );
videoWidget->setWindowTitle( "Test Webcam" );
char captDevName[1024], captGuidName[1024];
VoEEngineSingleton::Instance()->GetViECapture()->GetCaptureDevice( 0, captDevName, 1024, captGuidName, 1024 );
VoEEngineSingleton::Instance()->GetViECapture()->AllocateCaptureDevice( captGuidName, 1024, captureID );
testVideoChannel = VoEEngineSingleton::Instance()->GetViEBase()->CreateChannel( testVideoChannel );
if( testVideoChannel == -1 )
LOGERR << "Creating video channel error: " << VoEEngineSingleton::Instance()->GetViEBase()->LastError() << endl;
else LOGDEBUG << "Video channel created, ID = " << testVideoChannel << endl;
testAudioChannel = VoEEngineSingleton::Instance()->GetVoEBase()->CreateChannel();
if( testAudioChannel == -1 )
LOGERR << "Creating audio channel error: " << VoEEngineSingleton::Instance()->GetVoEBase()->LastError() << endl;
else LOGDEBUG << "Audio channel created, ID = " << testAudioChannel << endl;
if( VoEEngineSingleton::Instance()->GetViEBase()->ConnectAudioChannel( testVideoChannel, testAudioChannel ) != 0 )
LOGERR << "ConnectAudioChannel() error: " << VoEEngineSingleton::Instance()->GetViEBase()->LastError() << endl;
else LOGINFO << "Audio channel connected successful " << endl;
if( VoEEngineSingleton::Instance()->GetViECapture()->ConnectCaptureDevice( captureID, testVideoChannel ) != 0 )
LOGERR << "ConnectCaptureDevice() error: " << VoEEngineSingleton::Instance()->GetViEBase()->LastError() << endl;
else LOGINFO << "Capture device connected successful " << endl;
if( VoEEngineSingleton::Instance()->GetViERender()->StartRender( testVideoChannel ) != 0 )
LOGERR << "StartRender() error: " << VoEEngineSingleton::Instance()->GetViEBase()->LastError() << endl;
else LOGINFO "StartRender() successed " << endl;
if( VoEEngineSingleton::Instance()->GetViECapture()->StartCapture( captureID ) != 0 )
LOGERR << "StartCapture() error: " << VoEEngineSingleton::Instance()->GetViEBase()->LastError() << endl;
else LOGINFO << "StartCapture() successed " << endl;
videoWidget->show();
}
When I click button for playing video - webcam starts playing but videoWidget window is black empty.
What am I doing not true? And maybe I must use other Qt widget for it?

You have to implement video renderer in Qt. subclass webrtc::ExternalRenderer and draw the frame

#include <QApplication>
#include <QUrl>
#include <QWebEngineView>
class WebEnginePage: public QWebEnginePage{
Q_OBJECT
public:
WebEnginePage(QObject *parent = Q_NULLPTR):QWebEnginePage(parent){
connect(this, &WebEnginePage::featurePermissionRequested, this, &WebEnginePage::onFeaturePermissionRequested);
}
private Q_SLOTS:
void onFeaturePermissionRequested(const QUrl &securityOrigin, QWebEnginePage::Feature feature){
if(feature == QWebEnginePage::MediaAudioCapture
|| feature == QWebEnginePage::MediaVideoCapture
|| feature == QWebEnginePage::MediaAudioVideoCapture)
setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionGrantedByUser);
else
setFeaturePermission(securityOrigin, feature, QWebEnginePage::PermissionDeniedByUser);
}
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QWebEngineView view;
view.setPage(new WebEnginePage);
QUrl url = "https://appr.tc/r/386424467";
// view.setUrl(commandLineUrlArgument());
view.setUrl(url);
view.resize(1024, 750);
view.show();
return app.exec();
}
#include "main.moc"

Related

Can I query the list of variables and types

Can I use twincat-ads to query a Beckhoff PLC for the variables (and their types) that are exposed on ADS.
Yes you can.
This example comes directly from the Beckhoff ads documentation which you should study a bit in order to understand the basics of the ads protocol.
/// <summary>
/// Defines the entry point of the application.
/// </summary>
/// <param name="args">The arguments.</param>
static void Main(string[] args)
{
    Console.WriteLine("");
    Console.WriteLine("Press [Enter] for start:");
    Console.ReadLine();
    // Parse the command-line arguments
    AmsAddress address = ArgParser.Parse(args);
    using (TcAdsClient client = new TcAdsClient())
    {
    // Connect the AdsClient to the device target.
    client.Connect(address);
    // Load symbolic information
    ISymbolLoader loader = SymbolLoaderFactory.Create(client, SymbolLoaderSettings.Default);
    ReadOnlySymbolCollection allSymbols = loader.Symbols;
    ISymbol bVar1 = allSymbols["GVL.bVar1"];
    ISymbol bVar2 = allSymbols["GVL.iCount"];
    ISymbol projectName = allSymbols["TwinCAT_SystemInfoVarList._AppInfo.ProjectName"];
    SymbolCollection symbols = new SymbolCollection() {bVar1, bVar2, projectName};
    // Sum Command Read
    SumSymbolRead readCommand = new SumSymbolRead(client,symbols);
    object[] values = readCommand.Read();
    for (int i = 0; i < symbols.Count; i++)
    {
        Console.WriteLine("Symbol: {0} (Value: {1}, Type: {2})",symbols[i].InstancePath,values[i].ToString(),values[i].GetType().Name);
    }
    // Sum Command Write
    SumSymbolWrite writeCommand = new SumSymbolWrite(client,symbols);
    object[] writeValues = new object[] {true, (short) 42, "MyNewProjectName"};
    writeCommand.Write(writeValues);
    }
    Console.WriteLine("");
    Console.WriteLine("Press [Enter] for leave:");
    Console.ReadLine();
}
In C++ you need to use the AdsSyncReadReq function:
#include <iostream.h>
#include <windows.h>
#include <conio.h>
#include <assert.h>
// ADS headers for TwinCAT 3
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsDef.h"
#include "C:\TwinCAT\AdsApi\TcAdsDll\Include\TcAdsAPI.h"
void main()
{
long nErr, nPort;
char *pchSymbols = NULL;
UINT uiIndex;
AmsAddr Addr;
PAmsAddr pAddr = &Addr;
AdsSymbolUploadInfo tAdsSymbolUploadInfo;
PAdsSymbolEntry pAdsSymbolEntry;
// Open communication port on the ADS router
nPort = AdsPortOpen();
nErr = AdsGetLocalAddress(pAddr);
if (nErr) cerr << "Error: AdsGetLocalAddress: " << nErr << '\n';
// Select Port: TwinCAT 3 PLC1 = 851
pAddr->port = 851;
// Read the length of the variable declaration
nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_UPLOADINFO, 0x0, sizeof(tAdsSymbolUploadInfo), &tAdsSymbolUploadInfo);
if (nErr) cerr << "Error: AdsSyncReadReq: " << nErr << '\n';
pchSymbols = new char[tAdsSymbolUploadInfo.nSymSize];
assert(pchSymbols);
// Read information about the PLC variables
nErr = AdsSyncReadReq(pAddr, ADSIGRP_SYM_UPLOAD, 0, tAdsSymbolUploadInfo.nSymSize, pchSymbols);
if (nErr) cerr << "Error: AdsSyncReadReq: " << nErr << '\n';
// Output information about the PLC variables
pAdsSymbolEntry = (PAdsSymbolEntry)pchSymbols;
for (uiIndex = 0; uiIndex < tAdsSymbolUploadInfo.nSymbols; uiIndex++)
{
cout << PADSSYMBOLNAME(pAdsSymbolEntry) << "\t\t"
<< pAdsSymbolEntry->iGroup << '\t'
<< pAdsSymbolEntry->iOffs << '\t'
<< pAdsSymbolEntry->size << '\t'
<< PADSSYMBOLTYPE(pAdsSymbolEntry) << '\t'
<< PADSSYMBOLCOMMENT(pAdsSymbolEntry) << '\n';
pAdsSymbolEntry = PADSNEXTSYMBOLENTRY(pAdsSymbolEntry); cout.flush();
}
getch();
// Close communication port
nErr = AdsPortClose();
if (nErr) cerr << "Fehler: AdsPortClose: " << nErr << '\n';
// Release memory
if (pchSymbols) delete(pchSymbols);
}
For more info:
https://infosys.beckhoff.com/english.php?content=../content/1033/tc3_ads_intro/9007199370899851.html&id=5869483416056481636

Can't delete a pointer in C++

I got this code from a book. When I ran on Visual Studio, it said to switch strcpy() to strcpy_s(), and after I did that, it seems the program terminated at the delete pointer. I tried to run on Dev-C++, and it works fine. Anyone knows why? Thank you.
#include "pch.h"
#include <iostream>
#include <cstring>
int main()
{
cout << "Enter a kind of animal: ";
cin >> animal; // ok if input < 20 chars
ps = animal; // set ps to point to string
cout << ps << "!\n"; // ok, same as using animal
cout << "Before using strcpy():\n";
cout << animal << " at " << (int *)animal << endl;
cout << ps << " at " << (int *)ps << endl;
ps = new char[strlen(animal) + 1]; // get new storage
strcpy_s(ps, sizeof(animal), animal); // copy string to new storage
cout << "After using strcpy():\n";
cout << animal << " at " << (int *)animal << endl;
cout << ps << " at " << (int *)ps << endl;
delete[] ps;
return 0;
}

Qt: RFCOMM BluetoothSocket Connection Problems after switching Pages in QML

I'm developing an cross plattform Application in Qt Creator, which has the exercise to control a device via Classic Bluetooth. I have a communication protocol. FIRST: I can connect to device and write Data to it with BluetoothSocket. If I put the startMotor() function into the socketConnected SLOT after beepBuzzor() command then it works fine and I get state() connected.
My problem is if I switch the page in my Application on Android and click on the "start motor" button, I get the state() unconnected, but I am still connected to the device because the LED on the device shows connected. My app does not crash. I think the problem is in the line with socket->connectToService(...), but I'm unsure what to change. The beepBuzzor command works fine, startMotor command too. But if I call the function after successfully connectToService() it does not work because the state is unconnected.
BluetoothManager::BluetoothManager(QObject *parent) : QObject(parent)
{
socket = new QBluetoothSocket(QBluetoothServiceInfo::RfcommProtocol);
}
void BluetoothManager::startDiscovery()
{
// Check if Bluetooth is available on this device
if (localDevice.isValid()) {
qDebug() << "Bluetooth is available on this device";
//Turn BT on
localDevice.powerOn();
// Make it visible to others
localDevice.setHostMode(QBluetoothLocalDevice::HostDiscoverable);
//Read local device name & address
qDebug() << "Local Device:" << localDevice.name() << "(" << "Address:" << localDevice.address() << ")";
// Create a discovery agent and connect to its signals
discoveryAgent = new QBluetoothDeviceDiscoveryAgent(this);
connect(discoveryAgent, SIGNAL(finished()), this, SLOT(deviceDiscoverFinished()));
// Start a discovery
// Trick: da es kein DiscoveryTimer für Classic gibt, suchen wir nach LE devices, da BT121 BLE unterstützt.
// Die Verbindung erfolgt jedoch über RFCOMM sobald man sich mit dem Gerät verbindet.
discoveryAgent->setLowEnergyDiscoveryTimeout(5000);
discoveryAgent->start(QBluetoothDeviceDiscoveryAgent::LowEnergyMethod);
qDebug() << "Device discover started";
}
else
{
qDebug() << "Bluetooth is not available on this device";
}
}
//SLOT for the finish of device Discovery
void BluetoothManager::deviceDiscoverFinished()
{
qDebug() << "Device discover finished";
listOfDevices = discoveryAgent->discoveredDevices();
qDebug() << "Found new devices:";
for (int i = 0; i < listOfDevices.size(); i++)
{
//Q_OS_IOS / MAC do not need here cuz the run is on android device, delete later
//We do not find galileo device on MacBook
#if defined (Q_OS_IOS) || defined (Q_OS_MAC)
// On MacOS and iOS we get no access to device address,
// only unique UUIDs generated by Core Bluetooth.
qDebug() << "getting address from deviceUuid()" << listOfDevices.at(i).name().trimmed()
<< " ( " << listOfDevices.at(i).deviceUuid().toString().trimmed() << " ) ";
setDevice(listOfDevices.at(i).name().trimmed() + " (" + listOfDevices.at(i).deviceUuid().toString().trimmed() + ")");
#else
qDebug() << listOfDevices.at(i).name().trimmed()
<< " ("
<< listOfDevices.at(i).address().toString().trimmed()
<< ")";
setDevice(listOfDevices.at(i).name().trimmed() + " (" + listOfDevices.at(i).address().toString().trimmed() + ")");
#endif
}
}
/**
* In GUI (QML) user select a device with index i.
* Create a new socket, using Rfcomm protocol to communicate
*/
void BluetoothManager::deviceSelected(int i)
{
selectedDevice = listOfDevices.at(i);
#if defined (Q_OS_IOS) || defined (Q_OS_MAC)
qDebug() << "User select a device: " << selectedDevice.name() << " ("
<< selectedDevice.deviceUuid().toString().trimmed() << ")";
#else
qDebug() << "User select a device: " << selectedDevice.name() << " ("
<< selectedDevice.address().toString().trimmed() << ")";
#endif
if (localDevice.pairingStatus(selectedDevice.address())== QBluetoothLocalDevice::Paired)
{
qDebug() << "Pairing is allready done";
}
else
{
qDebug() << "Not paired. Please do pairing first for communication with device!";
}
selecDevAdress = selectedDevice.address();
connectToSvc();
//Connect SIGNALS with SLOTS
connect(socket, SIGNAL(error(QBluetoothSocket::SocketError)), this, SLOT(socketError(QBluetoothSocket::SocketError)));
connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
connect(socket, SIGNAL(readyRead()), this, SLOT(socketRead()));
connect(socket, SIGNAL(stateChanged(QBluetoothSocket::SocketState)), this, SLOT(socketStateChanged()));
}
void BluetoothManager::connectToSvc()
{
qDebug() << "Create socket";
//socket->connectToService(selecDevAdress, QBluetoothUuid(QString("00001101-0000-1000-8000-00805F9B34FB")), QIODevice::ReadWrite);
//static const QString serviceUuid(QStringLiteral("00001101-0000-1000-8000-00805F9B34FB"));
socket->connectToService(selectedDevice.address(), QBluetoothUuid(QString("00001101-0000-1000-8000-00805F9B34FB")), QIODevice::ReadWrite);
//Also works with this line instead of the two above (with declaration of serviceUuid)
//socket->connectToService(QBluetoothAddress(selectedDevice.address()),QBluetoothUuid(QBluetoothUuid::SerialPort));
socket->open(QIODevice::ReadWrite);
socket->openMode();
}
//SLOT wenn Socket verbunden ist
void BluetoothManager::socketConnected()
{
//qDebug() << ("Connected to: "+socket->peerAddress().toString() +":"+socket->peerPort());
qDebug() << ("Connected to: "+socket->peerAddress().toString());
qDebug() << "Socket connected";
qDebug() << "Local: "
<< socket->localName()
<< socket->localAddress().toString()
<< socket->localPort();
qDebug() << "Peer: "
<< socket->peerName()
<< socket->peerAddress().toString()
<< socket->peerPort();
//Do "beep" sound commando after succesfull connection to Galileo device
beepBuzzor();
}
/**
* Socket disconnected.
* Delete socket, free the memory.
*/
//SLOT für Verbindungsabbruch von Socket
void BluetoothManager::socketDisconnected()
{
qDebug() << "Socket disconnected";
socket->deleteLater();
}
void BluetoothManager::socketError(QBluetoothSocket::SocketError error)
{
qDebug() << "Socket error: " << error;
}
void BluetoothManager::socketStateChanged()
{
int socketState = socket->state();
if(socketState == QAbstractSocket::UnconnectedState)
{
qDebug() << "unconnected";
}
else if(socketState == QAbstractSocket::HostLookupState)
{
qDebug() << "host lookup";
}
else if(socketState == QAbstractSocket::ConnectingState )
{
qDebug() << "connecting";
}
else if(socketState == QAbstractSocket::ConnectedState)
{
qDebug() << "connected";
}
else if(socketState == QAbstractSocket::BoundState)
{
qDebug() << "bound";
}
else if(socketState == QAbstractSocket::ClosingState)
{
qDebug() << "closing";
}
else if(socketState == QAbstractSocket::ListeningState)
{
qDebug() << "listening";
}
}
// SLOT when data ready on bluetooth socket
void BluetoothManager::socketRead()
{
qDebug() << "socketRead()";
QByteArray recievedData = socket->readAll();
emit dataRecieved(recievedData);
}
/**
* Get a string with device info
*/
const QString &BluetoothManager::device() const
{
return deviceInfo;
}
void BluetoothManager::setDevice(const QString &newDevice)
{
if (newDevice != deviceInfo) {
deviceInfo = newDevice;
emit deviceChanged();
}
}
void BluetoothManager::beepBuzzor()
{
QByteArray beep;
beep.append(QByteArray::fromRawData("\x04\x00\x09\xD0\x07\x32\x00", 7));
command(beep);
}
void BluetoothManager::startMotor()
{
qDebug() << "startMotor slot";
if(socket->state() == QBluetoothSocket::UnconnectedState){
qDebug() << "Socket Unconnected";
}
else{
qDebug() << "Socket Unonnected";
}
socketStateChanged();
//command(start);
}
void BluetoothManager::command(QByteArray &cmdBuf)
{
socket->write(cmdBuf);
}

OpenCL Vector add program

I'm absolutely new to OpenCL programming. I have a working installation of OpenCL library and drivers. But the program I'm trying to run is not producing expected output (Output is all zeros). It is just a simple vector_add program.
Thanks in advance for suggestions.
int main(int argc, char** argv)
{
cout << "Hello OpenCL" << endl;
vector<Platform> all_platforms;
int err = Platform::get(&all_platforms);
cout << "Getting Platform ... Error code " << err << endl;
if (all_platforms.size()==0)
(cout << "No platforms" << endl, exit(0));
cout << "Platform info : " << all_platforms[0].getInfo<CL_PLATFORM_NAME>() << endl;
Platform default_platform = all_platforms[0];
cout << "Defaulting to it ..." << endl;
vector<Device> all_devices;
err = default_platform.getDevices(CL_DEVICE_TYPE_GPU, &all_devices);
cout << "Getting devices ... Error code : " << err << endl;
if (all_devices.size()==0)
(cout << "No devices" << endl, exit(0));
Device default_device = all_devices[0];
cout << all_devices.size() << " devices & " << "Device info : " << all_devices[0].getInfo<CL_DEVICE_NAME>() << endl;
cout << "Defaulting to it ..." << endl;
Context context(default_device);
Program::Sources sources;
std::string kernel_code=
" void kernel simple_add(global const int* A, global const int* B, global int* C){"
" unsigned int i = get_global_id(0); "
" C[i]=A[i]+B[i]; "
" } ";
sources.push_back(make_pair(kernel_code.c_str(), kernel_code.length()+1));
Program program(context, sources);
if (program.build(all_devices)==CL_SUCCESS)
cout << "Built Successfully" << endl;
Buffer buffer_A(context,CL_MEM_READ_WRITE,sizeof(int)*10);
Buffer buffer_B(context,CL_MEM_READ_WRITE,sizeof(int)*10);
Buffer buffer_C(context,CL_MEM_READ_WRITE,sizeof(int)*10);
int A[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int B[] = {0, 1, 2, 0, 1, 2, 0, 1, 2, 0};
CommandQueue queue(context,default_device);
queue.enqueueWriteBuffer(buffer_A,CL_TRUE,0,sizeof(int)*10,A); // load data from host to device
queue.enqueueWriteBuffer(buffer_B,CL_TRUE,0,sizeof(int)*10,B);
Kernel kernel(program, "vector_add");
kernel.setArg(0, buffer_A);
kernel.setArg(1, buffer_B);
kernel.setArg(2, buffer_C);
queue.enqueueNDRangeKernel(kernel,cl::NullRange,cl::NDRange(10),cl::NullRange);
queue.finish();
int *C = new int[10];
queue.enqueueReadBuffer(buffer_C, CL_TRUE, 0, 10 * sizeof(int), C);
for (int i=0;i<10;i++)
std::cout << A[i] << " + " << B[i] << " = " << C[i] << std::endl;
return 0;
}
As pointed out in the comments, you should always check the error codes when using OpenCL API functions. This can be achieved by enabling exception handling in the C++ wrapper:
#define __CL_ENABLE_EXCEPTIONS // with cl.hpp
//#define CL_HPP_ENABLE_EXCEPTIONS // with cl2.hpp
#include <CL/cl.hpp>
int main(int argc, char *argv[])
{
try
{
// OpenCL code here
}
catch (cl::Error& err)
{
cout << err.what() << " failed with error code " << err.err() << endl;
}
}
If you do this, you will receive useful information about a couple of issues with your code.
The clCreateKernel function returns CL_INVALID_NAME. In your kernel, you define the kernel function with the name simple_add, but then you try and create a kernel object using the name vector_add.
If you have an OpenCL platform with multiple devices, you may also receive an error when building your kernel program. This is because you are creating an OpenCL context with a single device, but then trying to build the program for a list of devices:
Context context(default_device);
// ...
if (program.build(all_devices)==CL_SUCCESS)
cout << "Built Successfully" << endl;
The simplest fix is just to remove the argument from the build function, since by default it will build the program for all devices in the context (which is almost always what you actually want):
if (program.build()==CL_SUCCESS)
cout << "Built Successfully" << endl;

qt: unable to read image from url

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)

Resources