缩放图片算法优化 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优化 源数据以及目标数据坐标的计算
即使是这样优化效果也很好
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/153868.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

YOLOv3 学习记录

文章目录 简介整体介绍整体架构图 网络架构的改进Backbone 的改进FPNAnchor 机制 坐标表示与样本匹配目标边界框的预测正负样本匹配 损失函数 简介 关注目标在哪里 目标是什么 目标检测的发展路径&#xff1a; proposal 两阶段 --> anchor-base/ anchor-free --> nms f…

深度学习之基于YoloV5安检仪危险品识别系统

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 深度学习之基于 YOLOv5 安检仪危险品识别系统介绍YOLOv5 简介安检仪危险品识别系统系统架构应用场景 二、功能三、系统四. 总结 一项目简介 深度学习之基于…

自动化网络图软件

由于 IT 系统的发展、最近向混合劳动力的转变、不断变化的客户需求以及其他原因&#xff0c;网络监控变得更加复杂。IT 管理员需要毫不费力地可视化整个网络基础设施&#xff0c;通过获得对网络的可见性&#xff0c;可以轻松发现模式、主动排除故障、确保关键设备可用性等。 为…

计算机视觉的应用17-利用CrowdCountNet模型解决人群数量计算问题(pytorch搭建模型)

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下计算机视觉的应用17-利用CrowdCountNet模型解决人群数量计算问题(pytorch搭建模型)。本篇文章&#xff0c;我将向大家展示如何使用CrowdCountNet这个神奇的工具&#xff0c;以及它是如何利用深度学习技术来解决复杂…

《增长黑客》思维导图

增长黑客这个词源于硅谷&#xff0c;简单说&#xff0c;这是一群以数据驱动营销、以迭代验证策略&#xff0c;通过技术手段实现爆发式增长的新型人才。 近年来&#xff0c;互联网公司意识到这一角色可以发挥四两拨千斤的作用&#xff0c;因此对该职位的需求也如井喷式增长。本…

营业执照识别

目录 1、制作文本检测数据集 2、导出文本检测推理模型 3、制作语义实体识别数据集 4、训练模型 5、模型预测 6、模型导出 7、模型推理 1、制作文本检测数据集 文本检测数据集格式如下&#xff1a; dataset_dir # 数据集根目录&#xff0c;目录名称可以改变 ├── im…

【广州华锐互动】VR模拟真实火灾场景,教你如何正确逃生和自救

随着科技的不断发展&#xff0c;人们对于安全教育的需求也在不断提高。在消防安全领域&#xff0c;传统的培训方式已经无法满足现代社会的需求。为了提高人们的消防安全意识&#xff0c;提升应急处理能力&#xff0c;VR火灾自救逃生体验系统应运而生。 VR火灾自救逃生体验系统是…

金蝶云星空其他出库单保存提示序列号不一致

文章目录 金蝶云星空其他出库单保存提示序列号不一致保存报错初步分析总结 金蝶云星空其他出库单保存提示序列号不一致 保存报错 显示单据数量0.序列号数量3 初步分析 输入实发数量没有触发序列号数量的计算 检查实发数量的值更新事件 实发数量和序列号数量的转换&#xff…

我把MySQL运行在Docker上,差点完了……

容器的定义&#xff1a;容器是为了解决“在切换运行环境时&#xff0c;如何保证软件能够正常运行”这一问题。 目前&#xff0c;容器和 Docker 依旧是技术领域最热门的词语&#xff0c;无状态的服务容器化已经是大势所趋&#xff0c;同时也带来了一个热点问题被大家所争论不以&…

LeetCode【41】缺失的第一个正数

题目&#xff1a; 分析&#xff1a; 第i个位置的数&#xff0c;如果再数组 0到length-1范围内&#xff0c;则将其放到对应的位置&#xff1b; 再遍历一遍数组&#xff0c;找到第一个不在位置i的正数数字&#xff0c;即为所求 思路&#xff1a;https://blog.csdn.net/weixin_45…

