缩放打印文件(prt,prn)

打印机支持的文件为 prt 或者prn

这里介绍如何缩放打印文件

打印文件格式如下:

cpp 复制代码
struct SRipHeader
{
	int		nSignature;			 
	int		nVersion;			 
	int		nImageWidth;		// RIP Image pixel width
	int		nImageHeight;		// RIP Image pixel height

	int		nImageColorNum;		//RIP image Color number include 4 (YMCK) 6 YMCKLcLm 8 YMCKLcLmOrGr

	int		nImageColorDeep;	//1,2,4,8 RIP image output bit per color
	int		nImageResolutionX;	//RIP image X resolution, 180,360,720
	int		nImageResolutionY;	//RIP Image Y resolution, 186,372,558,744

	int		nCompressMode;		// First version should be 0 , no compress mode
	int		nBytePerLine;		//First version used for no compress mode
	int		nBidirection;		// Bidirection for 1, Unidirection for 0
	int		nPass;				//1,2,3,4,6,8,12 Pass

	int		nSpeed;				//High speed 0 Middle speed 1 Low Speed 2

	///Version 2 Change
	unsigned char  nExtraChannel;
	unsigned char  nVSDMode;					//Set VSD Mode for EPSON PrintHead driver
	unsigned char  nEpsonPrintMode;				// High Qulity :0 ,High Speed: 1

	unsigned char	nChannelColorName[16];		//color for each channel
	unsigned char	biCompression;				// whether or not use data compression;0:no Compression;1:RLE4;2:RLE8
	int 			nPreviewImgByteSize;		// If the preview is included, it is the number of bytes in the preview, otherwise it should be 0.
	unsigned char	bPreviewImg;				// Whether it contains a preview;0:no preview;1:bmp(24bit,rgb);
	unsigned char   nReserve[2];				//Fill with 0

	unsigned char  nPrtNum;
	unsigned char  nChannel[4];
};

注意:读文件时,首先需要解析文件头,如上

假设是4色(ymck),位深(nImageColorDeep)为2的打印文件,则文件内容如下:

Y : 00 01 01 10 11 10

M: 11 10 01 11 00 00

C: 00 10 01 00 11 00

K : 00 00 01 00 00 01

也就是说我们看见的图片的每一行对应打印文件的四行,每2位代表一个颜色

图片的宽度为nImageWidth,那么文件这一行的长度为:(nImageWidth * nImageColorDeep+7)/8

因为文件必须为 8位对齐

最邻近算法缩放图片

cpp 复制代码
#pragma once
#include "PrtFile.h"
#include <string>
#include<fstream> 
#include <mutex>
#include "windows.h"

class CZoomPrtFile :
    public CPrtFile
{
public:
	CZoomPrtFile();
	virtual ~CZoomPrtFile();
	bool Open(LPCTSTR szFileName);
	
	virtual void Close();
	virtual int Seek(uint64 pos);
	virtual int Read(void* buf, int size, int count);
	virtual int ReadLine(BYTE* pData, int nLine, int xStart, int nLen);
	virtual void AbortRead();

	void setZoom(size_t zoomWidth, size_t zoomHeight);
	bool saveZoomPrtFile(const std::string& prtFile,size_t zoomWidth, size_t zoomHeight);
	bool saveZoomPrtFile(const std::string& prtFile);
	void zoomPrtFileparallel(BYTE* pTargetData);
	/*void zoomPrtFileThreadProc(BYTE* pTargetData, int ColorNum);*/
	void zoomPrtFileThreadProc(BYTE* pTargetData, int start, int endRow);

private:
	void zoomPrtFile(BYTE* pTargetData);
	unsigned char getPixel(unsigned char* data, int x, int nImageColorDeep);
	void setPixel(unsigned char* data, int x, unsigned char pixel, int nImageColorDeep);
	bool writePrtFile(const std::string& prtFile, unsigned char* data, size_t outDataSize);
	unsigned char getPixel(unsigned char data, int x, int nImageColorDeep);
private:
	FILE* m_fp;
	bool m_bAbort;
	size_t m_zoomWidth;
	size_t m_zoomHeight;
	size_t m_perWidth;
	size_t m_perHeight;


	std::mutex fileMutex; // 文件锁
};

cpp

cpp 复制代码
#include "CZoomPrtFile.h"
#include <Windows.h>
#include<vector>
#include <thread>
#include <chrono>
#include <iostream>
using namespace std;

CZoomPrtFile::CZoomPrtFile() :
	m_fp(NULL),
	m_bAbort(false),
	m_zoomWidth(-1),
	m_zoomHeight(-1)
{
}

CZoomPrtFile::~CZoomPrtFile()
{
	Close();
}

bool CZoomPrtFile::Open(LPCTSTR szFileName)
{
	m_fp = _wfsopen(szFileName, L"rb", _SH_DENYNO);

	if (!m_fp)
	{
		return false;
	}

	if (OpenPrt())
	{
		m_perWidth = m_header.nImageWidth;
		m_perHeight = m_header.nImageHeight;
		return true;
	}
	else
	{
		return false;
	}
}

