How to read my application screen pixel data with Qt - c++

I am trying to read my application screen pixel data in my Qt Qml application.
The first approach was grabToImage(), which is fast in my PC. But the same is taking seconds to grab image in my embedded device.
So I tried to read /dev/fb0, using QFile::readAll,
QFile file("/dev/fb0");
QFile dataFile("/home/icu/WorkSpace/Samples/FBRead/Exe/data.bin");
if(!file.open(QIODevice::ReadOnly))
{
qDebug() << Q_FUNC_INFO << file.errorString();
}
if(!dataFile.open(QIODevice::WriteOnly))
{
qDebug() << Q_FUNC_INFO << dataFile.errorString();
}
QTextStream in(&file);
QString data;
qDebug() << Q_FUNC_INFO << "start read";
// while(!in.atEnd())
// {
qDebug() << Q_FUNC_INFO << "read";
data = in.readAll();
// qDebug() << Q_FUNC_INFO << data;
// }
QByteArray dataBytes;
dataBytes.append(data);
dataFile.write(dataBytes);
file.close();
dataFile.close();
I tried to open the file with some tool which shows image reading from raw file. But it did not show any data. When I open the file data is like 01 01 01 00 01 01 01 00 ...
Is there any alternate way to read my screen pixel data fast? Thanks

I'm not sure if using a QTextStream and converting data to QString and then back to QByteArray is the best way to do it. As explained in Qt's documentation constructing a QString from QByteArray forces a conversion to UTF-8 and also stops copying at the first null character, so you are modifying your pixel data and not getting it completely. Try copying data directly between files instead:
bool grabScreenToFile(const QString& outPath) {
QFile inFile("/dev/fb0");
QFile outFile(outPath);
// ...
outFile.write(inFile.readAll());
return true;
}
To check if this is copying the actual content of the file and you have no problem with it (truncation, conversions, ...), compare with the file obtained using cat /dev/fb0 > grab.raw (note that it is not a JPEG or PNG image but a raw buffer).
/dev/fb0
This link contains a long explanation about grabbing the framebuffer from the /dev/fb0 device. Basically, it points out that you must pay attention to the depth of the buffer, since pixels may be packed in different ways.
On the other hand, have you tried any other of the grabbing methods provided by Qt, such as QScreen::grabWindow? Maybe its performance is better that the QML's QQuickItem::grabToImage (which is the one I guess you are using). Indeed, the documentation states:
This function will render the item to an offscreen surface and copy that surface from the GPU's memory into the CPU's memory, which can be quite costly.
Following code is a modification of the screenshot example.
auto screen = QGuiApplication::primaryScreen();
if (const QWindow *window = windowHandle()) {
screen = window->screen();
}
if (screen) {
const auto pixmap = screen->grabWindow(yourWidget->winId());
// ...
}

Related

QT failed to load Image from Buffer

My work Environment : Qt 5.8 MSVC2015 64bit, QT GraphicsView, Windows 7 64 bit
I am loading image from buffer (a demon process is going send a image buffer), but it failed to create image with buffer.
QFile file("D:\\2.png");
if (!file.open(QFile::ReadOnly))
qDebug() << "Error failed to Open file";
QByteArray array = file.readAll();
array = array.toBase64();
QImage tempimage((uchar *)array.data(), 250, 250, QImage::Format_RGBX8888);
if (!tempimage.isNull()) {
///I always get this error
qDebug() << "Error!!! failed to create a image!";
}
Any idea what I am missing here ?
Why are you converting to base64?
Wait, where are you converting from PNG to an image plane?
Try bool QImage::loadFromData(const QByteArray &data, const char *format = Q_NULLPTR) to load the PNG instead of the CTor with the raw data.
If your wire format isn't PNG (and is in fact base64 encoded raw pixel data) then you want to convert FROM base64.
Thanks for all suggestion & help.
I fix my mistakes removed base64 conversion & loaded buffer using loadFromData with QByteArray reinterpret_cast:
Here is a final solution :
QFile file("D:\\2.png");
if (!file.open(QFile::ReadOnly))
qDebug() << "Error failed to Open file";
QByteArray array = file.readAll();
QImage tempimage;
//// This very important to cast in below format, QByteArray don't work as arguments.
tempimage.loadFromData(reinterpret_cast<const uchar *>(array.data()),array.size());
if (tempimage.isNull()) {
qDebug() << "Error!!! failed to create a image!";
}

Receiving jpeg through socket and yet unable to display on Qt

