缩放图片算法优化 sse

前情提要
这里实现了打印文件的缩放算法 缩放打印文件(prt,prn)
核心功能如下:

void CZoomPrtFile::zoomPrtFile(BYTE* pTargetData)
{
	float xRatio = static_cast<float>(m_perWidth - 1) / m_zoomWidth;
	float yRatio = static_cast<float>(m_perHeight - 1) / m_zoomHeight;

	int srcX=0, srcY=0;
	int nTargetLineSize = (m_zoomWidth * m_header.nImageColorDeep + 7) / 8;

	BYTE* pSourceLineData = new BYTE[m_header.nBytePerLine];
	for (size_t row = 0; row < m_zoomHeight; row++) 
	{
		srcY = static_cast<int>(yRatio * row);
		for (int ColorNum = 0; ColorNum < m_header.nImageColorNum; ColorNum++)
		{

			memset(pSourceLineData, 0, m_header.nBytePerLine);
			ReadLine(pSourceLineData, srcY * m_header.nImageColorNum + ColorNum, 0, m_header.nBytePerLine);

			for (size_t column = 0; column < m_zoomWidth; column++) 
			{
				srcX = static_cast<int>(xRatio * column);
				// 获取源图像的 bit像素值
				unsigned char srcValue = getPixel(pSourceLineData, srcX, m_header.nImageColorDeep);
				int y = (row * m_header.nImageColorNum + ColorNum) * nTargetLineSize + sizeof(m_header);
				// 设置目标图像的2bit像素值
				setPixel(pTargetData+y,column, srcValue, m_header.nImageColorDeep);
			}
		}
	}

	delete[] pSourceLineData;
}

unsigned char CZoomPrtFile::getPixel(unsigned char* data, int x, int nImageColorDeep)
{
	//unsigned char存储 8/int nImageColorDeep 个 int nImageColorDeep bit像素 ,其中 nImageColorDeep :1,2,4,8 RIP image output bit per color
	int byteIndex = x * nImageColorDeep / 8; // 字节索引
	int bitIndex = (x * nImageColorDeep) % 8; // 位索引

	// 创建掩码
	unsigned char mask = (1 << nImageColorDeep) - 1;
	//std::lock_guard<std::mutex> locker(fileMutex);
	// 位运算提取像素

	unsigned char pixel;
	{ 
		std::lock_guard<std::mutex> locker(fileMutex); 
		pixel = data[byteIndex];
	}
	pixel = (pixel >> bitIndex) & mask;

	return pixel;
}

unsigned char CZoomPrtFile::getPixel(unsigned char data, int x, int nImageColorDeep)
{
	//unsigned char存储 8/int nImageColorDeep 个 int nImageColorDeep bit像素 ,其中 nImageColorDeep :1,2,4,8 RIP image output bit per color
	int byteIndex = x * nImageColorDeep / 8; // 字节索引
	int bitIndex = (x * nImageColorDeep) % 8; // 位索引

	// 创建掩码
	unsigned char mask = (1 << nImageColorDeep) - 1;
	//std::lock_guard<std::mutex> locker(fileMutex);
	// 位运算提取像素
	unsigned char pixel = (data >> bitIndex) & mask;

	return pixel;
}

使用sse 128