void CZoomPrtFile::Close()
{
	if (m_fp)
	{
		fclose(m_fp);
		m_fp = NULL;
	}
}

int CZoomPrtFile::Seek(uint64 pos)
{
	return _fseeki64(m_fp, pos, SEEK_SET);
}

int CZoomPrtFile::Read(void* buf, int size, int count)
{
	//std::lock_guard<std::mutex> locker(fileMutex);
	return (int)fread(buf, size, count, m_fp);
}

int CZoomPrtFile::ReadLine(BYTE* pData, int nLine, int xStart, int nLen)
{
	//std::lock_guard<std::mutex> locker(fileMutex);  fseek和fread单独使用线程安全 fseek和fread联合使用需要加锁或者采用临界区
	Seek(sizeof(m_header) + (int64)nLine * m_header.nBytePerLine + xStart);
	Read(pData, 1, nLen);
	return 0;
	while (true)
	{
		if (m_bAbort)
		{
			break;
		}

		if (Seek(sizeof(m_header) + (int64)nLine * m_header.nBytePerLine + xStart) != 0)
		{
			Sleep(10);

			continue;
		}

		if (Read(pData, 1, nLen) != nLen)
		{
			Sleep(10);

			continue;;
		}
		else
		{
			return nLen;
		}
	}

	return 0;
}

void CZoomPrtFile::AbortRead()
{
	m_bAbort = true;
}



void CZoomPrtFile::setZoom(size_t zoomWidth, size_t zoomHeight)
{
	 m_zoomWidth = zoomWidth;
	 m_zoomHeight = zoomHeight;
}
bool CZoomPrtFile::saveZoomPrtFile(const std::string& prtFile,size_t zoomWidth, size_t zoomHeight)
{
	m_zoomWidth = zoomWidth;
	m_zoomHeight = zoomHeight;
	return saveZoomPrtFile(prtFile);
}

bool CZoomPrtFile::saveZoomPrtFile(const std::string& prtFile)
{
	// Get Start Time
	std::chrono::system_clock::time_point start = std::chrono::system_clock::now();
	bool ok = false;

	if (m_zoomWidth > 1 && m_zoomHeight > 1 && m_fp)
	{
		int nTargetLineByteSize = (m_zoomWidth * m_header.nImageColorDeep + 7) / 8;
		int nTargetDataSize = sizeof(m_header) + nTargetLineByteSize * m_header.nImageColorNum * m_zoomHeight;
		BYTE* pTargetData = new BYTE[nTargetDataSize];
		memset(pTargetData, 0, nTargetDataSize);
		SRipHeader zoomHeader(m_header);
		zoomHeader.nImageHeight = m_zoomHeight;
		zoomHeader.nImageWidth = m_zoomWidth;
		zoomHeader.nBytePerLine = nTargetLineByteSize;
		memcpy(pTargetData, &zoomHeader, sizeof(zoomHeader));

		zoomPrtFile(pTargetData);

		//zoomPrtFileparallel(pTargetData);

		ok=writePrtFile(prtFile, pTargetData, nTargetDataSize);
		delete[] pTargetData;
		// Get End Time
		auto end = std::chrono::system_clock::now();
		auto diff = std::chrono::duration_cast <std::chrono::milliseconds> (end - start).count();
		std::cout << prtFile<<" . Total Time Taken = " << diff << " milliseconds" << " . Total size = " << m_header.nBytePerLine* m_header.nImageHeight * m_header.nImageColorNum + sizeof(m_header) << "byte" 
			" . target file size = " << zoomHeader.nBytePerLine * zoomHeader.nImageHeight * zoomHeader.nImageColorNum + sizeof(zoomHeader) << std::endl;
	}
	return ok;
}


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;
}
void CZoomPrtFile::zoomPrtFileparallel(BYTE* pTargetData)
{
	std::vector<std::thread> threadPool;
	int threadNum = 8;
	int step = m_zoomHeight / threadNum;
	for (int i = 0; i < threadNum -1; i++)
	{
		threadPool.push_back(std::thread(&CZoomPrtFile::zoomPrtFileThreadProc, this, pTargetData, i* step,(i+1)* step));
	}

	zoomPrtFileThreadProc(pTargetData, (threadNum - 1) * step, m_zoomHeight);
	for (int i = 0; i < threadNum - 1; i++)
	{
		threadPool[i].join();
	}
}

void CZoomPrtFile::zoomPrtFileThreadProc(BYTE* pTargetData, int start, int endRow)
{
	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 = start; row < endRow; 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像素值
				int byteIndex = srcX * m_header.nImageColorDeep / 8; // 字节索引

				unsigned char srcValue = getPixel(pSourceLineData[byteIndex], 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;
}
//
//void CZoomPrtFile::zoomPrtFileThreadProc(BYTE* pTargetData, int ColorNum)
//{
//	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);
//		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);
//			// 设置目标图像的2bit像素值
//			int y = (row * m_header.nImageColorNum + ColorNum)* nTargetLineSize + sizeof(m_header);
//			setPixel(pTargetData+y, column, srcValue, m_header.nImageColorDeep);
//		}
//	}
//	delete[] pSourceLineData;
//	return;
//}

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;
}

