最后一个问题了,一个博文《C#双三次插值缩放图像》好象不错,改一下放在这里
好象不能一次三个通道,R、G、B 要放大三次:
//-----------------------------------------------------------------------
//C#双三次插值缩放图像
/// <summary>
/// 双三次插值缩放灰度图像。
/// </summary>
/// <param name="image">源图像。</param>
/// <param name="newWidth">新宽度。</param>
/// <param name="newHeight">新高度。</param>
/// <returns>缩放后的图像。</returns>
static void ResizeGrayscaleImage(IMAGE * P,double ZoomRate )
{
//目标图像,缩放比,
int Pwidth=P->getwidth();
int Pheight=P->getheight();
//分别对原图像获取指针
DWORD* M=GetImageBuffer(P);
//为BiCubic_Zoom函数准备数据
//int m_nBitCount=8*3;
int m_nBitCount=8;
//图像每行像素字节数
int lineByte=(Pwidth*m_nBitCount/8+3)/4*4;
//申请缓冲区,存放后面函数用到的数据格式 输入
unsigned char* r=new unsigned char[lineByte * Pheight]; //R
unsigned char* g=new unsigned char[lineByte * Pheight]; //G
unsigned char* b=new unsigned char[lineByte * Pheight]; //B
DWORD tt;
int pp;
for(int i=0;i<Pheight;i++)
for(int j=0;j<Pwidth;j++)
{
tt=M[j+i*Pwidth];
pp=j+i*lineByte;
r[pp]=GetRValue(tt);
g[pp]=GetGValue(tt);
b[pp]=GetBValue(tt);
}
int newWidth= Pwidth * ZoomRate;
int newHeight = Pheight * ZoomRate;
//返回图像每行像素字节数
int lineByteOut=(newWidth*m_nBitCount/8+3)/4*4;
unsigned char* OutR=new unsigned char[lineByteOut * newHeight];
unsigned char* OutG=new unsigned char[lineByteOut * newHeight];
unsigned char* OutB=new unsigned char[lineByteOut * newHeight];
//这里三个通道分别缩放三次
//ResizeProcess(BitmapData srcData, ref BitmapData dstData)
ResizeProcess(r,Pwidth,Pheight, lineByte,OutR,newWidth, newHeight,lineByteOut);
ResizeProcess(g,Pwidth,Pheight, lineByte,OutG,newWidth, newHeight,lineByteOut);
ResizeProcess(b,Pwidth,Pheight, lineByte,OutB,newWidth, newHeight,lineByteOut);
P->Resize(newWidth, newHeight);
M=GetImageBuffer(P);
Pwidth=P->getwidth();
Pheight=P->getheight();
//lineByte=(Pwidth*m_nBitCount/8+3)/4*4;
for(int i=0;i<Pheight;i++)
for(int j=0;j<Pwidth;j++)
{
pp=j+i*lineByteOut;
M[j+i*Pwidth]=RGB(OutR[pp],OutG[pp+1],OutB[pp+2]);
}
}
/// <summary>
/// 双三次插值处理缩放。
/// </summary>
/// <param name="srcData">源图像数据。</param>
/// <param name="dstData">目标图像数据。</param>
static void ResizeProcess(unsigned char* srcData,int srcWidth,int srcHeight, int srcStride,
unsigned char* dstData,int dstWidth,int dstHeight, int dstStride)
{
// 获取源图像数据
//int srcWidth = srcData.Width;
//int srcHeight = srcData.Height;
//int srcStride = srcData.Stride;
//IntPtr srcPtr = srcData.Scan0;
unsigned char* srcPtr = srcData;
// 获取目标图像数据
//int dstWidth = dstData.Width;
//int dstHeight = dstData.Height;
//int dstStride = dstData.Stride;
int dstOffset = dstStride - dstWidth;
//IntPtr dstPtr = dstData.Scan0;
unsigned char* dstPtr = dstData;
// 计算比例系数
double xFactor = (double)srcWidth / dstWidth;
double yFactor = (double)srcHeight / dstHeight;
// 将源图像数据复制到托管内存中
int srcBytes = srcStride * srcHeight;
byte* srcGrayData = new byte[srcBytes];
//Marshal.Copy(srcPtr, srcGrayData, 0, srcBytes);
memcpy(srcGrayData, srcPtr, srcBytes);
// 保存目标图像数据
int dstBytes = dstStride * dstHeight;
byte* dstGrayData = new byte[dstBytes];
int dst = 0; // 下标
// 源图像坐标点及系数
double ox, oy, dx, dy, k1, k2;
int ox1, oy1, ox2, oy2;
// 目标图像像素值
double grayValue;
// 边界
int ymax = srcHeight - 1;
int xmax = srcWidth - 1;
//#region 插值
for (int y = 0; y < dstHeight; y++)
{
// Y坐标
oy = (double)y * yFactor - 0.5;
oy1 = (int)oy;
dy = oy - (double)oy1;
for (int x = 0; x < dstWidth; x++, dst++)
{
// X坐标
ox = (double)x * xFactor - 0.5f;
ox1 = (int)ox;
dx = ox - (double)ox1;
// 像素值归零
grayValue = 0;
for (int n = -1; n < 3; n++)
{
// Y系数
k1 = BiCubicInterpolator(dy - (double)n);
oy2 = oy1 + n;
if (oy2 < 0)
oy2 = 0;
if (oy2 > ymax)
oy2 = ymax;
for (int m = -1; m < 3; m++)
{
// X系数
k2 = k1 * BiCubicInterpolator((double)m - dx);
ox2 = ox1 + m;
if (ox2 < 0)
ox2 = 0;
if (ox2 > xmax)
ox2 = xmax;
grayValue += k2 * srcGrayData[oy2 * srcStride + ox2];
}
}
dstGrayData[dst] = (byte)max(0, min(255, grayValue));
}
dst += dstOffset;
}
//Marshal.Copy(dstGrayData, 0, dstPtr, dstBytes);
memcpy(dstPtr, dstGrayData, dstBytes);
//#endregion
}
/// <summary>
/// 双三次插值器。
/// coefficient is set to -0.5.
/// </summary>
/// <param name="x">X Value.</param>
/// <returns>Bicubic cooefficient.</returns>
static double BiCubicInterpolator(double x)
{
if (x < 0)
{
x = -x;
}
double biCoef = 0;
if (x <= 1)
{
biCoef = (1.5 * x - 2.5) * x * x + 1;
}
else if (x < 2)
{
biCoef = ((-0.5 * x + 2.5) * x - 4) * x + 2;
}
return biCoef;
}
效果
输入图:
放大图:
重建图:
这个图已经放大了两次,就是9倍,效果好象不明显,再过一次(不放大):
只能这样,看来是不能无限放大的。
本程序已经全部完成了。哈哈