void CZoomPrtFile::zoomPrtFileSSE128(BYTE* pTargetData)
{
	const float xRatio = static_cast<float>(m_perWidth - 1) / m_zoomWidth;
	const float yRatio = static_cast<float>(m_perHeight - 1) / m_zoomHeight;

	__m128 xmmRatio = _mm_set1_ps(xRatio);
	__m128 ymmRatio = _mm_set1_ps(yRatio);
	__m128i colorDeep = _mm_set1_epi32(m_header.nImageColorDeep);

	__m128i bitMask = _mm_set1_epi8(0x07);
	unsigned char mask = (1 << m_header.nImageColorNum) - 1;
	__m128i mmMask = _mm_set1_epi32(mask); 
	
	BYTE* pSourceLineData = new BYTE[m_header.nBytePerLine];
	int nTargetLineSize = (m_zoomWidth * m_header.nImageColorDeep + 7) / 8;

	for (int row = 0; row < m_zoomHeight; row++)
	{
		int srcY = static_cast<int>(yRatio * row);

		for (int ColorNum = 0; ColorNum < m_header.nImageColorNum; ColorNum++)
		{
			memset(pSourceLineData, 0, m_header.nBytePerLine);
			ReadLine(pSourceLineData, srcY * m_header.nImageColorNum + ColorNum, 0, m_header.nBytePerLine);

			for (int column = 0; column < m_zoomWidth; column+=4)
			{
				// 加载128位值。返回值代表寄存器的变量中的相同值,地址p不需要16字节对齐。
				__m128i xmmColumn = _mm_setr_epi32(column, column + 1, column + 2, column + 3);
				// 列索引转换为浮点数
				__m128 xmmColumnF = _mm_cvtepi32_ps(xmmColumn);
				// 乘以缩放比例  转换为整数
				__m128i xmmSrcXInt = _mm_cvttps_epi32(_mm_mul_ps(xmmColumnF, xmmRatio));


				//原图
				 xmmSrcXInt = _mm_mullo_epi32(xmmSrcXInt, colorDeep);
				// 方法1:右移三位实现除以8
				__m128i xmmSrcXByteIndex = _mm_srli_epi32(xmmSrcXInt, 3);// 字节索引
				__m128i xmmSrcXBitIndex = _mm_and_si128(xmmSrcXInt, bitMask);// 位索引
				//目标图
				__m128i xmmDesX = _mm_mullo_epi32(xmmColumn, colorDeep);//位索引 
				__m128i xmmDesXByteIndex = _mm_srli_epi32(xmmDesX, 3);// 字节索引
				__m128i xmmDesXBitIndex = _mm_and_si128(xmmDesX, bitMask);// 位索引

				//源数据
				alignas(16) int srcXByteIndex[4];//
				_mm_store_si128((__m128i*)srcXByteIndex, xmmSrcXByteIndex);
				alignas(16) int srcXBitIndex[4];//
				_mm_store_si128((__m128i*)srcXBitIndex, xmmSrcXBitIndex);

				unsigned char pixel[4]{ 
					(pSourceLineData[srcXByteIndex[0]] >> srcXBitIndex[0])& mask,
					(pSourceLineData[srcXByteIndex[1]] >> srcXBitIndex[1])& mask,
					(pSourceLineData[srcXByteIndex[2]] >> srcXBitIndex[2])& mask,
					(pSourceLineData[srcXByteIndex[3]] >> srcXBitIndex[3])& mask
				};
				//目标数据
				int y = (row * m_header.nImageColorNum + ColorNum) * nTargetLineSize + sizeof(m_header);
				BYTE* desDataPointer = pTargetData + y;

				alignas(16) int DesXByteIndex[4];
				_mm_store_si128((__m128i*)DesXByteIndex, xmmDesXByteIndex);
				alignas(16) int DesXBitIndex[4];//
				_mm_store_si128((__m128i*)DesXBitIndex, xmmDesXBitIndex);

				desDataPointer[DesXByteIndex[0]] = (desDataPointer[DesXByteIndex[0]] & ~(mask << DesXBitIndex[0])) |
					((pixel[0] /*& mask*/ ) << DesXBitIndex[0]);
				desDataPointer[DesXByteIndex[1]] = (desDataPointer[DesXByteIndex[1]] & ~(mask << DesXBitIndex[1])) |
					((pixel[1] /*& mask*/) << DesXBitIndex[1]);
				desDataPointer[DesXByteIndex[2]] = (desDataPointer[DesXByteIndex[2]] & ~(mask << DesXBitIndex[2])) |
					((pixel[2] /*& mask*/) << DesXBitIndex[2]);
				desDataPointer[DesXByteIndex[3]] = (desDataPointer[DesXByteIndex[3]] & ~(mask << DesXBitIndex[3])) |
					((pixel[3] /*& mask*/) << DesXBitIndex[3]);
			}
		}
	}

}

本来提取像素和设置像素都应该用sse写的,但是折磨了chatgpt好几天 也没有写出来。
所以这里仅用sse优化 源数据以及目标数据坐标的计算
即使是这样优化效果也很好
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值