【docker启动的Jenkins时,遇到时区问题处理】

1、查看容器中的时区 [rootlocalhost jenkins]# docker exec -it jenkins cat /etc/timezone Etc/UTC而本地使用的是Asia/shanghai [rootlocalhost jenkins]# timedatectl | grep Time zoneTime zone: n/a (CST, 0800)###查看 [rootlocalhost jenkins]# cd /usr/share/zoneinf…

代码随想录算法训练营|五十五天

两个字符串的删除操作 583. 两个字符串的删除操作 - 力扣&#xff08;LeetCode&#xff09; 因为两个字符串都能删除&#xff0c;所以字符不匹配的话就有三个方向取最小值赋值给dp[i,j]&#xff0c;不过这里dp[i-1,j-1]2dp[i,j-1]1&#xff0c;从字面上理解 就是 当 同时删wo…

软件外包开发文档工具

有许多工具可用于生成和管理软件开发文档。这些工具可以帮助团队更有效地协作、记录和维护文档。以下是一些常用的软件开发文档生成工具&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&#xff0c;欢迎交流合作。 Javadoc&#…

软件测试面试-如何定位线上出现bug

其实无论是线上还是在测试出现bug&#xff0c;我们核心的还是要定位出bug出现的原因。 定位出bug的步骤&#xff1a; 1&#xff0c;如果是必现的bug&#xff0c;尽可能的复现出问题&#xff0c;找出引发问题的操作步骤。很多时候&#xff0c;一个bug的产生&#xff0c;很多时…

GBase8a-GDCA-第二次阶段测试

文章目录 主要内容在这里插入图片描述 ![在这里插入图片描述](https://img-blog.csdnimg.cn/1d552b9d6d204f4fb4280ccc52807ed5.png)在这里插入图片描述 总结 主要内容 GBase8a-GDCA-第二次阶段测试及答案 总结 以上是今天要讲的内容&#xff0c;GBase8a-GDCA-第二次阶段测试…

字母不重复的子串-第15届蓝桥第二次STEMA测评Scratch真题精选

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第158讲。 第15届蓝桥第2次STEMA测评已于2023年10月29日落下帷幕&#xff0c;编程题一共有6题&#xff0c;分别如下&am…

矩阵起源到此一游:千岛湖(内含海量招聘岗位)

秋意渐浓&#xff0c;正值金秋时节&#xff0c;MO 也出去玩啦&#xff01; 海量招聘岗位&#xff0c;点击链接一键查看&#xff0c;就等您来&#xff1a; 「矩阵起源招聘」2023年矩阵起源招聘信息-BOSS直聘​www.zhipin.com/gongsi/job/59a68fecfe392c0d1nd93N-4EVU~.html​编…

放松鸭-技术支持

“放松鸭”利用苹果手表的HRV心率变异性和静息心率等数据进行分析&#xff0c;帮助您了解当前身体疲劳和心理压力程度&#xff0c;并及时提醒您的压力状态。我们的目标是让您更好地感知、管理和应对压力&#xff0c;让您的身心得到平静和放松。通过读取您的心脏数据&#xff0c…

MySQL数据库入门到大牛_基础_08__聚合函数(常用的5种聚合函数;GROUP BY分组;HAVING使用及与WHERE的对比;SELECT的执行过程)

我们上一章讲到了 SQL 单行函数。实际上 SQL 函数还有一类内置函数&#xff0c;叫做聚合&#xff08;或聚集、分组&#xff09;函数&#xff0c;它是对一组数据进行汇总的函数&#xff0c;输入的是一组数据的集合&#xff0c;输出的是单个值。即使输出多个值&#xff0c;也得作…

嵌套的iframe页面中rem字号变小问题处理

问题原因 如果 html 的 font-size: 100px&#xff0c;那字号为0.16rem的字实际为100px * 0.16 16px 故最外层的html的字号 与iframe下的html字号 不相同时&#xff0c;则会导致iframe页面内的字体字号存在问题 解决办法 先获取外层html的font-size const fontSize par…