Vtk实现DCM转PNG

1 篇文章 0 订阅

namespace ImageDataToQimage
{
	// 限制输出像素值范围
	template<class F>
	inline F TP_LimitNum(F x, F xmin, F xmax)
	{
		x = (x > xmin ? x : xmin);
		x = (x < xmax ? x : xmax);
		return x;
	}

	//======================================
	// inPtr 输入数据指针,unsigned char类型
	// outPtr 输出数据指针,unsigned char类型,component size为4
	// ncols 图像列数(宽)
	// nrows 图像行数(高)
	// numComp 输入数据component size值,可以理解为通道数(R/G/B/A)
	//======================================
	inline void ConvertVtkImageToRGBA(const unsigned char *inPtr, unsigned char *outPtr, int ncols, int nrows, int numComp)
	{
		const int vmin = 0;
		const int vmax = 255;
		unsigned char alpha = 255;
		int inIncX = numComp;
		// loop through the data and copy it for the texture
		if (numComp == 1)
		{
			for (int idy = 0; idy < nrows; idy++)
			{
				for (int idx = 0; idx < ncols; idx++)
				{
					// Pixel operation
					int val = inPtr[0];
					val = TP_LimitNum(val, vmin, vmax);
					unsigned char cval = static_cast<unsigned char>(val + 0.5);
					outPtr[0] = cval;
					outPtr[1] = cval;
					outPtr[2] = cval;
					outPtr[3] = alpha;
					outPtr += 4;
					inPtr += inIncX;
				}
			}
		}
		else if (numComp == 2)
		{
			for (int idy = 0; idy < nrows; idy++)
			{
				for (int idx = 0; idx < ncols; idx++)
				{
					// Pixel operation
					int val = inPtr[0];
					val = TP_LimitNum(val, vmin, vmax);
					unsigned char cval = static_cast<unsigned char>(val + 0.5);
					val = inPtr[1];
					val = TP_LimitNum(val, vmin, vmax);
					unsigned char aval = static_cast<unsigned char>(val + 0.5);
					outPtr[0] = cval;
					outPtr[1] = cval;
					outPtr[2] = cval;
					outPtr[3] = aval;
					outPtr += 4;
					inPtr += inIncX;
				}
			}
		}
		else if (numComp == 3)
		{
			for (int idy = 0; idy < nrows; idy++)
			{
				for (int idx = 0; idx < ncols; idx++)
				{
					// Pixel operation
					int r = inPtr[0];
					int g = inPtr[1];
					int b = inPtr[2];
					r = TP_LimitNum(r, vmin, vmax);
					g = TP_LimitNum(g, vmin, vmax);
					b = TP_LimitNum(b, vmin, vmax);
					outPtr[0] = static_cast<unsigned char>(r + 0.5);
					outPtr[1] = static_cast<unsigned char>(g + 0.5);
					outPtr[2] = static_cast<unsigned char>(b + 0.5);
					outPtr[3] = alpha;
					outPtr += 4;
					inPtr += inIncX;
				}
			}
		}
		else // if (numComp == 4)
		{
			for (int idy = 0; idy < nrows; idy++)
			{
				for (int idx = 0; idx < ncols; idx++)
				{
					// Pixel operation
					int r = inPtr[0];
					int g = inPtr[1];
					int b = inPtr[2];
					int a = inPtr[3];
					r = TP_LimitNum(r, vmin, vmax);
					g = TP_LimitNum(g, vmin, vmax);
					b = TP_LimitNum(b, vmin, vmax);
					a = TP_LimitNum(a, vmin, vmax);
					outPtr[0] = static_cast<unsigned char>(r + 0.5);
					outPtr[1] = static_cast<unsigned char>(g + 0.5);
					outPtr[2] = static_cast<unsigned char>(b + 0.5);
					outPtr[3] = static_cast<unsigned char>(a + 0.5);
					outPtr += 4;
					inPtr += inIncX;
				}
			}
		}
	}
}

调用方式

//这里我自己的数据是从vtkImageViewer2中获取到的dcm文件数据,
//即image->GetInput 返回值类型vtkImageData *

vtkImageData *imageData = ...; // 源图像数据
int ncols = imageData->GetDimensions()[0]; // 图像列数(宽)
int nrows = imageData->GetDimensions()[1]; // 图像行数(高)

// 获取原图像数据的灰度值范围
// 如:CT值的单位是Hounsfield,简称为Hu,范围是-1024-3071。用于衡量人体组织对X射线的吸收率,设定水的吸收率为0Hu。
double range[2];
imageData->GetScalarRange(range); 

// 将原图像灰度值调节到0~255范围内,输出为unsigned char(0~255)类型数据(即调节窗宽窗位)
vtkImageShiftScale* shifter = vtkImageShiftScale::New();
shifter->SetShift(-1.0*range[0]); //减去最小值
shifter->SetScale(255.0 / (range[1] - range[0])); //调节比例,灰度换算公式:255*X/(range[1]-range[0])
shifter->SetOutputScalarTypeToUnsignedChar();
shifter->SetInputData(imageData);
shifter->Update();

// 获取原图像component size值,即通道数
int numComp = shifter->GetOutput()->GetScalarSize();

// 申请内存
unsigned char *inPtr = static_cast<unsigned char*>(shifter->GetOutput()->GetScalarPointer()); // 输入,从图像中获取数据指针
unsigned char *outPtr = new unsigned char[nrows * ncols * 4]; // 输出,RGBA共4通道,所以这里乘4
ConvertVtkImageToRGBA(inPtr, outPtr, ncols, nrows, numComp);

// 创建QImage,理论上可以用outPtr创建任意其它类型图像
QImage image = QImage(outPtr, ncols, nrows, QImage::Format_RGB32);
//实现QImage的缩放 公认比较好的方法是,先缩至缩略图4倍大小, 再进一步平滑缩放
QImage img = (*iamge).scaled(640, 480).scaled(200, 200, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);

参考:原作者出处

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值