CImage图像非整数倍放大缩小问题,,高手指点下,谢谢~!

tiankong1399 2008-10-25 01:15:13
下面是程序块,,其中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);
}
...全文
736 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
宅番茄 2011-01-18
  • 打赏
  • 举报
回复
粗略地看了一下,你的j是整数,这样q = j/alpha这一句的除法会按照整数除法运行,这样q的数值就已经是整数了。y1 = (int)q得到的y1数值和q相同。q最后会变成0。p也同理。
这样的话你生成的图像质量会有问题吧?因为双线性插值的系数是错误的,生成的结果图像可能和box filtering差不多?
mexiao 2009-05-22
  • 打赏
  • 举报
回复
不错,谢谢啊!
zgxsdkjdx 2008-10-28
  • 打赏
  • 举报
回复
看了您的程序及修改的内容,深受启发,看来似乎处理的是黑白影像,如果是彩色影像该如何处理呢?恳请指点!非常感谢
tiankong1399 2008-10-26
  • 打赏
  • 举报
回复
谢谢呀~~
laoma_hbu 2008-10-26
  • 打赏
  • 举报
回复
//修改点一:看你的程序我理解nSize的值,应该表示目标图像每行像素所占字节数。
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;//生成二维数组


tiankong1399 2008-10-26
  • 打赏
  • 举报
回复
真的谢谢六楼~~~,我琢磨了几天没琢磨出来,谢谢了~~
不过还是不大明白六楼那三处为何那样子改??
laoma_hbu 2008-10-25
  • 打赏
  • 举报
回复
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 = (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);


我修改了一下,在我这可以运行了。
tiankong1399 2008-10-25
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 hbdycnm 的回复:]
Dx = (int) (alpha * P.nWidth);//计算结果位图宽度
Dy = (int) (alpha * P.nHeight);//计算结果位图高度
//错误可能在这里,当alpha 为0到1之间的时候,你计算出的值将永远为0。

自己一行一行的调试下好了。
[/Quote]

当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。

tiankong1399 2008-10-25
  • 打赏
  • 举报
回复
三楼的改法试过了,不行,缩小时,还是出现相同的问题
hbdycnm 2008-10-25
  • 打赏
  • 举报
回复
Dx = (int) (alpha * P.nWidth + 1);
tiankong1399 2008-10-25
  • 打赏
  • 举报
回复
的确是这两句的问题,但是,要怎么改比较妥当,,请知道的指教~!
hbdycnm 2008-10-25
  • 打赏
  • 举报
回复
Dx = (int) (alpha * P.nWidth);//计算结果位图宽度
Dy = (int) (alpha * P.nHeight);//计算结果位图高度
//错误可能在这里,当alpha 为0到1之间的时候,你计算出的值将永远为0。

自己一行一行的调试下好了。

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