缩放图片算法优化 sse

news2024/12/25 23:35:46

前情提要
这里实现了打印文件的缩放算法 缩放打印文件(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优化 源数据以及目标数据坐标的计算
即使是这样优化效果也很好
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[PHP]写个简单的分页静态接口用宝塔部署到Nginx

使用get方式传入page和pageSize参数&#xff0c;接口根据参数进行分页处理。 1.创建一个 PHP 文件 例如 city.php&#xff0c;用于定义接口和返回 JSON 数据。 2.在 city.php 文件中编写接口 <?php// 设置响应内容为 JSON 格式 header(Content-Type: application/json);…

iApp祁天社区UI成品源码 功能齐全的社区应用

iApp祁天社区UI成品源码是一个非常实用的资源&#xff0c;提供了完整的源代码&#xff0c;可以帮助您快速搭建一个功能齐全的社区应用。 这个源码具有丰富的UI设计&#xff0c;经过精心调整和优化&#xff0c;确保用户体验流畅而舒适。它不仅具备基本的社区功能&#xff0c;如…

linux清理僵尸进程

当你top看到这个&#xff0c;或者按M后看到内存吃的很多&#xff0c;那你看下有没有&#x1f9df; 二选一查看是什么进程 ps aux | egrep "Z|defunct" ps -aux | awk {if($8"Z"){print $2,$11}}没用直接杀杀杀 kill -9 查到的PID号可中断下载文件 wget…

基于SSM的智慧养老平台设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

OpenCV中的像素重映射原理及实战分析

引言 映射是个数学术语&#xff0c;指两个元素的集之间元素相互“对应”的关系&#xff0c;为名词。映射&#xff0c;或者射影&#xff0c;在数学及相关的领域经常等同于函数。 基于此&#xff0c;部分映射就相当于部分函数&#xff0c;而完全映射相当于完全函数。 说的简单点…

最新计算机网络考试试题分析与整理

博主今天下午刚刚考完试&#xff0c;针对今天计网考试知识点进行整理总结&#xff0c;希望可以对大家有所帮助~ 目录 1.先看简答大题共五道 1.1CRC冗余码计算 1.2tcp拥塞控制 1.3tcp报文段 1.4RIP路由表更新 1.5子网划分 2.再看填空题七道 2.1网络边缘端系统间的通信关…

ClickHouse的表引擎

1 表引擎的使用 表引擎是ClickHouse的一大特色。可以说&#xff0c; 表引擎决定了如何存储表的数据。包括&#xff1a; 数据的存储方式和位置&#xff0c;写到哪里以及从哪里读取数据。支持哪些查询以及如何支持。并发数据访问。索引的使用&#xff08;如果存在&#xff09;。是…

安装最新版IntelliJ IDEA来开发Java应用程序

安装最新版IntelliJ IDEA来开发Java应用程序 Install the Latest Version of IntelliJ IDEA to Develop Java Applications 本文简要介绍如何安装配置JetBrains IntelliJ IDEA集成开发环境&#xff0c;从而开发Java应用程序&#xff1b;文中侧重实际操作和编程步骤&#xff0…

海康Visionmaster-环境配置:VB.Net 二次开发环境配 置方法

Visual Basic 进行 VM 二次开发的环境配置分为三步。 第一步&#xff0c;使用 VS 新建一个框架为.NET Framework 4.6.1&#xff0c;平台去勾选首选 32 为的工程&#xff0c;重新生成解决方案&#xff0c;保证工程 Debug 下存在 exe 文件&#xff0c;最后关闭新建工程&#xff1…

51单片机应用从零开始(五)·加减乘除运算

51单片机应用从零开始&#xff08;一&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;二&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;三&#xff09;-CSDN博客 51单片机应用从零开始&#xff08;四&#xff09;-CSDN博客 详解 KEIL C51 软件的使用建立工程…

2023年05月 Python(六级)真题解析#中国电子学会#全国青少年软件编程等级考试

Python等级考试(1~6级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 明明每天坚持背英语单词,他建立了英语单词错题本文件“mistakes.txt”,将每天记错的单词增加到该文件中,下列打开文件的语句最合适的是?( ) A: f = open(“mistakes.txt”) B: …

基于SSM的学生疫情信息管理系统设计与实现

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用JSP技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

C++打怪升级(十一)- STL之list

~~~~ 前言1. list是什么2. list接口函数的使用1. 构造相关默认构造n个val构造迭代器范围构造拷贝构造 2 赋值运算符重载函数2 析构函数3 迭代器相关begin 和 endrbegin 和rend 4 容量相关emptysize 5 元素访问相关frontback 6 修改相关push_backpop_backpush_frontpop_frontins…

Codewhisperer 使用评价

最近亚⻢逊推出了一款基于机器学习的 AI 编程助手 Amazon CodeWhisperer&#xff0c;可以实时提供代码建议。在编写代码时&#xff0c;它会自动根据现有的代码和注释给出建议。Amazon CodeWhisperer 与GitHub Copilot类似&#xff0c;主要的功能有: 代码补全注释和文档补全代码…

SpringCloud-Gateway修改Response响应体,并解决大数据量返回不全等问题

官网相关案例&#xff1a; Spring Cloud Gatewayhttps://docs.spring.io/spring-cloud-gateway/docs/current/reference/html/#the-modifyresponsebody-gatewayfilter-factory ModifyRequestBodyGatewayFilterFactory类: https://github.com/spring-cloud/spring-cloud-gate…

设计基于STM32F103C8T6微控制器的巡线小车

巡线小车是一种能够在一条预定线追踪路径的小车&#xff0c;广泛应用于工业自动化、物流仓储、智能家居等领域。本设计将使用STM32F103C8T6微控制器来实现一个基础的巡线小车。 硬件组成&#xff1a;1. STM32F103C8T6微控制器开发板&#xff1a;作为巡线小车的核心控制器&…

MFC保存窗口客户区为图片

首先的窗口输出一些内容&#xff1b; 菜单单击函数代码&#xff1b; void CgetmypicView::OnTestGetmypic() {// TODO: 在此添加命令处理程序代码HWND hwnd this->GetSafeHwnd();HDC hDC ::GetWindowDC(hwnd);//获取DC RECT rect;::GetClientRect(hwnd, &rect)…

windows与wsl互传文件

1.把windows上的文件传到wsl中&#xff0c;\\wsl.localhost\Ubuntu-22.04\mnt\wsl 将你要传的文件放到wsl这个路径下&#xff0c;Ubuntu-22.04是我的子系统&#xff0c;换成自己对应的 2.把wsl中的文件传到windows中 将wsl中的文件放到 /mnt/c 或 /mnt/d 中&#xff0c;这两…

ClickHouse SQL操作

基本上来说传统关系型数据库&#xff08;以MySQL为例&#xff09;的SQL语句&#xff0c;ClickHouse基本都支持&#xff0c;这里不会从头讲解SQL语法只介绍ClickHouse与标准SQL&#xff08;MySQL&#xff09;不一致的地方。 1 Insert 基本与标准SQL&#xff08;MySQL&#xff09…

python趣味编程-5分钟实现一个简单贪吃蛇游戏(含源码、步骤讲解)

在本教程《如何用 Python 制作游戏》中,我们将为名为“简单贪吃蛇游戏”的游戏制作一个程序。 Python 中的贪吃蛇游戏:项目信息 项目名称:Python 游戏摘要:Python提供了一个名为pygame的内置库,用于开发游戏。使用的语言:Python 与 Tkinter GUI 库Python版本(推荐):2.…