Уже несколько дней я пытаюсь отправить данные 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, ¶m, ¶m_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 работает без проблем.
После отладки я заметил следующее:
Данные JPG, отправленные передатчиком, в точности совпадают с полученными. Кроме того, метаданные и BMP также принимаются правильно.
Когда приемник загружает изображения JPG с жесткого диска с QPixmap::load(path_to.jpg)
изображения правильно отображаются в графическом интерфейсе. (Обратите внимание, что файлы JPG были сгенерированы передатчиком за несколько миллисекунд до загрузки).
Полученные данные полностью отличаются от данных, загружаемых с жесткого диска, независимо от того, имеют ли они одинаковый источник.
Размер передаваемых байтов точно такой же, как на жестком диске. Данные имеют тип uint8_t на приемнике и на передатчике.
В чем может быть причина того, что переданные данные отличаются от данных, загружаемых с жесткого диска?
Может ли QT выполнить преобразование внутренне?