Results 1 to 19 of 19

Thread: Receiving raw image data through TCP for display using Qt

  1. #1
    Join Date
    Jun 2014
    Posts
    16
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Receiving raw image data through TCP for display using Qt

    Receiving raw image data through TCP for display using Qt
    I am working on a GUI to display image from sensor. The GUI acts as a client while the sensor acts as a server. Once I send a command to the sensor, the sensor will send streaming raw image data (binary data) continuously to the GUI through TCP. The data will be an exact copy of the image memory with size width (1240) x height (1028) coded in U8 (unsigned 8 bit). The size of one incoming data is (1240 x 1028 x 1 byte) + 20 byte (meta header) = 1.3MByte.

    My biggest obstacles are:
    1.) how can I receive and store the streaming data from sensor continuously for display purpose?
    2.) how can I display the raw data?

    I have tried the code as below, but QImage return with NULL. No image is saved. Please advise.

    "client.h"
    Qt Code:
    1. #ifndef CLIENT_H
    2. #define CLIENT_H
    3.  
    4. #include <QObject>
    5. #include <QWidget>
    6. #include <QTcpSocket>
    7.  
    8. class Client : public QWidget
    9. {
    10. Q_OBJECT
    11. public:
    12. explicit Client(QWidget *parent = 0);
    13. int capture (int mode, int NBRLine);
    14.  
    15. signals:
    16.  
    17. public slots:
    18.  
    19. private:
    20. QTcpSocket* socket;
    21.  
    22. };
    23.  
    24. #endif // CLIENT_H
    To copy to clipboard, switch view to plain text mode 

    "client.cpp"

    Qt Code:
    1. #include "client.h"
    2. #include <QHostAddress>
    3. #include "mainwindow.h"
    4. #include <QtGui>
    5. #include <QAbstractSocket>
    6. #include <QImage>
    7.  
    8. Client::Client(QWidget *parent) :
    9. QWidget(parent)
    10. {
    11. socket = new QTcpSocket(this);
    12. }
    13.  
    14. int Client::capture(int mode, int NBRLine)
    15. {
    16. if (socket->state() != QTcpSocket::ConnectedState)
    17. {
    18. socket->connectToHost("192.168.0.65", 1096);
    19. }
    20.  
    21. /* send command to retrieve raw image data from sensor */
    22. if(socket->waitForConnected(5000))
    23. {
    24. QByteArray block;
    25. QDataStream out(&block, QIODevice::WriteOnly);
    26. out.setVersion(QDataStream::Qt_4_0);
    27. out.setByteOrder(QDataStream::LittleEndian);
    28. out << qint32(0) << qint32(0) << qint32(0) << qint32(1);
    29. out << qint32(9) << qint32(1) << qint32(0) << mode << qint32(10) << qint32(2) << qint32(0) << NBRLine ;
    30. socket->write(block);
    31. socket->flush();
    32. }
    33. else
    34. {
    35. return false;
    36. }
    37. /**********************************************************/
    38.  
    39. /* to get data size of each scan through width and height in the meta header */
    40. QDataStream input(socket);
    41. input.setVersion(QDataStream::Qt_4_0);
    42. input.setByteOrder(QDataStream::LittleEndian);
    43. qint32 buffer, cmdID, counter, metaSize, width, height;
    44. do
    45. {
    46. if (socket->waitForReadyRead(1000))
    47. {
    48. input >> cmdID;
    49. if (cmdID == 101)
    50. {
    51. input >> buffer >> buffer >> buffer >> buffer;
    52. }
    53. }
    54. else
    55. {
    56. socket->disconnectFromHost();
    57. break;
    58.  
    59. }
    60. } while (cmdID != 1);
    61.  
    62. input >> counter >> metaSize;
    63. if (metaSize != 8) return false;
    64.  
    65. input >> width >> height;
    66. quint32 datasize = width * height;
    67.  
    68. /**********************************************************/
    69.  
    70. /* Receiving streaming data which I have problem here !!!! */
    71. while (socket->bytesAvailable() < datasize + 80) {
    72. if (!socket->waitForReadyRead(1000)) {
    73. socket->disconnectFromHost();
    74. break;
    75. }
    76. }
    77.  
    78. QImage img;
    79. input >> img;
    80.  
    81. if (img.isNull())
    82. {
    83. return 0;
    84. }
    85. img.save("E:/temp1");
    86. return 1;
    87. }
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Usually you would want to stay single threaded as long as possible, meaning that you don't use blocking I/O on the socket but connect to its signals.

    Also QDataStream is intended for communication between two Qt programs, it might add information to the data that is written into it, e.g. type information. So make sure that the other side is using the same QDataStream setup.
    If the sensor is not using Qt at all, don't use QDataStream on the receiver send either.

    If the data you receive is raw image data, then one way to create the image is to write into its buffer.
    I.e. you create the QImage with the correct dimensions and depth and when image data is received you copy it into the image's data array. See QImage::bits().

    Cheers,
    _

  3. #3
    Join Date
    Jun 2014
    Posts
    16
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    First thanks for your quick response.
    Any disadvantage for using the method of blocking I/O on the socket?
    One reason I am not using the connect signal method is that I have no idea on how to pass the expected value of Cmd_ID to the function e.g. “connect(socket, SIGNAL(readyRead()),this, SLOT(tcpReady()) )”.
    The response data I will receive is like below:
    <Cmd_ID (4 byte)> <Counter (4 byte)> <Size_of_Meta_Header (4 byte)> <Width (4 byte)>)> <Height (4 byte)> <Data>
    First I need to check the value of Cmd_ID whether it is matched with the expected value.Then I need to calculate the size of data by multiplying Width and Height. This is the reason I use QDataStream.
    The sensor is not using Qt, what should I use instead?
    I am a newbie in Qt. Can you show me an example to write the raw image data into its buffer and copy it into the image's data array? Thanks

  4. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Quote Originally Posted by benz6699 View Post
    Any disadvantage for using the method of blocking I/O on the socket?
    The disadvantage is that you need a second thread if you don't want to block the UI.
    A multithreaded program is usually much harder to get right.

    Quote Originally Posted by benz6699 View Post
    One reason I am not using the connect signal method is that I have no idea on how to pass the expected value of Cmd_ID to the function e.g. “connect(socket, SIGNAL(readyRead()),this, SLOT(tcpReady()) )”.
    The command ID is part of the data, no?
    So it can be read from the socket independent of whether you wait for data blockingly or asynchronously.

    Quote Originally Posted by benz6699 View Post
    First I need to check the value of Cmd_ID whether it is matched with the expected value.Then I need to calculate the size of data by multiplying Width and Height. This is the reason I use QDataStream.
    The sensor is not using Qt, what should I use instead?
    Well, you can use the data stream to interpret multibyte integers for you, but don't expect it to be of any value for any other type of data.

    Quote Originally Posted by benz6699 View Post
    I am a newbie in Qt. Can you show me an example to write the raw image data into its buffer and copy it into the image's data array? Thanks
    You would create the image when you know about its size
    Qt Code:
    1. m_image = QImage(width, height, QImage::Format_Indexed8);
    To copy to clipboard, switch view to plain text mode 
    you need to have either a pointer to the current byte or an index that tells you which byte in the image you are at
    Qt Code:
    1. m_index = 0;
    To copy to clipboard, switch view to plain text mode 
    then, when you receive image data, you copy the data into the image
    Qt Code:
    1. // loop through incoming data
    2. for (int i = 0; i < data.count(); ++i, ++m_index) {
    3. m_image.bits()[m_index] = data[i];
    4. }
    To copy to clipboard, switch view to plain text mode 
    That can probably be optimized using memcpy() instead of the loop.

    Cheers,
    _

  5. #5
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    The kind of problem you are facing has been extensively covered multiple times on this forum. Searching the forum will give you lots of useful advice.

    Reading structured data (such as an image) asynchronously is not entirely trivial because you need to explicitly represent the state of a decoder that may be stopped at any point. By contrast, with synchronous I/O the state is implicitly represented in the context of the decoding thread.

    In your case, you will need:
    • an enum value State representing the piece of data you are currently receiving: command ID, counter, size of meta header, width, height, image data, or meta header;
    • an integer I representing how many bytes are missing from the piece of data currently received;
    • variables representing data currently being received or already received (e.g. a quint32 for each of the command ID, counter, size of meta header, width, and height, a QImage, and something for the meta header -- maybe a QByteArray -- should do it).


    Initialize State with "currently receiving the command ID", and I with 4 (since the command ID is encoded on 4 bytes). When you receive readyRead(), do the following:
    1. Start a loop.
    2. If there are 0 bytes to read, then exit the loop.
    3. Switch on S.
    4. Read up to I bytes straight to the target buffer (e.g. I bytes from the end of the appropriate quint32, QImage raw data, or QByteArray), and subtract from I the number of bytes actually read.
    5. If I becomes 0, then you finished reading the current piece of data; do some postprocessing (such as endianness conversion, checks that values are withing acceptable bounds, etc.), update S and I and the other variables (for example, if you are then preparing to receive the QImage's raw data, do not forget to set its size). If you just received the last piece of data, notify the user by emitting a signal.
    6. Loop.

  6. #6
    Join Date
    Jun 2014
    Posts
    16
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    The disadvantage is that you need a second thread if you don't want to block the UI.
    A multithreaded program is usually much harder to get right.
    Understood.

    The command ID is part of the data, no?
    So it can be read from the socket independent of whether you wait for data blockingly or asynchronously.
    The command ID is part of the receiving data. It tells me which data format will I receive. But it is not part of the image data. The real useful image data comes after <Height (4 bytes)>. The image data is an exact copy of the image memory with size <width> * <height> coded in U8.


    Well, you can use the data stream to interpret multibyte integers for you, but don't expect it to be of any value for any other type of data.
    After I read the width and height using data stream. How can I read and save the image data so that I can use your method below to build the QImage?


    You would create the image when you know about its size
    Qt Code:
    1. m_image = QImage(width, height, QImage::Format_Indexed8);
    To copy to clipboard, switch view to plain text mode 
    you need to have either a pointer to the current byte or an index that tells you which byte in the image you are at
    Qt Code:
    1. m_index = 0;
    To copy to clipboard, switch view to plain text mode 
    then, when you receive image data, you copy the data into the image
    Qt Code:
    1. // loop through incoming data
    2. for (int i = 0; i < data.count(); ++i, ++m_index) {
    3. m_image.bits()[m_index] = data[i];
    4. }
    To copy to clipboard, switch view to plain text mode 
    That can probably be optimized using memcpy() instead of the loop.

    Cheers,

  7. #7
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Quote Originally Posted by benz6699 View Post
    After I read the width and height using data stream. How can I read and save the image data so that I can use your method below to build the QImage?
    QTcpSocket is a QIODevice subclass, you can use its read methods, e.g. readAll() to read all currently buffered data.

    Cheers,
    _

  8. #8
    Join Date
    Jun 2014
    Posts
    16
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Quote Originally Posted by anda_skoa View Post
    QTcpSocket is a QIODevice subclass, you can use its read methods, e.g. readAll() to read all currently buffered data.

    Cheers,
    _
    Thanks for your advice. I have tried your method below to read and construct the image (gray level image). In the debugging mode I have checked that all the value stored in the variable "buffer" are zero (Refer attachment "BufferAllZero.jpg"). However the image I get is not totally black (It should be all black as I am not providing any light to the sensor). There are always some pixels with different color at the right bottom of the image (Refer attachment "temp1.png"). Can it be the noise? Or the image format I use is not suitable?

    Qt Code:
    1. pixel = width * height;
    2. char *temp = new char[pixel];
    3. //char *temp = 0;
    4. input.readRawData(temp, pixel);
    5. buffer.append(temp, pixel);
    6.  
    7.  
    8. QImage image = QImage(8, 10, QImage::Format_Indexed8);
    9.  
    10. int m_index = 0;
    11. for (int i = 0; i < 79; ++i, ++m_index)
    12. {
    13. image.bits()[m_index] = buffer[i];
    14.  
    15. }
    16. bool gray = image.isGrayscale();
    17.  
    18. if( !image.isNull() )
    19. {
    20. int result = image.save("E:/temp1.png", "PNG",1);
    21. }
    To copy to clipboard, switch view to plain text mode 
    Attached Images Attached Images

  9. #9
    Join Date
    Mar 2011
    Posts
    120
    Thanked 1 Time in 1 Post
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Try to read from socket.

    Qt Code:
    1. int sizeReceived = 0;
    2. int sizeAvailable = 0;
    3.  
    4. while(socket->waitForReadyRead(time) && socket->bytesAvailable())
    5. {
    6. sizeAvailable = socket->bytesAvailable();
    7. if(totalSize < sizeReceived + sizeAvailable)
    8. buffer += socket->read(sizeAvailable);
    9. else
    10. {
    11. buffer += socket->read(totalSize - sizeReceived);
    12. break;
    13. }
    14. sizeReceived += sizeAvailable ;
    15. }
    To copy to clipboard, switch view to plain text mode 

    (Please ignore if there is some syntax mistake. This is just a dummy code.)

    then user buffer to construct QImage.

  10. #10
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,416
    Thanks
    37
    Thanked 1,544 Times in 1,494 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Quote Originally Posted by benz6699 View Post
    However the image I get is not totally black (It should be all black as I am not providing any light to the sensor). There are always some pixels with different color at the right bottom of the image (Refer attachment "temp1.png"). Can it be the noise?
    Have you checked the return value of readRawData()? Is it the number of bytes you expect?

    Cheers,
    _

  11. #11
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    You cannnot expect to read all the image data from the socket in one go. As already said in this thread, you must keep track of how much data you have received. My previous post outlines a solution to your problem that does not assume any single piece of data (including the 32-bit integers) to be read in a single execution of the slot connected to readyRead().

  12. #12
    Join Date
    Jun 2014
    Posts
    16
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Quote Originally Posted by anda_skoa View Post
    Have you checked the return value of readRawData()? Is it the number of bytes you expect?

    Cheers,
    _
    Yes, I have checked the return value of readRawData(). It is the number of bytes I expect. For this testing I have set the camera so that it deliver only 8 x 10 pixel image. And all the values in the buffer are zero from buffer[0] to buffer[79]. So I should get a total black image right? However I always get an image with pixels with other colour at the bottom right corner. I cannot identify where is my mistake here. Please advice.

  13. #13
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    What value does QImage::byteCount() return? Scanlines must be 32-bit aligned, which generally introduces some padding; though there shouldn't be any if your image is 8 pixels wide and 8 bits deep.

    By the way, you do not need to go through a temporary buffer. Just read into QImage::bits() directly.

  14. #14
    Join Date
    Jun 2014
    Posts
    16
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Quote Originally Posted by yeye_olive View Post
    What value does QImage::byteCount() return? Scanlines must be 32-bit aligned, which generally introduces some padding; though there shouldn't be any if your image is 8 pixels wide and 8 bits deep.

    By the way, you do not need to go through a temporary buffer. Just read into QImage::bits() directly.
    QImage::byteCount() return the value I expect which is 80 (I "ask" the sensor to send me 8 x 10 x1 byte image). So what else can I check more?

    Can you show me the code of how to read data directly into QImage::bits()? Thanks.

  15. #15
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Quote Originally Posted by benz6699 View Post
    QImage::byteCount() return the value I expect which is 80 (I "ask" the sensor to send me 8 x 10 x1 byte image). So what else can I check more?
    Could you post a minimal complete example reproducing the problem?
    Quote Originally Posted by benz6699 View Post
    Can you show me the code of how to read data directly into QImage::bits()? Thanks.
    Sure, something like: result = my_qiodevice_ptr->read(my_qimage.bits() + number_of_bytes_already_read, my_qimage.byteCount() - number_of_bytes_already_read);

  16. #16
    Join Date
    Jun 2014
    Posts
    16
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Quote Originally Posted by yeye_olive View Post
    Could you post a minimal complete example reproducing the problem?
    Qt Code:
    1. #include "client.h"
    2. #include <QHostAddress>
    3. #include "mainwindow.h"
    4. #include <QtGui>
    5. #include <QAbstractSocket>
    6. #include <QImage>
    7.  
    8. Client::Client(QWidget *parent) :
    9. QWidget(parent)
    10. {
    11. socket = new QTcpSocket(this);
    12. connect(socket, SIGNAL(readyRead()),this, SLOT(tcpReady()) );
    13. }
    14.  
    15. int Client::capture(int mode, int NBRLine)
    16. {
    17. if (socket->state() != QTcpSocket::ConnectedState)
    18. {
    19. socket->connectToHost("192.168.0.65", 1096);
    20. }
    21. /* send command to retrieve raw image data from sensor */
    22. if(socket->waitForConnected(5000))
    23. {
    24. QByteArray block;
    25. QDataStream out(&block, QIODevice::WriteOnly);
    26. out.setVersion(QDataStream::Qt_4_0);
    27. out.setByteOrder(QDataStream::LittleEndian);
    28. //out << qint32(0) << qint32(0) << qint32(0) << qint32(1);
    29. out << qint32(9) << qint32(1) << qint32(0) << mode << qint32(10) << qint32(2) << qint32(0) << NBRLine ;
    30. socket->write(block);
    31. socket->flush();
    32. }
    33. else
    34. {
    35. return false;
    36. }
    37. }
    38.  
    39.  
    40. int Client::tcpReady()
    41. {
    42. QDataStream input(socket);
    43. input.setVersion(QDataStream::Qt_4_0);
    44. input.setByteOrder(QDataStream::LittleEndian);
    45. qint32 cmdID, counter, metaSize, CmdNbr, min, max, value, error, width, height;
    46. QByteArray buffer;
    47.  
    48. int sizereceived = 0;
    49. int sizeAvailable = 0;
    50.  
    51. forever{
    52. if (socket->bytesAvailable() < sizeof(qint32))
    53. {
    54. return 0;
    55. }
    56. input >> cmdID;
    57. // We get the data response with cmdID = 100 when we send a command to get parameter value
    58. if (cmdID == 100)
    59. {
    60. input >> counter >> metaSize >> CmdNbr >> min >> max >> value;
    61. }
    62. // We get the data response with cmdID = 101 when we send a command to set parameter value
    63. else if (cmdID == 101)
    64. {
    65. input >> counter >> metaSize >> CmdNbr >> error;
    66. }
    67. // Here we get a streaming raw image data
    68. else if (cmdID == 1)
    69. {
    70. break;
    71. }
    72. else
    73. {
    74. return 0;
    75. }
    76. }
    77.  
    78. // Here we read the data and construct image
    79. input >> counter >> metaSize >> width >> height;
    80. int pixel = width * height;
    81. char *temp = new char[pixel];
    82. //char *temp = 0;
    83. int read = input.readRawData(temp, pixel);
    84. buffer.append(temp, pixel);
    85. QImage image = QImage(width, height, QImage::Format_Indexed8);
    86. delete [] temp;
    87.  
    88. int m_index = 0;
    89. for (int i = 0; i < (pixel-1); ++i, ++m_index)
    90. {
    91. image.bits()[m_index] = buffer[i];
    92. }
    93. int cnt = image.byteCount();
    94. bool gray = image.isGrayscale();
    95.  
    96. if( !image.isNull() )
    97. {
    98. int result = image.save("E:/temp1.png", "PNG",1);
    99. }
    100. return 1;
    101. }
    To copy to clipboard, switch view to plain text mode 


    Sure, something like: result = my_qiodevice_ptr->read(my_qimage.bits() + number_of_bytes_already_read, my_qimage.byteCount() - number_of_bytes_already_read);
    I tried the following code, but it give me the error message" :-1: error: C2664: 'qint64 QIODevice::read(char *,qint64)' : cannot convert parameter 1 from 'uchar *' to 'char *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast."

    Qt Code:
    1. input >> counter >> metaSize >> width >> height;
    2. int pixel = width * height;
    3.  
    4. QImage image = QImage(width, height, QImage::Format_Indexed8);
    5. socket->read(image.bits(), pixel);
    To copy to clipboard, switch view to plain text mode 

  17. #17
    Join Date
    Jun 2014
    Posts
    16
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    Quote Originally Posted by bibhukalyana View Post
    Try to read from socket.

    Qt Code:
    1. int sizeReceived = 0;
    2. int sizeAvailable = 0;
    3.  
    4. while(socket->waitForReadyRead(time) && socket->bytesAvailable())
    5. {
    6. sizeAvailable = socket->bytesAvailable();
    7. if(totalSize < sizeReceived + sizeAvailable)
    8. buffer += socket->read(sizeAvailable);
    9. else
    10. {
    11. buffer += socket->read(totalSize - sizeReceived);
    12. break;
    13. }
    14. sizeReceived += sizeAvailable ;
    15. }
    To copy to clipboard, switch view to plain text mode 

    (Please ignore if there is some syntax mistake. This is just a dummy code.)

    then user buffer to construct QImage.

    I have tried your method to read the big file. It is working to combine the small packet to become one. However the image I get is different from the original image (refer attachment ori.jpg with only one line and temp1.png with 4 line). Any idea?

    Qt Code:
    1. input >> counter >> metaSize >> width >> height;
    2. int totalSize = width * height;
    3. int sizeReceived = 0;
    4. int sizeAvailable = 0;
    5. char *temp = new char[totalSize];
    6.  
    7. while(socket->waitForReadyRead(1000) && socket->bytesAvailable())
    8. {
    9. sizeAvailable = socket->bytesAvailable();
    10. if (totalSize > (sizeReceived + sizeAvailable))
    11. {
    12. input.readRawData(temp, sizeAvailable);
    13. buffer.append(temp, sizeAvailable);
    14. }
    15. else
    16. {
    17. input.readRawData(temp, (totalSize - sizeReceived));
    18. buffer.append(temp, (totalSize - sizeReceived));
    19. break;
    20. }
    21. sizeReceived += sizeAvailable;
    22. }
    23.  
    24. QImage image = QImage(width, height, QImage::Format_Indexed8);
    25. delete [] temp;
    26.  
    27. int m_index = 0;
    28. for (int i = 0; i < (totalSize-1); ++i, ++m_index)
    29. {
    30. image.bits()[m_index] = buffer[i];
    31. }
    32. int cnt = image.byteCount();
    33. bool gray = image.isGrayscale();
    34.  
    35. if( !image.isNull() )
    36. {
    37. int result = image.save("E:/temp1.png", "PNG",1);
    38. }
    To copy to clipboard, switch view to plain text mode 

    ori.jpgtemp1.jpg

  18. #18
    Join Date
    Oct 2009
    Posts
    483
    Thanked 97 Times in 94 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    I dug this up a bit, and here are my findings.

    It seems that QImage::save() produces garbage unless you set the color map. The following example demonstrates this:
    Qt Code:
    1. #include <QImage>
    2.  
    3. int main(int argc, char *argv[])
    4. {
    5. QImage image(8, 10, QImage::Format_Indexed8);
    6. image.setColorTable(QVector<QRgb>() << 0xff0000ff); // This line is crucial
    7. image.fill(0);
    8. image.save("foo.png");
    9. return 0;
    10. }
    To copy to clipboard, switch view to plain text mode 
    This produces a blue image as expected, and garbage if you omit line 6. Do not forget to initialize the color table, then. In your case it may mean streaming it along with the image data, depending on whether or not the color table is always the same.

    Secondly, avoid going through all these useless intermediate buffers (temp and buffer). If you are going to use QDataStream::readRawData(), just do my_qdatastream.readRawData(reinterpret_cast<char *>(my_qimage.bits()), my_qimage.byteCount()), provided you are certain you have enough bytes in the stream, of course.

    Finally, your current approach to reading from the socket in one go is completely broken. As I have already warned you twice about it, I will stop here. Just do not be surprised if this stops working as soon as you test your program over a real network.

  19. #19
    Join Date
    Jun 2014
    Posts
    16
    Thanks
    2
    Qt products
    Qt4 Qt/Embedded
    Platforms
    Windows

    Default Re: Receiving raw image data through TCP for display using Qt

    This produces a blue image as expected, and garbage if you omit line 6. Do not forget to initialize the color table, then. In your case it may mean streaming it along with the image data, depending on whether or not the color table is always the same.
    Where should I put the following code:

    Qt Code:
    1. image.setColorTable(QVector<QRgb>() << 0xff0000ff); // This line is crucial
    2. image.fill(0);?
    To copy to clipboard, switch view to plain text mode 

    before or after input.readRawData(reinterpret_cast<char *>(image.bits()), sizeAvailable);?

    My code is as the following:

    Qt Code:
    1. int Client::tcpReady()
    2. {
    3. QDataStream input(socket);
    4. input.setVersion(QDataStream::Qt_4_0);
    5. input.setByteOrder(QDataStream::LittleEndian);
    6. qint32 cmdID, counter, metaSize, CmdNbr, min, max, value, error, width, height;
    7. QByteArray buffer;
    8.  
    9. forever{
    10. if (socket->bytesAvailable() < sizeof(qint32))
    11. {
    12. return 0;
    13. }
    14. input >> cmdID;
    15. // We get the data response with cmdID = 100 when we send a command to get parameter value
    16. if (cmdID == 100)
    17. {
    18. input >> counter >> metaSize >> CmdNbr >> min >> max >> value;
    19. }
    20. // We get the data response with cmdID = 101 when we send a command to set parameter value
    21. else if (cmdID == 101)
    22. {
    23. input >> counter >> metaSize >> CmdNbr >> error;
    24. }
    25. // Here we get a streaming raw image data
    26. else if (cmdID == 1)
    27. {
    28. break;
    29. }
    30. else
    31. {
    32. return 0;
    33. }
    34. }
    35. input >> counter >> metaSize >> width >> height;
    36. int totalSize = width * height;
    37. int sizeReceived = 0;
    38. int sizeAvailable = 0;
    39.  
    40.  
    41. QImage image = QImage(width, height, QImage::Format_Indexed8);
    42. // image.setColorTable(QVector<QRgb>() << 0xff0000ff); // This line is crucial
    43. // image.fill(0);
    44.  
    45. while(socket->waitForReadyRead(1000) && socket->bytesAvailable())
    46. {
    47. sizeAvailable = socket->bytesAvailable();
    48. if (totalSize > (sizeReceived + sizeAvailable))
    49. {
    50. input.readRawData(reinterpret_cast<char *>(image.bits()), sizeAvailable);
    51. }
    52. else
    53. {
    54. input.readRawData(reinterpret_cast<char *>(image.bits()), (totalSize - sizeReceived));
    55. break;
    56. }
    57. sizeReceived += sizeAvailable;
    58. }
    59.  
    60.  
    61. if( !image.isNull() )
    62. {
    63. int result = image.save("E:/temp1.png", "PNG",1);
    64. }
    65. return 1;
    66. }
    To copy to clipboard, switch view to plain text mode 

    Secondly, avoid going through all these useless intermediate buffers (temp and buffer). If you are going to use QDataStream::readRawData(), just do my_qdatastream.readRawData(reinterpret_cast<char *>(my_qimage.bits()), my_qimage.byteCount()), provided you are certain you have enough bytes in the stream, of course.
    I have used this method in my code. But it give me a blank image. Did I apply your method incorrectly?
    Finally, your current approach to reading from the socket in one go is completely broken. As I have already warned you twice about it, I will stop here. Just do not be surprised if this stops working as soon as you test your program over a real network.
    Thanks for your precious advice. I always keep that in my mind. I just want to deal the image issue before this one. I handle this issue in the latest code, but I found out that if the sensor send me the image non-stop, my software will be hanged. I cannot do anything on my software ( even I tried to move the position of my software). Any mistake I made?

Similar Threads

  1. Receiving Image through serial port in QT
    By jakr13 in forum Qt Programming
    Replies: 3
    Last Post: 4th February 2013, 05:14
  2. Display my data array as an image
    By OzQTNoob in forum Newbie
    Replies: 5
    Last Post: 4th December 2012, 09:17
  3. Replies: 0
    Last Post: 26th July 2012, 09:32
  4. How to Display/Paint raw image data.
    By vinaykusta in forum Qt Programming
    Replies: 5
    Last Post: 12th October 2011, 14:01
  5. Replies: 2
    Last Post: 29th September 2008, 00:08

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.