纯代码实现png图片的读取,png与bmp互转,读取图片像素矩阵,通过矩阵运算实现图片转灰度图,缩放等功能,并将处理后数据导出为png和bmp

该代码实现了一个从PNG二进制数据流中读取像素矩阵,处理图像,并将矩阵数据转为PNG格式导出的功能。它使用zlib库进行解压缩和压缩,包含了解码PNG的IDAT块、滤波重建、BMP读取以及图像灰度化和缩放的方法。此外,还提供了循环冗余码计算和滤波算法的实现。
摘要由CSDN通过智能技术生成

 以下是源代码 pictureMat.h,用于学习实现从png数据流中读取像素矩阵,用于处理图片,再将矩阵数据转为png导出成图片,  需要依赖库zlib,zlib官网 ,png滤波算法可见 点击此处

目录

1 大致结构

2 初始化 

3 读取二进制数据 

3.1 读取png

 3.1.1 解压代码

 3.1.2 滤波重建 

 3.2 读取BMP

4 保存

4.1 保存为png

4.1.2 循环冗余码

4.1.3 滤波

4.1.4 压缩代码

5 将图像转为灰度图

6 图像缩放


1 大致结构

#pragma comment(lib,"zlibd.lib")
#include<stdio.h>
#include<iostream>
#include<iomanip>
#include<vector>
#include <zlib.h>
#include <assert.h>
#include<math.h>
#include<sys/timeb.h>
#define PI 3.1415926535
using namespace std;

class PictureMat
{
	
public:

	char format[3] = {0};
	int offset=3;
	int Width;
	int realWidth;
	int Height;
	char BitDepth=8;
	char ColorType=2;
	unsigned char* bytearray;//原始数据
	unsigned long datalen;//原始数据长度
	vector<unsigned char>IHDRs;
	vector<unsigned char>others;
	vector<int>IDATlen;
	vector <vector<unsigned char>> IDATs;//原始IDAT数据
	vector<unsigned char>title;
	vector<unsigned char>IENDs;
	//Matrix<unsigned char> mat();
	unsigned char*mat;
	PictureMat() {};
	PictureMat(unsigned char* bytestream, const unsigned long& datalen) :bytearray(bytestream), datalen(datalen)
	{
		
		

	}

	void LoadFromBMP() 
	{
		
	}
	~PictureMat()
	{
		
		
		
	}
	//转为灰度图
	void rgb2gray()
	{
		
	}


	

	//图像缩放
	void scale(const int&newWidth,const int&newHeight,const int &method)
	{
		
	}
	//以bmp格式保存在数据流中
	void save2bmp(vector<unsigned char>&outdata)
	{
		
		
	}

	//以png格式保存在二进制数据流中
	void save(vector<unsigned char>&outdata)
	{
		
		
	};


	void compress_zlib(unsigned char* outbuf, unsigned long outbufLen, unsigned char* inbuf, unsigned long inbuflen)
	{
		int res=compress(outbuf, &outbufLen, inbuf, inbuflen);
		cout << "compress message: " << res << endl;
	}
	void uncompress_zlib(unsigned char* outbuf, unsigned long outbufLen, unsigned char* inbuf, unsigned long inbuflen)
	{
		int res = uncompress(outbuf, &outbufLen, inbuf, inbuflen);
		cout << "uncompress message: " << res << endl;
	}
	

	void inflate_zlib(unsigned char* outbuf, unsigned long outbufLen, unsigned char* inbuf, unsigned long inbuflen,int fmt)
	{
		
	}
	size_t deflate_zlib(unsigned char* outbuf, size_t outbufLen, unsigned char* inbuf, unsigned long inbuflen,int fmt)
	{
		

	}

	void filter(unsigned char* buf, unsigned long buflen)
	{
		
	}

	bool isTableComputed = 0;
	unsigned int crc_table[256];
	//计算循环冗余 4字节
	unsigned int crc(unsigned char* buf, int len)
	{
		return update_crc(0xffffffff, buf, len) ^ 0xffffffff;
	}
	unsigned int update_crc(unsigned int crc, unsigned char* buf, int len)
	{
		
	}
	void make_crc_table(void)
	{
		
	}

};

2 初始化 

PictureMat() {};
PictureMat(unsigned char* bytestream, const unsigned long& datalen) :bytearray(bytestream), datalen(datalen)
{
		
	if (bytearray[1] == 'P' && bytearray[2] == 'N' && bytearray[3] == 'G')LoadFromPNG();
	else if (bytearray[0] == 'B' && bytearray[1] == 'M')LoadFromBMP();
}