I trying to send and receive jpeg images (image size around: 1kb) from my client socket. I have successfully send and receive the image data by checking the size of the data. However when I tried to past the image data to QByteArray and display on QImage, nothing was shown. The code below is a snippet of the receiving and displaying jpeg image.
Server.cpp
memcpy(&Rbuffer, ptr, msgCtl.iMsgLen - 8);
ptr += msgCtl.iMsgLen - 8;
cout << "Size of the image data recieve from the send buffer is " << sizeof(Rbuffer) << endl;
QByteArray ba = QByteArray::fromRawData(Rbuffer, sizeof(Rbuffer));
QBuffer qbuff(&ba);
qbuff.open(QIODevice::ReadOnly);
//QImageReader qimg ("C:\\test.jpg");
QImageReader qimg (&qbuff,"JPG");
qimg.setDecideFormatFromContent(true);
qimg.setDevice(&qbuff);
QImage img = qimg.read();
if (!img.isNull()){
cout << "no problem" << endl;
}
imageView->setPixmap(QPixmap::fromImage(img));
Hope someone could guide me on this. Thank you
On Windows, you have to copy the imageformats directory to your build directory.
eg.
C:\Qt\5.7\msvc2015_64\plugins\imageformats to my_build_dir\imageformats
Try this code:
QPixmap scaledPixmap = QPixmap::fromImage(image).scaled(
QSize(imageWidth, imageHeight),
Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
imageView->setScaledContents(false);
imageView->setPixmap(scaledPixmap);

Get the checksum of an open QIODevice

i need the checksum of a file and found this, which works perfectly fine. Now i want to change this function to take a pointer to a QIODevice that has been opened before with the following lines:
if (!file.open(QFile::ReadOnly | QFile::Text))
{
...
}
This is passed to read (reader.read(&file);) as device:
bool XmlReader::read(QIODevice* device)
{
QByteArray b = fileChecksum(device);
...
}
This is my implementation of fileChecksum. It returns a checksum, but i am caught in a loop forever and i am getting an xml parse error. What am i doing wrong here?
QByteArray XmlReader::fileChecksum(QIODevice* device)
{
if (device->isOpen())
{
QCryptographicHash hash(QCryptographicHash::Sha256);
if (hash.addData(device)) {
return hash.result();
}
}
return QByteArray();
}
EDIT
right after QByteArray b = fileChecksum(device); i do:
qDebug() << "Checksum: " << b.toHex();
whick keeps printing and printing and printing...
The parse error is: premature end of document which is rubbish.
Hope this helps.
Since the lines of code that eventually caused the error are not in view I can only speculate about what happened.
The function fileChecksum called hash.addData(device) which read the QIODevice until the end and kept the cursor position there.
Most likely you tried to read from the QIODevice afterwards which would explain the premature end of documen message.
As a fast workaround you can just try to reset the position afterwards with
auto pos = device->pos();
QByteArray b = fileChecksum(device);
device->seek(pos);
But you should only read the data once if you can (to support non random-access QIODevices too). For example you can store the result in a QBuffer and use that as a QIODevice. Like this:
bool XmlReader::read(QIODevice* device)
{
QByteArray contents = device->readAll();
QBuffer buffer(&contents);
device = &buffer;//you can also just use &buffer from here on out instead of overwriting the pointer
QByteArray b = fileChecksum(device);
device->reset();
/* ... further reads from device here */
}

Convert byte array to picture

Hello I try to convert a byte array to an Image but each time i get a null image, somebody could help me please ?
QImage image("p.jpg");
qDebug()<<image;
QImage image2;
QByteArray paquet2;
QDataStream out2(&paquet2, QIODevice::WriteOnly);
out2 << image;
qDebug()<<image2.fromData(paquet2,"jpg");
qDebug 1 result: QImage(Qsize(500,500))
qDebug 2 result: QImage(Qsize(0,0))
fromData() is a static method.
Try image2.loadFromData(paquet2) or QImage::fromData(paquet2) instead.
I noticed something very strange, this code works as expected:
QImage img("...");
QByteArray data;
QBuffer buff(&data);
QDataStream out(&buff);
out << img;
qDebug() << QImage::fromData(data);
But it gives a warning about the IODevice not being open.
If I manually buff.open(), fromData() produces a null image again.
Without explicitly opening, the openMode() is automatically set to Unbuffered | WriteOnly and it works, if I open() it explicitly to Unbuffered | WriteOnly it doesn't work. Go figure...

QDataStream unable to serialize data

I am trying to follow the tutorial here and serialize Qt objects. Here is my code:
QFile file("/Users/kaustav/Desktop/boo.dat");
if (!file.open(QIODevice::WriteOnly)) {
qDebug() << "Cannot open file for writing: "
<< qPrintable(file.errorString()) << endl; //no error message gets printed
return 0;
}
QDataStream out(&file); // we will serialize the data into the file
out.setVersion(QDataStream::Qt_5_3); //adding this makes no difference
out << QString("the answer is"); // serialize a string
out << (qint32)42;
When I run this program, the file gets created in my desktop all right, but its size is 0 kB, it is blank. Naturally, when I then try this:
QFile file("/Users/kaustav/Desktop/boo.dat");
file.open(QIODevice::ReadOnly);
QDataStream in(&file); // read the data serialized from the file
in.setVersion(QDataStream::Qt_5_3);
QString str;
qint32 w;
in >> str >> w;
I get a blank string in str. What am I doing wrong? If of any help, I am using Qt Creator 3.1.1 based on Qt 5.2.1.
Check if there are any errors returned when calling open and ensure you close the file with file.close() when you're finished with it.
As you're using Qt 5, you should really use QSaveFile instead, when saving the data.