下面是程序块,,其中alpha为放大缩小倍数,当alpha大于1时,,也就是图像的放大功能可以实现,可是,当alpha在0~1之间时,也就是图像的缩小功能不行,,提示说,堆栈被破坏,或者存在bug....可是放大都可以,缩小时为什么不行,,大家帮忙看看,算法上有没什么不对的。先谢谢了~!inline void ImageScale(CImage *Imgn, CImage *Imgm, double alpha) //非整数倍缩放
{
struct IMAGEPARAMENT P;
RGBQUAD ColorTab[256];
int i, j, nSize;
BYTE **list, *sc;
int Dx, Dy, x1, y1, x2, y2, flag, bpd;
double p, q, a, b, c, d, t1, t2, t3;
if (ImageType(Imgm) == 2) //flag作为标志,当为1时,表示用双线性内插
flag = 1;
else
flag = 0; //为0时,表示用最近邻点法
GetImageParament(Imgm, &P);
Dx = (int) (alpha * P.nWidth);//计算结果位图宽度
Dy = (int) (alpha * P.nHeight);//计算结果位图高度
Imgn -> Destroy();
Imgn ->Create(Dx, Dy, P.nBitCount ); //建立结果位图
bpd = P.nBytesPerPixel;
if (bpd == 1) //256色图像
{
for (i = 0; i < P.nNumColors; i++)
{
GetAllPalette(Imgm, ColorTab);
SetAllPalette(Imgn, ColorTab); //复制调色板
}
}
nSize = (int) ((P.nBytesPerLine + P.nHeight * bpd) * alpha);//计算工作单元大小
sc = (BYTE*) malloc(nSize); //申请像素行工作单元
list = (BYTE**) malloc(Dy * sizeof(BYTE*)); // 申请指针数组
for (i = 0; i < P.nHeight; i++)
list[i] = (BYTE*) Imgm ->GetPixelAddress(0, 0) - i * P.nBytesPerLine;//生成二维数组
for (j = 0; j < Dy; j++)
{
q = j / alpha;
y1 = (int) q;
y2 = y1 + 1;
q = q - y1;
for (i = 0;i < Dx; i++)
{
p = i / alpha;
x1 = (int) p; //x1,y1为整数部分
x2 = x1 + 1;
p = p - x1; //p,q为小数部分
if ((x2 > P.nWidth)||(y2 > P.nHeight )) // 范围检查
continue;
if (x2 == P.nWidth ) x2--;
if (y2 == P.nHeight ) y2--;
if (flag == 0) //flag等于0,采用最近邻点法
{
if (q > 0.5) y1 = y2;
if (p > 0.5) x1 = x2;
memcpy(&sc[i * bpd], &list[y1][x1 * bpd],bpd); //从源位图复制像素数据
}
else
{ // flag等于1,双线性内插法
a = (double) list[y1][x1]; //从源位图取数据
b = (double) list[y1][x2];
c = (double) list[y2][x1];
d = (double) list[y2][x2];
t1 = (1 - p) * a + p * b; //双线性内插计算
t2 = (1 - p) * c + p * d;
t3 = (1 - q) * t1 + q * t2;
sc[i] = (BYTE) t3;
}
}
SetRectValue(Imgn, 0, j, Dx, 1, sc); //处理结果总结果位图
}
free(sc); //释放工作单元
free(list);
}
{
struct IMAGEPARAMENT P;
RGBQUAD ColorTab[256];
int i, j, nSize;
BYTE **list, *sc;
int Dx, Dy, x1, y1, x2, y2, flag, bpd;
double p, q, a, b, c, d, t1, t2, t3;
if (ImageType(Imgm) == 2) //flag作为标志,当为1时,表示用双线性内插
flag = 1;
else
flag = 0; //为0时,表示用最近邻点法
GetImageParament(Imgm, &P);
Dx = (int) (alpha * P.nWidth);//计算结果位图宽度
Dy = (int) (alpha * P.nHeight);//计算结果位图高度
Imgn -> Destroy();
Imgn ->Create(Dx, Dy, P.nBitCount ); //建立结果位图
bpd = P.nBytesPerPixel;
if (bpd == 1) //256色图像
{
for (i = 0; i < P.nNumColors; i++)
{
GetAllPalette(Imgm, ColorTab);
SetAllPalette(Imgn, ColorTab); //复制调色板
}
}
nSize = (int) ((P.nBytesPerLine + P.nHeight * bpd) * alpha);//计算工作单元大小
sc = (BYTE*) malloc(nSize); //申请像素行工作单元
list = (BYTE**) malloc(Dy * sizeof(BYTE*)); // 申请指针数组
for (i = 0; i < P.nHeight; i++)
list[i] = (BYTE*) Imgm ->GetPixelAddress(0, 0) - i * P.nBytesPerLine;//生成二维数组
for (j = 0; j < Dy; j++)
{
q = j / alpha;
y1 = (int) q;
y2 = y1 + 1;
q = q - y1;
for (i = 0;i < Dx; i++)
{
p = i / alpha;
x1 = (int) p; //x1,y1为整数部分
x2 = x1 + 1;
p = p - x1; //p,q为小数部分
if ((x2 > P.nWidth)||(y2 > P.nHeight )) // 范围检查
continue;
if (x2 == P.nWidth ) x2--;
if (y2 == P.nHeight ) y2--;
if (flag == 0) //flag等于0,采用最近邻点法
{
if (q > 0.5) y1 = y2;
if (p > 0.5) x1 = x2;
memcpy(&sc[i * bpd], &list[y1][x1 * bpd],bpd); //从源位图复制像素数据
}
else
{ // flag等于1,双线性内插法
a = (double) list[y1][x1]; //从源位图取数据
b = (double) list[y1][x2];
c = (double) list[y2][x1];
d = (double) list[y2][x2];
t1 = (1 - p) * a + p * b; //双线性内插计算
t2 = (1 - p) * c + p * d;
t3 = (1 - q) * t1 + q * t2;
sc[i] = (BYTE) t3;
}
}
SetRectValue(Imgn, 0, j, Dx, 1, sc); //处理结果总结果位图
}
free(sc); //释放工作单元
free(list);
}
解决方案 »
- 用CWnd::CreateExCWnd创建的窗口的初始位置怎么设定?
- 关于用GDI显示JPEG,PNG的问题
- CArry问题
- 困绕我的一个问题:有关网络通信方面编程的,我老师让我做的一个课题,有知道的或知情的是否能够给我指点一下?可以再加分.
- 找软件开发支持工程师
- 100分,解决后立即揭帖!工具栏中动态创建的Combobox的CBN_SELCHANGE消息函数怎么添加上去的?
- 请问这个编译错误怎么解决?
- 我新建了一个dialog,我想让他在程序一开始出现
- 如何在文档/视图类中使用定时器?
- 谁能详细讲讲用彩图和掩图实现动画的原理和过程
- 怎样获取笔记本内置电池的电压,等参数
- 关于NM_CUSTOMDRAW消息
Dy = (int) (alpha * P.nHeight);//计算结果位图高度
//错误可能在这里,当alpha 为0到1之间的时候,你计算出的值将永远为0。自己一行一行的调试下好了。
当alpha 为0到1之间的时候,为什么计算出的值将永远为0。提示错误有:HEAP[ghgh.exe]: Heap block at 003BF6C8 modified at 003BFE64 past requested size of 794
Windows 已在 ghgh.exe 中触发一个断点。其原因可能是堆被损坏,这也说明 ghgh.exe 中或它所加载的任何 DLL 中有 bug。
RGBQUAD ColorTab[256];
int i, j, nSize;
BYTE **list, *sc;
int Dx, Dy, x1, y1, x2, y2, flag, bpd;
double p, q, a, b, c, d, t1, t2, t3;
if (ImageType(Imgm) == 2) //flag作为标志,当为1时,表示用双线性内插
flag = 1;
else
flag = 0; //为0时,表示用最近邻点法
GetImageParament(Imgm, &P);
Dx = (int) (alpha * P.nWidth);//计算结果位图宽度
Dy = (int) (alpha * P.nHeight);//计算结果位图高度
Imgn -> Destroy();
Imgn ->Create(Dx, Dy, P.nBitCount ); //建立结果位图
bpd = P.nBytesPerPixel;
if (bpd == 1) //256色图像
{
for (i = 0; i < P.nNumColors; i++)
{
GetAllPalette(Imgm, ColorTab);
SetAllPalette(Imgn, ColorTab); //复制调色板
}
}
//修改点一
nSize = (Dx * P.nBitCount + 31) / 32 * 4; //(int) ((P.nBytesPerLine + P.nHeight * bpd) * alpha);//计算工作单元大小
//
sc = (BYTE*) malloc(nSize); //申请像素行工作单元
//修改点二
list = (BYTE**) malloc(P.nHeight * sizeof(BYTE*)); //malloc(Dy * sizeof(BYTE*)); // 申请指针数组
//
//修改点三
for (i = 0; i < P.nHeight; i++)
list[i] = (BYTE*) Imgm->GetPixelAddress(0, i); // ->GetPixelAddress(0, 0) - i * P.nBytesPerLine;//生成二维数组
//
for (j = 0; j < Dy; j++)
{
q = j / alpha;
y1 = (int) q;
y2 = y1 + 1;
q = q - y1;
for (i = 0;i < Dx; i++)
{
p = i / alpha;
x1 = (int) p; //x1,y1为整数部分
x2 = x1 + 1;
p = p - x1; //p,q为小数部分
if ((x2 > P.nWidth)||(y2 > P.nHeight )) // 范围检查
continue;
if (x2 == P.nWidth ) x2--;
if (y2 == P.nHeight ) y2--;
if (flag == 0) //flag等于0,采用最近邻点法
{
if (q > 0.5) y1 = y2;
if (p > 0.5) x1 = x2;
memcpy(&sc[i * bpd], &list[y1][x1 * bpd],bpd); //从源位图复制像素数据
}
else
{ // flag等于1,双线性内插法
a = (double) list[y1][x1]; //从源位图取数据
b = (double) list[y1][x2];
c = (double) list[y2][x1];
d = (double) list[y2][x2];
t1 = (1 - p) * a + p * b; //双线性内插计算
t2 = (1 - p) * c + p * d;
t3 = (1 - q) * t1 + q * t2;
sc[i] = (BYTE) t3;
}
}
SetRectValue(Imgn, 0, j, Dx, 1, sc); //处理结果总结果位图
}
free(sc); //释放工作单元
free(list); 我修改了一下,在我这可以运行了。
nSize = (Dx * P.nBitCount + 31) / 32 * 4; //(int) ((P.nBytesPerLine + P.nHeight * bpd) * alpha);//计算工作单元大小
//
sc = (BYTE*) malloc(nSize);
//修改点二:list应该对应原始图像数据,list[i]应该指向原始图像第i行数据的起始位置。
list = (BYTE**) malloc(P.nHeight * sizeof(BYTE*)); //malloc(Dy * sizeof(BYTE*)); // 申请指针数组
//
//修改点三:如点二说的,list[i]指向图像第i行的起始位置。
for (i = 0; i < P.nHeight; i++)
list[i] = (BYTE*) Imgm->GetPixelAddress(0, i); // ->GetPixelAddress(0, 0) - i * P.nBytesPerLine;//生成二维数组
这样的话你生成的图像质量会有问题吧?因为双线性插值的系数是错误的,生成的结果图像可能和box filtering差不多?