3 读取二进制数据 

3.1 读取png

有时,png的idat数据块会保存为若干个,此时需要把各个idat数据块拼接到一起,才能得到完整的数据。(各个idat数据块的开头 XXXXIDAT 和结尾循环冗余 XXXX 需要去除)

void LoadFromPNG()
	{
		
		vector<unsigned char> idat_chunk;
		bool startWrite = false;
		int k = 0;

		
		/*初始化,从二进制数据中载入PNG的长、宽、位深度、颜色类型*/
		Width = ((bytearray[18] % 0x100) << 8) + (bytearray[19] + 0x100) % 0x100;
		Height = (((bytearray[22] + 0x100) % 0x100) << 8) + (bytearray[23] + 0x100) % 0x100;
		BitDepth = bytearray[24];
		ColorType = bytearray[25];
	

		for (int i = 0; i < 3; i++)format[i] = bytearray[i + 1];
		//cout << strcmp(format, "PG") << endl;
		cout << (int)Width << " " << (int)Height << " " << (int)BitDepth << " " << (int)ColorType << endl;
		int i = 0x20;
		while (1)
		{
			others.push_back(bytearray[i]);
			if (bytearray[i] == 'I' && bytearray[i + 1] == 'D' && bytearray[i + 2] == 'A' && bytearray[i + 3] == 'T')
			{
				for (int j = 0; j < 5; j++)others.pop_back();
				break;
			}
			i++;
			if (i >= datalen)break;
		}

		/*根据颜色类型决定实际的图像宽度*/
		switch (ColorType)
		{
		case 0:
			realWidth = Width; break;
		case 2:
			realWidth = Width * 3;
			offset = 3;
			break;
		case 3:
			realWidth = Width * 3; break;
		case 4:
			realWidth = Width; break;
		case 6:
			realWidth = Width * 4;
			offset = 4;
			break;
		default:
			realWidth = Width;
			offset = 2;
			break;
		}
		for (int i = 0; i < 8; i++)title.push_back(bytearray[i]);
		for (int i = 8; i < 29; i++)IHDRs.push_back(bytearray[i]);
		int temp = 0;
		/*寻找IDAT数据块,并载入到 IDATs 的链表中*/
		for (int i = 0; i < datalen; i++)
		{


			if (bytearray[i] == 'I' && bytearray[i + 1] == 'D' && bytearray[i + 2] == 'A' && bytearray[i + 3] == 'T')
			{



				temp = ((int)(bytearray[i - 1] % 0x100) + ((int)bytearray[i - 2] << 8) + ((int)bytearray[i - 3] << 16) + ((int)bytearray[i - 4] << 24));
				//temp -= 4;

				IDATlen.push_back(temp);


				//i += 4;
				//i -= 4;
				startWrite = true;
				k = 0;


				//cout << str << endl;
			}

			if (startWrite && k < temp)
			{
				idat_chunk.push_back(bytearray[i + 4]);
				k++;

			}
			else if (startWrite && k >= temp)
			{
				IDATs.push_back(idat_chunk);
				idat_chunk.clear();
				startWrite = false;
			}


		}

		cout << "IDAT_chunks: " << IDATs.size() << endl;
		unsigned long outdatalen = (realWidth + 1) * Height;

		mat = (unsigned char*)malloc(sizeof(unsigned char) * outdatalen);

		vector<unsigned char> inbuf;
		for (int i = 0; i < IDATs.size(); i++)
		{
			for (int j = 0; j < IDATlen[i]; j++)
			{
				inbuf.push_back(IDATs[i][j]);
			}
		};


		cout << "inbuf: " << inbuf.size() << " outdatalen: " << outdatalen << endl;
		
		inflate_zlib(mat, outdatalen, inbuf.data(), inbuf.size(),0);//解压

		reconstruction(mat, outdatalen);//重建
		//show(bytearray,0, datalen);
		//show(mat, 0, outdatalen);

	}

 3.1.1 解压代码

输出的数据长度可以确定,就是图像的(宽 * 通道数量+1字节的滤波器标识符)* 高,

输入数据的长度,idat首4字节就告诉你长度了,如果有多块,就全加起来。