void CZoomPrtFile::setPixel(unsigned char* data,int x, unsigned char pixel, int nImageColorDeep)
{
	
	//int y = (int64)nLine * nTargetLineSize + sizeof(m_header);
	int byteIndex = x * nImageColorDeep / 8;//在第y行的byte的位置
	int bitIndex = (x * nImageColorDeep) % 8;

	// 创建掩码 
	unsigned char mask = (1 << nImageColorDeep) - 1;
	// 清空原像素
	
	unsigned char temp = data[byteIndex];
	temp &= ~(mask << bitIndex);
	temp |= (pixel & mask) << bitIndex;
	//std::lock_guard<std::mutex> locker(fileMutex);
	data[byteIndex] = temp;
	//data[byteIndex] &= ~(mask << bitIndex);

	 设置新像素  
	//data[ byteIndex] |= (pixel & mask) << bitIndex;

}

bool CZoomPrtFile::writePrtFile(const std::string& prtFile, unsigned char* data, size_t outDataSize)
{
	if (data == nullptr) {
		return false;
	}
	//Write file
	std::ofstream outFile;
	outFile.open(prtFile, std::ofstream::binary);
	if (!outFile.is_open()) {
		return false;
	}
	for (size_t i = 0; i < outDataSize; i++) {
		outFile << data[i];
	}
	outFile.close();
	return true;

}

main

cpp 复制代码
#include "CZoomPrtFile.h"
#include <iostream>
#include <fstream>
#include"base.h"
using namespace std;

void test()
{
	std::ifstream ifs("D:\\doc\\prt\\1111111.prn");
	if (!ifs.is_open())
	{
		return;
	}
	ifs.seekg(0, ios_base::end);  //先把文件输入流指针定位到文档末尾来获取文档的长度
	int length = ifs.tellg();

	cout << " 1111111.prn size is " << length << endl;
}

int main()
{
	test();
	CZoomPrtFile zoomPrtFile;
	zoomPrtFile.Open(L"D:\\doc\\prt\\1111111.prn");

	cout << " test 单线程"<< endl;
	zoomPrtFile.saveZoomPrtFile("D:\\doc\\prt\\1111111Zoom05.prn", 3259 * 0.5, 4605 * 0.5);
	zoomPrtFile.saveZoomPrtFile("D:\\doc\\prt\\1111111Zoom08.prn", 3259 * 0.8, 4605 * 0.8); 
	zoomPrtFile.saveZoomPrtFile("D:\\doc\\prt\\1111111Zoom15.prn", 3259 * 1.5, 4605 * 1.5);
	zoomPrtFile.saveZoomPrtFile("D:\\doc\\prt\\1111111Zoom20.prn", 3259 * 2, 4605 * 2);
	return 0;
}

 /*
 处理的速度要到至少500MB/S 

 test 多线程 8个线程
D:\doc\prt\1111111Zoom05.prn . Total Time Taken = 769 milliseconds . source size = 26303844 byte  target file size = 6574596, 
D:\doc\prt\1111111Zoom08.prn . Total Time Taken = 1738 milliseconds . source size = 26303844 byte  target file size = 16813860
D:\doc\prt\1111111Zoom15.prn . Total Time Taken = 5812 milliseconds . source size = 26303844 byte  target file size = 59082562
D:\doc\prt\1111111Zoom20.prn . Total Time Taken = 10308 milliseconds . source size = 26303844 byte  target file size = 105086184 
test 单线程
D:\doc\prt\1111111Zoom05.prn . Total Time Taken = 1926 milliseconds . source size = 26303844 byte . target file size = 6574596
D:\doc\prt\1111111Zoom08.prn . Total Time Taken = 4626 milliseconds . source size = 26303844 byte . target file size = 16813860
D:\doc\prt\1111111Zoom15.prn . Total Time Taken = 16128 milliseconds . source size = 26303844 byte . target file size = 59082562
D:\doc\prt\1111111Zoom20.prn . Total Time Taken = 28593 milliseconds . source size = 26303844 byte . target file size = 105086184
	         
 */


 
相关推荐
倔强的石头1069 分钟前
【C++指南】类和对象(九):内部类
开发语言·c++
A懿轩A1 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
机器视觉知识推荐、就业指导1 小时前
C++设计模式:享元模式 (附文字处理系统中的字符对象案例)
c++
半盏茶香1 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
Ronin3052 小时前
11.vector的介绍及模拟实现
开发语言·c++
✿ ༺ ོIT技术༻2 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
字节高级特工2 小时前
【C++】深入剖析默认成员函数3:拷贝构造函数
c语言·c++
唐诺9 小时前
几种广泛使用的 C++ 编译器
c++·编译器
冷眼看人间恩怨10 小时前
【Qt笔记】QDockWidget控件详解
c++·笔记·qt·qdockwidget
红龙创客10 小时前
某狐畅游24校招-C++开发岗笔试(单选题)
开发语言·c++