285 lines
10 KiB
C++
Raw Normal View History

2025-12-10 00:01:32 +08:00
#include "FormatConvert.h"
#include "ItkCamera.h"
#include <QDebug>
/// \~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 <QElapsedTimer>
/// \~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;
}