void inflate_zlib(unsigned char* outbuf, unsigned long outbufLen, unsigned char* inbuf, unsigned long inbuflen,int fmt)
	{
		z_stream strm;
		int err;
		strm.zalloc = (alloc_func)Z_NULL;
		strm.zfree = (free_func)Z_NULL;
		strm.opaque = (voidpf)Z_NULL;
		strm.next_in = inbuf;
		strm.avail_in = inbuflen;
		strm.next_out = outbuf;
		strm.avail_out = outbufLen;
		int restoreLen;
		switch (fmt)
		{
		case 0:
			// zlib
			err = inflateInit(&strm);
			assert(Z_OK == err);

			err = inflate(&strm, Z_FINISH);
			assert(err == Z_STREAM_END);

			restoreLen = strm.total_out;

			err = inflateEnd(&strm);
			break;
		case 1:
			// gzip
			err = inflateInit2(&strm, MAX_WBITS + 16);
			assert(Z_OK == err);

			err = inflate(&strm, Z_FINISH);
			assert(err == Z_STREAM_END);

			err = inflateEnd(&strm);
			break;
		case 2:
			// raw
			err = inflateInit2(&strm, MAX_WBITS * -1);
			assert(Z_OK == err);

			err = inflate(&strm, Z_FINISH);
			assert(err == Z_STREAM_END);

			err = inflateEnd(&strm);
			break;
		default:
			break;
		}
		
	}

 3.1.2 滤波重建 

个人理解滤波是为了留下更多重复的数据,以便进行压缩

void reconstruction(unsigned char* buf, unsigned long buflen)
	{
		int temp;
		int p;
		int pa;
		int pb;
		int pc;

		int a;
		int b;
		int c;
		for (int i = 0; i < Height; i++)
		{
			for (int j = 1 + offset; j < realWidth + 1; j += offset)
			{
				switch (buf[i * (realWidth + 1)])
				{
				case 1:
					for (int k = 0; k < offset; k++)
						buf[j + i * (realWidth + 1) + k] += buf[j + i * (realWidth + 1) - offset + k];
					break;
				case 2:
					if (j == 1 + offset)
						for (int k = 0; k < offset; k++)
							buf[j + i * (realWidth + 1) + k - offset] += buf[j - offset + (i - 1) * (realWidth + 1) + k];
					for (int k = 0; k < offset; k++)
						buf[j + i * (realWidth + 1) + k] += buf[j + (i - 1) * (realWidth + 1) + k];
					break;
				case 3:
					if (j == 1 + offset)
						for (int k = 0; k < offset; k++)
							buf[j + i * (realWidth + 1) + k - offset] += buf[j - offset + (i - 1) * (realWidth + 1) + k] / 2;
					for (int k = 0; k < offset; k++)
						buf[j + i * (realWidth + 1) + k] += (buf[j + (i - 1) * (realWidth + 1) + k] +
							buf[j + i * (realWidth + 1) - offset + k]) / 2;
					break;
				case 4:

					if (j == 1 + offset)
						for (int k = 0; k < offset; k++)
							buf[j + i * (realWidth + 1) + k - offset] += buf[j - offset + (i - 1) * (realWidth + 1) + k];
					for (int k = 0; k < offset; k++)
					{
						a = buf[j + i * (realWidth + 1) - offset + k];
						b = buf[j + (i - 1) * (realWidth + 1) + k];
						c = buf[j + (i - 1) * (realWidth + 1) - offset + k];
						p = a + b - c;
						pa = abs(p - a);
						pb = abs(p - b);
						pc = abs(p - c);
						if (pa <= pb && pa <= pc)temp = a;
						else if (pb <= pc)temp = b;
						else temp = c;

						buf[j + i * (realWidth + 1) + k] +=temp;
					}
					break;
				default:
					break;
				}

			}
		};

	}

 3.2 读取BMP

没什么好解释的,仅仅就是数据上下方向与png相反,rgb变成了bgr,横向像素方向不变。

