#include "FormatConvert.h" #include "ItkCamera.h" #include /// \~chinese 按双字节读取数据,截取高8位存到QImage中用作显示 \~english Read data in two bytes, intercept high 8 bits into QImage for display void ReadDataByShort(uchar* pDst, uchar* pSrc, qint64 srcSize, int nDepth) { uchar* pReadCursor = nullptr; qint64 i = 0; int offset = nDepth - 8; for (i = 0; i < srcSize; i += 2) { pReadCursor = pSrc + i; *pDst++ = (pReadCursor[0] >> offset) | (pReadCursor[1] << (8 - offset)); } } /// \~chinese 从8bit的RGBC数据中分离出RGB通道 \~english Separate the RGB data from 8 bit RGBC data void ReadRGBFromRGBC8(uchar* pSrc, qint64 iSrcSize, uchar* pDst) { uchar* pReadCursor = NULL; qint64 i = 0; for (i = 0; i < iSrcSize; i += 4) { pReadCursor = pSrc + i; *pDst++ = pReadCursor[0]; *pDst++ = pReadCursor[1]; *pDst++ = pReadCursor[2]; } } /// \~chinese 从16bit的RGBC数据中分离出RGB通道,并截取高8位 \~english Separate the RGB data from 16 bit RGBC data, intercept high 8 bits into QImage for display void ReadRGB8FromRGBC16(uchar* pSrc, qint64 iSrcSize, uchar* pDst, int nDepth) { uchar* pReadCursor = NULL; qint64 i = 0; int offset = nDepth - 8; for (i = 0; i < iSrcSize; i += 8) { pReadCursor = pSrc + i; *pDst++ = (pReadCursor[0] >> offset) | (pReadCursor[1] << (8 - offset)); *pDst++ = (pReadCursor[2] >> offset) | (pReadCursor[3] << (8 - offset)); *pDst++ = (pReadCursor[4] >> offset) | (pReadCursor[5] << (8 - offset)); } } /// \~chinese QImage释放时,释放分配的内存 \~english Release the memory when QImage released void cleanMalloc(void* info) { free(info); } /// \~chinese QImage释放时,释放传入的ITKBUFFER \~english Release the ITKBUFFER when QImage released void cleanItkBuffer(void* info) { if (nullptr == info) return; ITKBUFFER hBuffer = (ITKBUFFER)info; ItkBufferFree(hBuffer); } /// \~chinese 根据相机和当前像素格式确定最终的输出图像像素格式 \~english Get the output image data format with current camera type uint32_t getImagePixelFormat(ItkCamera* pCam, ITKBUFFER& hBuffer, bool& bColor) { #ifdef Q_OS_WIN ITK_BUFFER_INFO cvtBufferInfo; ItkBufferGetInfo(hBuffer, &cvtBufferInfo); uint64_t cvtBufferFormat = cvtBufferInfo.PixelFormat; #else uint32_t len = 128; char buffer[128] = {}; uint32_t nFormat; ItkDevToString(pCam->g_hCamera, "PixelFormat", buffer, &len); ItkDevGetPixelFormatVal(pCam->g_hCamera, buffer, &nFormat); uint64_t cvtBufferFormat = nFormat; #endif /// \~chinese 非CXP设备需要将RGB与BGR翻转 \~english Camera which is not CXP need convert RGB and BGR uint32_t format = cvtBufferFormat; if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_RGB888PACKED) { format = ITKBUFFER_VAL_FORMAT_BGR888PACKED; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_RGB888) { format = ITKBUFFER_VAL_FORMAT_BGR888; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_RGB101010) { format = ITKBUFFER_VAL_FORMAT_BGR101010; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_RGB121212) { format = ITKBUFFER_VAL_FORMAT_BGR121212; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_RGB141414) { format = ITKBUFFER_VAL_FORMAT_BGR141414; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_RGB161616) { format = ITKBUFFER_VAL_FORMAT_BGR161616; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_BGR888PACKED) { format = ITKBUFFER_VAL_FORMAT_RGB888PACKED; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_BGR888) { format = ITKBUFFER_VAL_FORMAT_RGB888; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_BGR101010) { format = ITKBUFFER_VAL_FORMAT_RGB101010; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_BGR121212) { format = ITKBUFFER_VAL_FORMAT_RGB121212; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_BGR141414) { format = ITKBUFFER_VAL_FORMAT_RGB141414; bColor = true; } if (cvtBufferFormat == ITKBUFFER_VAL_FORMAT_BGR161616) { format = ITKBUFFER_VAL_FORMAT_RGB161616; bColor = true; } return format; } #include /// \~chinese ITKBUFFER转QImage \~english Convert ITKBUFFER to QImage QImage ImageFromItkBuffer(ItkCamera *cam, ITKBUFFER hBuffer) { ITKBUFFER* hRead = &hBuffer; int64_t nImageWidth=0; int64_t nImageHeight=0; uint8_t bNeedCvt = 0; #ifdef Q_OS_WIN ITK_BUFFER_INFO bufferInfo; ItkBufferGetInfo(hBuffer, &bufferInfo); /// \~chinese 获取图像尺寸 \~english Get image size nImageWidth = bufferInfo.ImageWidth; nImageHeight = bufferInfo.ImageHeight; /// \~chinese 判断是否需要转换 \~english Judge if need convert ItkBufferNeedAutoConvert(hBuffer, &bNeedCvt); #else ItkBufferGetPrm(hBuffer, ITKBUFFER_PRM_WIDTH, &nImageWidth); ItkBufferGetPrm(hBuffer, ITKBUFFER_PRM_HEIGHT, &nImageHeight); #endif #ifdef Q_OS_WIN if (bNeedCvt) { /// \~chinese 创建任意格式的缓冲区来存储转换结果 \~english Create buffer in any format as result QElapsedTimer timer; timer.start(); /// \~chinese 经过转换后,会输出BGR格式 \~english Auto convert will output BGR format ITKSTATUS ret = ItkBufferConvert(hBuffer, cam->g_hCvtBuffer, 0, ITKBUFFER_VAL_CONVERT_OPTION_AUTO_FORMAT); qDebug() <<"ItkBufferConvert spent time:" << timer.elapsed() << endl; qDebug() << "ItkBuffertConvert result is " << hex << ret << endl; hRead = &cam->g_hCvtBuffer; } #endif bool bColor = false; uint32_t nFormat = getImagePixelFormat(cam, *hRead, bColor); #ifdef Q_OS_WIN if (!strcmp(cam->g_devInfo.DeviceClass, "CoaXPress") == 0 && bColor) { /// \~chinese 根据Buffer像素格式确定最终的输出图像像素格式 \~english Get the buffer format with current camera type ITKBUFFER itkBufferReal = nullptr; ItkBufferNew(nImageWidth, nImageHeight, nFormat, &itkBufferReal); ITKSTATUS ret = ItkBufferConvert(*hRead, itkBufferReal, nFormat, 0); qDebug() << "output format is " << hex << nFormat << endl; qDebug() << "ItkBufferConvert result:" << hex << ret << endl; hRead = &itkBufferReal; } #endif #ifdef Q_OS_WIN ItkBufferGetInfo(*hRead,&bufferInfo); /// \~chinese 获取通道数 \~english Get channel int channel = ITKBUFFER_FORMAT_IMAGE_CHANNELS(bufferInfo.PixelFormat); #else int channel =ITKBUFFER_FORMAT_IMAGE_CHANNELS(nFormat); #endif QImage::Format fmt; switch (channel) { case 1: fmt = QImage::Format_Grayscale8; break; case 3: fmt = QImage::Format_RGB888; break; case 4: fmt = QImage::Format_RGBA8888; break; default: return QImage(); } /// \~chinese 从缓冲区读取数据 \~english Read data from buffer void *pBufferAddr = nullptr; int64_t nImageSize = 0; int nImageDepth = 0; ItkBufferGetPrm(*hRead, ITKBUFFER_PRM_ADDRESS, &pBufferAddr); ItkBufferGetPrm(*hRead, ITKBUFFER_PRM_SIZE, &nImageSize); ItkBufferGetPrm(*hRead, ITKBUFFER_PRM_PIXEL_DEPTH, &nImageDepth); if (nImageDepth > 8) { uchar* data = (uchar*)malloc(nImageSize / 2); ReadDataByShort(data, (uchar*)pBufferAddr, nImageSize, nImageDepth); return QImage(data, nImageWidth, nImageHeight, nImageSize / 2 / nImageHeight, fmt, cleanMalloc, data); } else { return QImage((uchar*)pBufferAddr, nImageWidth, nImageHeight, nImageSize / nImageHeight, fmt); } } /// \~chinese 获取采集卡的缓冲区数据,转为QImage \~english Get the buffer data of the grabber and convert to QImage QImage ImageFromGrabber(ItkCamera *cam) { /// \~chinese 获取图像尺寸 \~english Get image size int nImageWidth = 0; int nImageHeight = 0; IKapGetInfo(cam->g_hBoard, IKP_IMAGE_WIDTH, &nImageWidth); IKapGetInfo(cam->g_hBoard, IKP_IMAGE_HEIGHT, &nImageHeight); /// \~chinese 读取缓冲区数据 \~english Read data from grabber int nFrameIndex = 0; uchar *pUserBuffer = NULL; int nImageSize = 0; IKapGetInfo(cam->g_hBoard, IKP_CURRENT_BUFFER_INDEX, &nFrameIndex); IKapGetInfo(cam->g_hBoard, IKP_FRAME_SIZE, &nImageSize); IKapGetBufferAddress(cam->g_hBoard, nFrameIndex, (void**)&pUserBuffer); /// \~chinese 判断是否存在C线 \~english Judge if extra channel exist int nImgType = 0; int nImgDepth = 0; IKapGetInfo(cam->g_hBoard, IKP_IMAGE_TYPE, &nImgType); IKapGetInfo(cam->g_hBoard, IKP_DATA_FORMAT, &nImgDepth); if (IKP_IMAGE_TYPE_VAL_RGBC == nImgType || IKP_IMAGE_TYPE_VAL_BGRC == nImgType) { uchar* data = nullptr; if (nImgDepth == 8) { data = (uchar*)malloc(nImageSize * 0.75); ReadRGBFromRGBC8(pUserBuffer, nImageSize, data); return QImage(data, nImageWidth, nImageHeight, QImage::Format_RGB888, cleanMalloc, data); } else { data = (uchar*)malloc(nImageSize * 0.75 / 2); ReadRGB8FromRGBC16(pUserBuffer, nImageSize, data, nImgDepth); return QImage(data, nImageWidth, nImageHeight, QImage::Format_RGB888, cleanMalloc, data); } } /// \~chinese 创建缓冲区 \~english Create buffer ITKBUFFER hBuffer = nullptr; uint32_t len = 128; char buffer[128] = {}; uint32_t nFormat; ItkDevToString(cam->g_hCamera, "PixelFormat", buffer, &len); ItkDevGetPixelFormatVal(cam->g_hCamera, buffer, &nFormat); #ifdef Q_OS_WIN ItkBufferNewWithPtr(nImageWidth, nImageHeight, nFormat, pUserBuffer, &hBuffer); #else ItkBufferNew(nImageWidth,nImageHeight,nFormat,&hBuffer); #endif QImage img = ImageFromItkBuffer(cam, hBuffer); ItkBufferFree(hBuffer); return img; }