285 lines
10 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}