void LoadFromBMP() 
	{
		format[0] = 'B'; format[1] = 'M'; format[2] = 'P';

		Width = (int)bytearray[18]  + ((int)bytearray[19] << 8) + ((int)bytearray[20] << 16) + ((int)bytearray[21] << 24);
		Height= (int)bytearray[22]  + ((int)bytearray[23] << 8) + ((int)bytearray[24] << 16) + ((int)bytearray[25] << 24);
		realWidth = 3 * Width;
		int bmpSize = bytearray[2] + ((int)bytearray[3]<<8) + ((int)bytearray[4]<<16)+((int)bytearray[5]<24);
		int dataSize= bytearray[34] + ((int)bytearray[35] << 8) + ((int)bytearray[36] << 16) + ((int)bytearray[37] < 24);
		cout << "Width: " << Width << " Height: " << Height << " bmpSize: " << bmpSize << " dataSize: "<<dataSize << endl;
		dataSize--;

		//if(realWidth*Height>3000)show(bytearray, 0, 300);
		//vector<unsigned char>datas;
		//for(int i=0;i<dataSize;i++)datas
		int lineOffset = realWidth%4!=0 ? 4 - realWidth % 4 : 0;
		cout << "lineOffset " << lineOffset << endl;
		int dataOffset = 54;

		timeb timeSeed;
		ftime(&timeSeed);
		srand(timeSeed.time*1000+timeSeed.millitm);

		mat = (unsigned char*)malloc(sizeof(unsigned char) * (realWidth + 1) * Height);
		
		//将bmp像素数据以png格式存储在矩阵中
		for (int i = 0; i < Height; i++)
		{
			if (i == 0)
				mat[i * (realWidth + 1)] = 1;
			else
				mat[i * (realWidth + 1)] = rand() % 3 + 2;
			for (int j = 0; j < Width; j++)
			{
				for (int k = 0; k < offset; k++)
				{
					//cout << 1 + k + j * offset + i * (realWidth + 1) << " " << (offset - k - 1) + j * offset + (Height - i-1) * (realWidth + lineOffset) << endl;
					mat[1 + k + j * offset + i * (realWidth + 1)] = bytearray[dataOffset + (offset - k - 1) + j * offset + (Height - i - 1) * (realWidth + lineOffset)];

				}

			}

		}


	};

4 保存

4.1 保存为png

先滤波,再压缩,最后分块,不能忘记再每个块的开头添加XXXXIDAT(XXXX代表数据块长度),结尾添加XXXX(循环冗余码,4字节)。(当然也可一整块)

//以png格式保存在二进制数据流中
	void save(vector<unsigned char>&outdata)
	{
		
		unsigned char PNGhead[8] = { 0x89,'P','N','G',0xd,0xa,0x1a,0xa }; for (unsigned char x : PNGhead)outdata.push_back(x); 
		unsigned char IHDRsizeAndName[8] = { 0,0,0,0xd,0x49,0x48,0x44,0x52 }; for (unsigned char x : IHDRsizeAndName)outdata.push_back(x); 
		unsigned char widthAndHeight[8]; for (int i = 0; i < 4; i++)widthAndHeight[i] = (Width >> ((3 - i) * 8)); for (int i = 0; i < 4; i++)widthAndHeight[i + 4] = (Height >> ((3 - i) * 8)); for (unsigned char x : widthAndHeight)outdata.push_back(x); 
		unsigned char bD_cType_cMethod_fMethod_iMethod[5] = { BitDepth,ColorType,0,0,0 }; for (unsigned char x : bD_cType_cMethod_fMethod_iMethod)outdata.push_back(x);
		int crc_IHDRs = crc(outdata.data() + 12, outdata.size() - 12);
		for (int i = 0; i < 4; i++)outdata.push_back(crc_IHDRs >> ((3-i)* 8));

		int outdatalen = (realWidth + 1) * Height;
		
	
		filter(mat, outdatalen);//滤波

		unsigned char* outidat = (unsigned char*)malloc(sizeof(unsigned char) * outdatalen );
		cout << outdatalen << endl;
	
		size_t outLen = deflate_zlib(outidat, outdatalen , mat, outdatalen, 0);
		cout << outLen << endl;
		
		
		vector<unsigned char>outidat_with_head;


		
		
#ifdef METHOD
		
		int lenCount = 10;
		int len = outLen / lenCount;
		for (int i = 0; i < lenCount; i++)
		{
			outidat_with_head.clear();
			
			//if (i == lenCount -1)len = outLen % lenCount;
			
			

			for (int j = 0; j < 4; j++)outdata.push_back(len >> (24 - j * 8));
			outidat_with_head.push_back('I'); outidat_with_head.push_back('D'); outidat_with_head.push_back('A'); outidat_with_head.push_back('T');
			for (int j = 0; j < len; j++)outidat_with_head.push_back(outidat[j+i*len]);
			int crc_IDATs = crc(outidat_with_head.data(), outidat_with_head.size());
			for (unsigned char x : outidat_with_head)outdata.push_back(x);
			for (int j = 0; j < 4; j++)outdata.push_back(crc_IDATs >> (24 - j * 8));

			
			
		}
#endif





		unsigned char IENDs[12] = { 0,0,0,0,'I','E','N','D',0xae ,0x42,0x60,0x82 }; for (auto x : IENDs)outdata.push_back(x);
		free(outidat);
		outidat = nullptr;
		//show(outdata.data(), 0, outdata.size());

	};

