前情提要
这里实现了打印文件的缩放算法 缩放打印文件(prt,prn)
核心功能如下:
void CZoomPrtFile::zoomPrtFile(BYTE* pTargetData) { float xRatio = static_cast
(m_perWidth - 1) / m_zoomWidth; float yRatio = static_cast(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(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(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 locker(fileMutex); // 位运算提取像素 unsigned char pixel; { std::lock_guard 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 locker(fileMutex); // 位运算提取像素 unsigned char pixel = (data >> bitIndex) & mask; return pixel; } 使用sse 128
void CZoomPrtFile::zoomPrtFileSSE128(BYTE* pTargetData) { const float xRatio = static_cast(m_perWidth - 1) / m_zoomWidth; const float yRatio = static_cast(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(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] ) << DesXBitIndex[0]); desDataPointer[DesXByteIndex[1]] = (desDataPointer[DesXByteIndex[1]] & ~(mask << DesXBitIndex[1])) | ((pixel[1] ) << DesXBitIndex[1]); desDataPointer[DesXByteIndex[2]] = (desDataPointer[DesXByteIndex[2]] & ~(mask << DesXBitIndex[2])) | ((pixel[2] ) << DesXBitIndex[2]); desDataPointer[DesXByteIndex[3]] = (desDataPointer[DesXByteIndex[3]] & ~(mask << DesXBitIndex[3])) | ((pixel[3] ) << DesXBitIndex[3]); } } } } 本来提取像素和设置像素都应该用sse写的,但是折磨了chatgpt好几天 也没有写出来。
所以这里仅用sse优化 源数据以及目标数据坐标的计算
即使是这样优化效果也很好
