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