285 lines
10 KiB
C++
285 lines
10 KiB
C++
#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;
|
||
}
|