4.1.2 循环冗余码

其实zlib库里面有原装的,之前不知道,就在网上找了

unsigned int crc_table[256];
unsigned int crc(unsigned char* buf, int len)
{
	return update_crc(0xffffffff, buf, len) ^ 0xffffffff;
}
unsigned int update_crc(unsigned int crc, unsigned char* buf, int len)
{
	unsigned int c = crc;
	int i;

	if (!isTableComputed)make_crc_table();
	for (i = 0; i < len; i++)
		c = crc_table[(c ^ buf[i]) & 0xff] ^ (c >> 8);
	return c;
}
void make_crc_table(void)
{
	unsigned long c;
	int i, j;

	for (i = 0; i < 256; i++)
	{
		c = (unsigned long)i;
		for (j = 0; j < 8; j++)
		{
			if (c & 1)
				c = 0xedb88320 ^ (c >> 1);
			else
				c >>= 1;
			//cout << c << endl;
		}
		crc_table[i] = c;
	}
	isTableComputed = 1;
}

4.1.3 滤波

	void filter(unsigned char* buf, unsigned long buflen)
	{
		int temp;
		int p;
		int pa;
		int pb;
		int pc;
		int a;
		int b;
		int c;
		//倒着算,可以节约空间,具体规范可去 https://www.w3.org/TR/2022/WD-png-3-20221025/#13Filtering
		for (int i = Height-1; i >-1; i--)
		{
			for (int j =realWidth; j > offset; j -= offset)
			{
				switch (buf[i * (realWidth + 1)])
				{
				case 1:
					for (int k = 0; k < offset; k++)
						buf[j + i * (realWidth + 1) - k] -= buf[j + i * (realWidth + 1) - offset - k];
					break;
				case 2:
					for (int k = 0; k < offset; k++)
						buf[j + i * (realWidth + 1) - k] -= buf[j + (i - 1) * (realWidth + 1) - k];
					if (j == 2 * offset)
						for (int k = 0; k < offset; k++)
							buf[j - offset + i * (realWidth + 1) - k] -= buf[j - offset + (i - 1) * (realWidth + 1) - k];
					break;
				case 3:
					for (int k = 0; k < offset; k++)
						buf[j + i * (realWidth + 1) - k] -=(buf[j + (i - 1) * (realWidth + 1) - k]+ buf[j + i * (realWidth + 1) - offset - k]) / 2;
					if (j == 2 * offset)
						for (int k = 0; k < offset; k++)
							buf[j - offset + i * (realWidth + 1) - k] -= buf[j - offset + (i - 1) * (realWidth + 1) - k] / 2;
					break;
				case 4:
					for (int k = 0; k < offset; k++)
					{
						a = buf[j + i * (realWidth + 1) - offset - k];
						b = buf[j + (i - 1) * (realWidth + 1) - k];
						c = buf[j + (i - 1) * (realWidth + 1) - offset - k];
						p = a + b - c;
						pa = abs(p - a);
						pb = abs(p - b);
						pc = abs(p - c);
						if (pa <= pb && pa <= pc)temp = a;
						else if (pb <= pc)temp = b;
						else temp = c;

						buf[j + i * (realWidth + 1) - k] -=temp;
					}
					if (j == 2*offset)
						for (int k = 0; k < offset; k++)
							buf[j - offset + i * (realWidth + 1) - k] -= buf[j - offset + (i - 1) * (realWidth + 1) - k];
					break;
				default:
					break;
				}

			}
		};

	}

4.1.4 压缩代码

