#include "update_data.h" #include "rle.h" #include #include static QImage* _rdpimg2QImage(int w, int h, int bitsPerPixel, bool isCompressed, const uint8_t* dat, uint32_t len) { QImage* out; switch(bitsPerPixel) { case 15: if(isCompressed) { uint8_t* _dat = reinterpret_cast(calloc(1, w*h*2)); if(!bitmap_decompress1(_dat, w, h, dat, len)) { free(_dat); return nullptr; } out = new QImage(_dat, w, h, QImage::Format_RGB555); free(_dat); } else { out = new QImage(QImage(dat, w, h, QImage::Format_RGB555).transformed(QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))); } return out; case 16: if(isCompressed) { uint8_t* _dat = reinterpret_cast(calloc(1, w*h*2)); if(!bitmap_decompress2(_dat, w, h, dat, len)) { free(_dat); qDebug() << "22------------------DECOMPRESS2 failed."; return nullptr; } // TODO: 这里需要进一步优化,直接操作QImage的buffer。 out = new QImage(w, h, QImage::Format_RGB16); for(int y = 0; y < h; y++) { for(int x = 0; x < w; x++) { uint16 a = ((uint16*)_dat)[y * w + x]; uint8 r = ((a & 0xf800) >> 11) * 255 / 31; uint8 g = ((a & 0x07e0) >> 5) * 255 / 63; uint8 b = (a & 0x001f) * 255 / 31; out->setPixelColor(x, y, QColor(r,g,b)); } } free(_dat); return out; } else { out = new QImage(QImage(dat, w, h, QImage::Format_RGB16).transformed(QMatrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0))); } return out; case 24: case 32: default: qDebug() << "--------NOT support UNKNOWN bitsPerPix" << bitsPerPixel; return nullptr; } } static QImage* _raw2QImage(int w, int h, const uint8_t* dat, uint32_t len) { QImage* out; // TODO: 这里需要进一步优化,直接操作QImage的buffer。 out = new QImage(w, h, QImage::Format_RGB16); for(int y = 0; y < h; y++) { for(int x = 0; x < w; x++) { uint16 a = ((uint16*)dat)[y * w + x]; uint8 r = ((a & 0xf800) >> 11) * 255 / 31; uint8 g = ((a & 0x07e0) >> 5) * 255 / 63; uint8 b = (a & 0x001f) * 255 / 31; out->setPixelColor(x, y, QColor(r,g,b)); } } return out; } UpdateData::UpdateData() : QObject(nullptr) { _init(); } UpdateData::UpdateData(int data_type) : QObject(nullptr) { _init(); m_data_type = data_type; } UpdateData::UpdateData(const TS_RECORD_HEADER& hdr) : QObject(nullptr) { _init(); m_data_type = TYPE_HEADER_INFO; m_hdr = new TS_RECORD_HEADER; memcpy(m_hdr, &hdr, sizeof(TS_RECORD_HEADER)); } UpdateData::UpdateData(uint16_t screen_w, uint16_t screen_h) { _init(); m_screen_w = screen_w; m_screen_h = screen_h; } void UpdateData::_init() { m_data_type = TYPE_UNKNOWN; m_hdr = nullptr; m_pointer = nullptr; // m_img = nullptr; // m_img_info = nullptr; m_data_buf = nullptr; m_data_len = 0; m_time_ms = 0; m_screen_w = 0; m_screen_h = 0; } UpdateData::~UpdateData() { if(m_hdr) delete m_hdr; if(m_pointer) delete m_pointer; // if(m_img) // delete m_img; // if(m_img_info) // delete m_img_info; for(int i = 0; i < m_images.size(); ++i) { delete m_images[i].img; } m_images.clear(); if(m_data_buf) delete m_data_buf; } bool UpdateData::parse(const TS_RECORD_PKG& pkg, const QByteArray& data) { m_time_ms = pkg.time_ms; if(pkg.type == TS_RECORD_TYPE_RDP_POINTER) { m_data_type = TYPE_POINTER; if(data.size() != sizeof(TS_RECORD_RDP_POINTER)) return false; m_pointer = new TS_RECORD_RDP_POINTER; memcpy(m_pointer, data.data(), sizeof(TS_RECORD_RDP_POINTER)); return true; } else if(pkg.type == TS_RECORD_TYPE_RDP_IMAGE) { m_data_type = TYPE_IMAGE; if(data.size() <= static_cast(sizeof(uint16_t) + sizeof(TS_RECORD_RDP_IMAGE_INFO))) return false; const uint8_t* dat_ptr = reinterpret_cast(data.data()); uint16_t count = (reinterpret_cast(dat_ptr))[0]; uint32_t offset = sizeof(uint16_t); for(uint16_t i = 0; i < count; ++i) { const TS_RECORD_RDP_IMAGE_INFO* info = reinterpret_cast(dat_ptr+offset); offset += sizeof(TS_RECORD_RDP_IMAGE_INFO); //const uint8_t* img_dat = reinterpret_cast(data.data() + sizeof(TS_RECORD_RDP_IMAGE_INFO)); //uint32_t img_len = data.size() - sizeof(TS_RECORD_RDP_IMAGE_INFO); const uint8_t* img_dat = dat_ptr + offset; offset += info->dat_len; QImage* img = _rdpimg2QImage(info->width, info->height, info->bitsPerPixel, (info->format == TS_RDP_IMG_BMP) ? true : false, img_dat, info->dat_len); if(img == nullptr) return false; // m_img = img; // m_img_x = info->destLeft; // m_img_y = info->destTop; // m_img_w = info->destRight - info->destLeft + 1; // m_img_h = info->destBottom - info->destTop + 1; UPDATE_IMAGE uimg; uimg.x = info->destLeft; uimg.y = info->destTop; uimg.w = info->destRight - info->destLeft + 1; uimg.h = info->destBottom - info->destTop + 1; uimg.img = img; m_images.push_back(uimg); } return true; } else if(pkg.type == TS_RECORD_TYPE_RDP_KEYFRAME) { m_data_type = TYPE_IMAGE; // const TS_RECORD_RDP_KEYFRAME_INFO* info = reinterpret_cast(data.data()); const uint8_t* img_dat = reinterpret_cast(data.data() + sizeof(TS_RECORD_RDP_KEYFRAME_INFO)); uint32_t img_len = data.size() - sizeof(TS_RECORD_RDP_KEYFRAME_INFO); QImage* img = _raw2QImage((int)m_screen_w, (int)m_screen_h, img_dat, img_len); if(img == nullptr) return false; UPDATE_IMAGE uimg; uimg.x = 0; uimg.y = 0; uimg.w = m_screen_w; uimg.h = m_screen_h; uimg.img = img; m_images.push_back(uimg); // m_img = img; // m_img_x = 0; // m_img_y = 0; // m_img_w = m_screen_w; // m_img_h = m_screen_h; return true; } return false; } void UpdateData::alloc_data(uint32_t len) { if(m_data_buf) delete m_data_buf; m_data_buf = new uint8_t[len]; memset(m_data_buf, 0, len); m_data_len = len; } void UpdateData::attach_data(const uint8_t* dat, uint32_t len) { if(m_data_buf) delete m_data_buf; m_data_buf = new uint8_t[len]; memcpy(m_data_buf, dat, len); m_data_len = len; }