QPixmap :: loadFromData () не принимает данные JPG, полученные из TCP / IP - PullRequest
0 голосов
/ 20 октября 2019

Уже несколько дней я пытаюсь отправить данные JPG через TCP на интерфейс QT. Все изображения генерируются другим процессом, который выполняет обработку изображений на основе графического процессора. Топология сети показана ниже:

РЕДАКТИРОВАТЬ

Сторона передатчика

Ранее данные обрабатывались алгоритмом для изображений BMP24. После этого изображения BMP сжимаются / кодируются в JPG, чтобы уменьшить сетевой трафик. Кодирование выполняется с помощью этой библиотеки , которая используется в следующей функции.

void CudaBase::encodeBmpToJpeg(unsigned char* idata, uint8_t* odata, int* p_jpeg_size, int width, int height)
{
    ... // init stuff
    gpujpeg_encoder_input_set_image(&encoder_input, idata); // pass idata which contains interleaved BMP24 data
    gpujpeg_encoder_encode(encoder, &param, &param_image, &encoder_input, &image, p_jpeg_size);  // encode BMP24 to JPG, variable image holds compressed JPG data
    gpujpeg_image_save_to_file(image_dir, image, *p_jpeg_size);  // save JPG on harddrive
    CUDA_CHECK(cudaStreamSynchronize(stream));
    // Copy JPG from image to odata 
    odata = (uint8_t*) malloc(*p_jpeg_size);
    if(odata != nullptr)
        memcpy((void*)odata, (void*)image, *p_jpeg_size);
    else
        printf("Could not allocated memory for jpeg image\n");
    CUDA_CHECK(cudaStreamDestroy(stream));
    gpujpeg_image_destroy(image);
    gpujpeg_encoder_destroy(encoder);
}

Теперь odata содержит данные JPG и готова к отправке через TCP, что выполняетсяследующие:

socket.make_tcp_header(&header, nof_recieved_records, nof_records, ch);
socket.send(&header, sizeof(header));
socket.waitForACK();
socket.send(images[ch], algthm.getImageSize()); // images[ch] points to odata
socket.waitForACK();

Вот как передатчик отправляет

template <typename T>
void Socket::send(T* ptr, int count)
{
    printf("Writing to server... \n");
    int result = 0;
    int _size = count;
    do
    {
        result = write(sockfd, (void*)ptr, _size);
        if(result == -1)
        {
            printf("Error sending to server: %d\n",errno);
            _size = 0;
        }
        else
        {
            _size -= result;
        }
    }
    while(_size > 0);
}

На стороне получателя

На стороне клиента QT данные JPGзаписывается в QByteArray и затем отображается в QLabel с использованием функции QPixmap::loadFromData(), но loadFromData() всегда возвращает ноль. Похоже, что содержимое QByteArray не соответствует JPG. Когда данные получены клиентом, QT издает сигнал, и вызывается следующая функция readyRead ():

void ThreadSocket::readyRead()
{
    static qint64 sum = 0;
    while(socket->bytesAvailable())
    {
        sum += socket->bytesAvailable();
        data->append(socket->readAll());
    }
    // Receive header from client
    if(sum == header_size)
    {
        sum = 0;
        setHeader(stream);
        send("OK");
        emit received_data(META);
    }
    // receive image data
    else if(sum == header.img_size)
    {
        sum = 0;
        send("OK");
        emit received_data(RAW);
    }
    else
    {
        return;
    }
    clearBuffer();
}

EDIT заканчивается здесь

Следующая функция представляет собой слот, который генерируется при получении новых (необработанных) данных потоком клиента.

void Controller::refresh_image()
{
    tcp_header *header = socket->getHeader(); // Get header informations from threaded socket
    QPixmap pix;
    switch(header->format) 
    {
        case BMP24:
        {
            QImage img(socket->getData(),
                header->img_width,
                header->img_height,
                QImage::Format_RGB888);
            pix = QPixmap::fromImage(img);
            break;
        }
        case JPEG:
        {
            if(!(pix.loadFromData(socket->getData(), "JPG"))) // Every time return zero
                qDebug() << "Not able to load pixmap from data";
            break;
        }
    }
    // Reload images in GUI
    view->label_list()->at(header->current_channel)->setPixmap(pix);
    view->update();
}

Примечание tcp_header - это структура, которую я сам установил и являюсь частьюмой собственный протокол TCP. В зависимости от заголовка отображаются изображения BMP или JPG. Отображение изображений BMP работает без проблем.

После отладки я заметил следующее:

  1. Данные JPG, отправленные передатчиком, в точности совпадают с полученными. Кроме того, метаданные и BMP также принимаются правильно.

  2. Когда приемник загружает изображения JPG с жесткого диска с QPixmap::load(path_to.jpg) изображения правильно отображаются в графическом интерфейсе. (Обратите внимание, что файлы JPG были сгенерированы передатчиком за несколько миллисекунд до загрузки).

  3. Полученные данные полностью отличаются от данных, загружаемых с жесткого диска, независимо от того, имеют ли они одинаковый источник.

  4. Размер передаваемых байтов точно такой же, как на жестком диске. Данные имеют тип uint8_t на приемнике и на передатчике.

В чем может быть причина того, что переданные данные отличаются от данных, загружаемых с жесткого диска?

Может ли QT выполнить преобразование внутренне?

...