设置输出的数据长度要足够大,一般不会超过输入数据的长度,但保险起见,还是大一点吧。

    size_t deflate_zlib(unsigned char* outbuf, size_t outbufLen, unsigned char* inbuf, unsigned long inbuflen,int fmt)
	{
		//压缩代码,
		z_stream strm;
		int err;
		size_t outLen;
		strm.zalloc = (alloc_func)Z_NULL;
		strm.zfree = (free_func)Z_NULL;
		strm.opaque = (voidpf)Z_NULL;

		strm.next_in = inbuf;
		strm.avail_in = inbuflen;
		strm.next_out = outbuf;
		strm.avail_out = outbufLen;

		switch (fmt)
		{
		case 0:
			// zlib
			err = deflateInit(&strm, Z_DEFAULT_COMPRESSION);
			assert(Z_OK == err);

			err = deflate(&strm, Z_FINISH);
			assert(err == Z_STREAM_END);

			outLen = strm.total_out;

			err = deflateEnd(&strm);
			break;
		case 1:
			// gzip
			err = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY);
			assert(Z_OK == err);

			err = deflate(&strm, Z_FINISH);
			assert(err == Z_STREAM_END);

			outLen = strm.total_out;

			err = deflateEnd(&strm);
			break;
		case 2:
			// raw
			err = deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS * -1, 8, Z_DEFAULT_STRATEGY);
			assert(Z_OK == err);

			err = deflate(&strm, Z_FINISH);
			assert(err == Z_STREAM_END);

			outLen = strm.total_out;

			err = deflateEnd(&strm);
			break;
		default:
			break;
		}


		return outLen;
	}

5 将图像转为灰度图

原图(png 或 bmp都可以,png可以3通道或4通道):

结果:

 代码:

这里取的权值都是0.33

	//转为灰度图
	void rgb2gray()
	{
		int offset_ = offset;
		if (ColorType == 6)offset_--;
		for (int i = 0; i < Height; i++)
		{
			
			for (int j = 1; j < realWidth+1; j+=offset)
			{
				unsigned char temp=0;
				for (int k = 0; k < offset_; k++)
				{
					temp += mat[j + i * (realWidth + 1) + k] * 0.33;
				}
					//temp = 10;
					
				
				for (int k = 0; k < offset_; k++)
					mat[j + i * (realWidth + 1) + k] = temp;
				
			}
		}
	}

6 图像缩放

放大:

将此图片下载到电脑上可以可以正常显示,可能是图片太大了

 缩小:

代码:

void scale(const int&newWidth,const int&newHeight,const int &method)
	{
		cout << offset << endl;
		
		unsigned char* newMat = (unsigned char*)malloc(sizeof(unsigned char) * (newWidth* offset +1) * newHeight);
		//for (int i = 0; i < newHeight; i++)for (int j = 0; j < (newWidth * offset + 1); j++)newMat[j + i * (newWidth * offset + 1)] = 0;
		int preX = 0;
		int nextX = 0;

		int preY = 0;
		int nextY = 0;
		int temp;

		switch (method)
		{
		case 0://最近邻插值法(Nearest Neighbour Interpolation)
			for (int i = 0; i < newHeight; i++)
			{
				int j;
				int k;
				
				newMat[i * (newWidth * offset + 1)] = mat[i * Height / newHeight * (realWidth + 1)];
				
				for (j = 0; j < newWidth; j++)
					for (k = 0; k < offset; k++)
						if (mat != nullptr)
						{
							newMat[1 + j * offset + k + i * (newWidth * offset + 1)] = mat[1 + j * Width / newWidth * offset + k + i * Height / newHeight * (realWidth + 1)];
							//cout << j * Width / newWidth << endl;
						}
			}
			break;

		case 1://一元一次拉格朗日插值

			//横向插值
			if(Height<newHeight)
				for (int i = 0; i < Height; i++)
				{

					newMat[i * newHeight / Height * (newWidth * offset + 1)] = mat[i * (realWidth + 1)];
					for (int j = 0; j < Width; j++)
					{
						nextX = j * newWidth / Width;
						for (int k = 0; k < offset; k++)
						{
							temp = newMat[1 + (j * newWidth / Width * offset) + k + (i * newHeight / Height) * (newWidth * offset + 1)] = mat[1 + j * offset + k + i * (realWidth + 1)];
#ifndef BILINEAR				
							if (nextX - preX > 1)
							{
								for (int m = 0; m < nextX - preX - 1; m++)
								{
									int t = temp * m / (newWidth / Width) + newMat[1 + ((j - 1) * newWidth / Width) * offset + k + i * newHeight / Height * (newWidth * offset + 1)] * (m - newWidth / Width) / (-newWidth / Width);
									newMat[1 + ((j - 1) * newWidth / Width + m + 1) * offset + k + i * newHeight / Height * (newWidth * offset + 1)] = t;
								}
							}
#endif
						}
						
						preX = nextX;
					}
					int blank = newWidth - (Width - 1) * newWidth / Width;
					if (blank != 0)
					{
						
						for (int j = 1; j < blank+1; j++)
						{
							for (int k = 0; k < offset; k++)
							{
								newMat[1 + k + ((Width - 1) * newWidth / Width + j) * offset + i * newHeight / Height * (newWidth * offset + 1)] =
								newMat[1 + k + ((Width - 1) * newWidth / Width + j-1) * offset + i * newHeight / Height * (newWidth * offset + 1)];
							}
						}
					}


				}

			else
				for (int i = 0; i < newHeight; i++)
				{
					newMat[i * (newWidth * offset + 1)] = mat[i * Height/newHeight*(realWidth + 1)];

					for (int j = 0; j < Width; j++)
					{
						nextX = j * newWidth / Width;
						for (int k = 0; k < offset; k++)
						{
							temp = newMat[1 + j * newWidth / Width * offset + k + i  * (newWidth * offset + 1)] = mat[1 + j * offset + k + i * Height / newHeight*(realWidth + 1)];
							if (nextX - preX > 1)
							{
								for (int m = 0; m < nextX - preX - 1; m++)
								{
									int t = temp * m / (newWidth / Width) + newMat[1 + ((j - 1) * newWidth / Width) * offset + k + i  * (newWidth * offset + 1)] * (m - newWidth / Width) / (-newWidth / Width);
									newMat[1 + ((j - 1) * newWidth / Width + m + 1) * offset + k + i * (newWidth * offset + 1)] = t;
								}
							}
						}
						preX = nextX;
					}

				}
			
			

			//纵向插值
			for (int i = 0; i < newWidth * offset + 1; i++)
			{
				for (int j = 0; j < Height; j++)
				{
					nextY = j * newHeight / Height;
#ifndef BILINEAR2
					if (nextY - preY > 1)
					{
						temp = newMat[1 + j * newHeight / Height * (newWidth * offset + 1) + i];

						for (int m = 0; m < nextY - preY; m++)
						{
							int t = temp * m / (newHeight / Height) + newMat[1 + (j - 1) * newHeight / Height * (newWidth * offset + 1) + i] * (m - newHeight / Height) / (-newHeight / Height);
							newMat[1 + ((j - 1) * newHeight / Height + m + 1) * (newWidth * offset + 1) + i] = t;
						}
					}
#endif
					preY = nextY;
				}
				int blank = newHeight - (Height - 1) * newHeight / Height;
				if (blank != 0)
				{
					
					for (int j = 0; j < blank ; j++)
					{
						newMat[1 + ((Height - 1) * newHeight / Height+j) * (newWidth * offset + 1) + i] = 
						newMat[1 + ((Height - 1) * newHeight / Height+j-1) * (newWidth * offset + 1) + i];
					}
				}
			}
			break;
		default:
			break;
		}
		mat= (unsigned char*)realloc(newMat,sizeof(unsigned char) * (newWidth * offset + 1) * newHeight);
		Width = newWidth;
		Height = newHeight;
		realWidth = newWidth * offset;
	}

以下是main运行文件

int main()
{
    ifstream ifs;
	//ifs.open("tip.png",ios::out|ios::ate|ios::binary);
	ifs.open("C://Users//Administrator//Desktop//madchen.png", ios::out | ios::ate | ios::binary);
	if (ifs.is_open())
	{
		unsigned char* str;
		unsigned long size = ifs.tellg();

		str = new unsigned char[size];


		ifs.seekg(0, ios::beg);
		ifs.read((char*)str, size);
		cout << size << endl;


		
		PictureMat mat(str,size);

		//mat.rgb2gray();
		mat.scale(1080, 2000,2);
		
		
		vector<unsigned char> pngdata;
#ifndef SAVE2PNG
		mat.save(pngdata);
		ofstream ofs;
		ofs.open("C://Users//Administrator//Desktop//mypng.png", ios::out| ios::binary);
#endif
#ifdef SAVE2BMP
		mat.save2bmp(pngdata);
		ofstream ofs;
		ofs.open("C://Users//Administrator//Desktop//mybmp.bmp", ios::out| ios::binary);
#endif
		for (unsigned char x : pngdata)ofs << x;
		ofs.close();

;
	}
	ifs.close();
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值