找不到这段缩放图像代码的异常原因?

loongjourney 2009-06-12 08:43:30
这段代码是在vc 2003环境下缩放图像,但是缩放出现异常,找不到原因。请各位高手给指点指点。
int pixel_width = 4;
void CImgProcessDlg::OnLoadImg()
{
m_MyImage.Load(_T("F:\\54321.jpg"));

DWORD imageWidth = m_MyImage.GetWidth(); //获得图像宽度(像素单位)
DWORD imageHeight = m_MyImage.GetHeight(); //获得图像高度(像素单位)
DWORD pitch = m_MyImage.GetPitch(); //获得图像宽度(以Byte为单位)
BYTE* lpBits = (BYTE*)m_MyImage.GetBits(); //获得图像数据地址

BYTE *lpDIBBits = new BYTE[imageHeight*imageWidth*pixel_width];
memset( lpDIBBits, 0, imageHeight*imageWidth*pixel_width);
//复制图像数据到lpDIBBits;
if(m_MyImage.GetBPP()==24)
{
for (int i = 0; i < imageHeight; i++)
{
for (int j = 0; j < imageWidth; j++)
{
BYTE r, g, b, a;
COLORREF pixel = m_MyImage.GetPixel( j, i);

r = GetRValue(pixel); // 红
g = GetGValue(pixel); // 绿
b = GetBValue(pixel); // 蓝
a = 0; // 透明色

*lpDIBBits++ = r; // 红
*lpDIBBits++ = g; // 绿
*lpDIBBits++ = b; // 蓝
*lpDIBBits++ = a; // 透明色
}
}
}
else
{
::MessageBox(NULL,_T("只能打开8或24位图像!"),NULL,MB_ICONSTOP);
return;
}

DWORD iDestWidth = 600;
DWORD iDestHeight = 800;
byte *dst = new BYTE[iDestWidth*iDestHeight*pixel_width];

// 转换图像
zoom( dst, lpDIBBits, imageWidth, imageHeight, iDestWidth, iDestHeight);

m_DestImg.CreateEx( iDestWidth, iDestHeight, 24, BI_BITFIELDS);

COLORREF pixel;
for( DWORD i = 0; i < iDestHeight; i++)
{
for( DWORD j = 0; j < iDestWidth; j++)
{
pixel = RGB( *dst++, *dst++, *dst++);
dst++; // 透明色
m_DestImg.SetPixel( i, j, pixel);
}
}

m_DestImg.Save( _T("F:\\liuwei.jpg"));

return;
}

/*
dst : 目标缓冲区
src : 来源缓冲区
sw : 来源图像宽度
sh : 来源图像高度
dw : 目标图像宽度
dh : 目标图像高度
*/
void CImgProcessDlg::zoom(byte *dst, byte *src, long sw, long sh, long dw,long dh)
{
assert(dst != 0);
assert(src != 0);
assert(sw > 0 && sh > 0);
assert(dw > 0 && dh > 0);

float scalex = static_cast<float>(sw) / static_cast<float>(dw);
float scaley = static_cast<float>(sh) / static_cast<float>(dh);

long width_bytes = static_cast<long>(sw) * pixel_width;

long *pbyDst = reinterpret_cast<long*>(dst);

for(long i = 0; i < dh; i++)
{
float inverse_y = i * scaley;
long yy = static_cast<long>(inverse_y);
byte *pbySrc = src + yy * width_bytes;

for(long j = 0; j < dw; j++)
{
float inverse_x = j * scalex;

long xx = static_cast<long>(inverse_x);
long* pbyCurrent = reinterpret_cast<long*>(pbySrc + pixel_width * xx);

*pbyDst = *pbyCurrent;

pbyDst++;
}
}
}
...全文
61 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
jtujtujtu 2009-06-15
  • 打赏
  • 举报
回复
错误点:

COLORREF pixel;
for( int m = 0; m < iDestHeight; m++)
{
for( int n = 0; n < iDestWidth; n++)
{
pixel = RGB( *dst++, *dst++, *dst++);
dst++; // 透明色
m_DestImg.SetPixel( n, m, pixel);
}
}

不明白为什么喜欢用这种表达式 —— pixel = RGB( *dst++, *dst++, *dst++);
个人很不喜欢,因为很容易出错,譬如 pixel = RGB( *++dst, *++dst, *++dst); 之类
用在这里都是不正确的
上述两个表达式,楼主可以单步试试结果

正确应为:


COLORREF pixel;
for( int m = 0; m < iDestHeight; m++)
{
for( int n = 0; n < iDestWidth; n++)
{
pixel = RGB( *(dst+2), *(dst+1), *dst);
dst+=4; // 透明色
m_DestImg.SetPixel( n, m, pixel);
}
}
oyljerry 2009-06-15
  • 打赏
  • 举报
回复
这个先检查你的算法是否正确等,这个需要你自己分析
loongjourney 2009-06-15
  • 打赏
  • 举报
回复
发错代码了,是这个
void CImgProcessDlg::OnLoadImg()
{
CImage m_MyImage;
m_MyImage.Load(_T("F:\\54321.jpg"));

DWORD imageWidth = m_MyImage.GetWidth(); //获得图像宽度(像素单位)
DWORD imageHeight = m_MyImage.GetHeight(); //获得图像高度(像素单位)
DWORD pitch = m_MyImage.GetPitch(); //获得图像宽度(以Byte为单位)
BYTE* lpBits = (BYTE*)m_MyImage.GetBits(); //获得图像数据地址

BYTE *lpDIBBits = new BYTE[imageHeight*imageWidth*pixel_width];
memset( lpDIBBits, 0, imageHeight*imageWidth*pixel_width);

int iPos = 0;
//复制图像数据到lpDIBBits;
if(m_MyImage.GetBPP()==24)
{
for (int i = 0; i < imageHeight; i++)
{
for (int j = 0; j < imageWidth; j++)
{
BYTE r, g, b, a;
COLORREF pixel = m_MyImage.GetPixel( j, i);

r = GetRValue(pixel); // 红
g = GetGValue(pixel); // 绿
b = GetBValue(pixel); // 蓝
a = 0; // 透明色

lpDIBBits[iPos] = b;
lpDIBBits[iPos + 1] = g;
lpDIBBits[iPos + 2] = r;
lpDIBBits[iPos + 3] = a;
iPos += 4;
}
}
}
else
{
::MessageBox(NULL,_T("只能打开8或24位图像!"),NULL,MB_ICONSTOP);
return;
}

int iDestWidth = 1024;
int iDestHeight = 768;
byte *dst = new BYTE[iDestWidth*iDestHeight*pixel_width];

// 转换图像
zoom( dst, lpDIBBits, imageWidth, imageHeight, iDestWidth, iDestHeight);

CImage m_DestImg;
DWORD adwBitmasks[3] = { 0x00000000, 0x00000000, 0x00000000};
m_DestImg.CreateEx( iDestWidth, iDestHeight, 24, 0);//, adwBitmasks, 0);

COLORREF pixel;
for( int m = 0; m < iDestHeight; m++)
{
for( int n = 0; n < iDestWidth; n++)
{
pixel = RGB( *dst++, *dst++, *dst++);
dst++; // 透明色
m_DestImg.SetPixel( n, m, pixel);
}
}

m_DestImg.Save( _T("F:\\TestJpg1.jpg"));

return;
}

/*dst : 目标缓冲区src : 来源缓冲区sw : 来源图像宽度sh : 来源图像高度dw : 目标图像宽度dh : 目标图像高度*/
void CImgProcessDlg::zoom(byte *dst, byte *src, long sw, long sh, long dw,long dh)
{
assert(dst != 0);
assert(src != 0);
assert(sw > 0 && sh > 0);
assert(dw > 0 && dh > 0);
// x缩放因子
float scalex = static_cast <float>(sw) / static_cast <float>(dw);
// y缩放因子
float scaley = static_cast <float>(sh) / static_cast <float>(dh);
// 源图像每行字节数
long width_bytes = static_cast <long>(sw) * pixel_width;
// 将dst看作long* (每个*dst相当于4bytes), 此处限制仅用于32bits的图像缩放,不过可以提高缩放速度!
long *pbyDst = reinterpret_cast <long*>(dst);

for(long i = 0; i < dh; i++)
{
// 计算dst中的每一行在源图像中的位置
float inverse_y = i * scaley;
// 取整
long yy = static_cast <long>(inverse_y);
// 获取源图像中此行数据
byte *pbySrc = src + yy * width_bytes;

for(long j = 0; j < dw; j++)
{
// 计算dst中的每一列在源图像中的位置
float inverse_x = j * scalex;
// 取整
long xx = static_cast <long>(inverse_x);
// 获取源图像中对应点的像素值 (long -〉4bits ARGB)
long* pbyCurrent = reinterpret_cast <long*>(pbySrc + pixel_width * xx);
// 赋值
*pbyDst = *pbyCurrent;
// dst中下一个点
pbyDst++;
}
}
}
loongjourney 2009-06-15
  • 打赏
  • 举报
回复
修改 好了,可以任意缩放图像,但是……
缩放后的结果是 黑白色 ……
看来换得继续 发帖, 各位帮指点指点
void CImgProcessDlg::OnLoadImg()
{
CImage m_MyImage;
m_MyImage.Load(_T("F:\\54321.jpg"));

DWORD imageWidth = m_MyImage.GetWidth(); //获得图像宽度(像素单位)
DWORD imageHeight = m_MyImage.GetHeight(); //获得图像高度(像素单位)
DWORD pitch = m_MyImage.GetPitch(); //获得图像宽度(以Byte为单位)
BYTE* lpBits = (BYTE*)m_MyImage.GetBits(); //获得图像数据地址

BYTE *lpDIBBits = new BYTE[imageHeight*imageWidth*pixel_width];
memset( lpDIBBits, 0, imageHeight*imageWidth*pixel_width);

int iPos = 0;
//复制图像数据到lpDIBBits;
if(m_MyImage.GetBPP()==24)
{
for (int i = 0; i < imageHeight; i++)
{
for (int j = 0; j < imageWidth; j++)
{
BYTE r, g, b, a;
COLORREF pixel = m_MyImage.GetPixel( j, i);

r = GetRValue(pixel); // 红
g = GetGValue(pixel); // 绿
b = GetBValue(pixel); // 蓝
a = 0; // 透明色

lpDIBBits[iPos] = pixel;
lpDIBBits[iPos + 1] = g;
lpDIBBits[iPos + 2] = b;
lpDIBBits[iPos + 3] = a;
iPos += 4;
}
}
}
else
{
::MessageBox(NULL,_T("只能打开8或24位图像!"),NULL,MB_ICONSTOP);
return;
}

int iDestWidth = 1024;
int iDestHeight = 768;
byte *dst = new BYTE[iDestWidth*iDestHeight*pixel_width];

// 转换图像
zoom( dst, lpDIBBits, imageWidth, imageHeight, iDestWidth, iDestHeight);

CImage m_DestImg;
DWORD adwBitmasks[3] = { 0x00000000, 0x00000000, 0x00000000};
m_DestImg.CreateEx( iDestWidth, iDestHeight, 24, 0);//, adwBitmasks, 0);

COLORREF pixel;
for( int m = 0; m < iDestHeight; m++)
{
for( int n = 0; n < iDestWidth; n++)
{
pixel = RGB( *dst++, *dst++, *dst++);
dst++; // 透明色
m_DestImg.SetPixel( n, m, pixel);
}
}

m_DestImg.Save( _T("F:\\TestJpg.jpg"));

return;
}

/*dst : 目标缓冲区src : 来源缓冲区sw : 来源图像宽度sh : 来源图像高度dw : 目标图像宽度dh : 目标图像高度*/
void CImgProcessDlg::zoom(byte *dst, byte *src, long sw, long sh, long dw,long dh)
{
assert(dst != 0);
assert(src != 0);
assert(sw > 0 && sh > 0);
assert(dw > 0 && dh > 0);
// x缩放因子
float scalex = static_cast <float>(sw) / static_cast <float>(dw);
// y缩放因子
float scaley = static_cast <float>(sh) / static_cast <float>(dh);
// 源图像每行字节数
long width_bytes = static_cast <long>(sw) * pixel_width;
// 将dst看作long* (每个*dst相当于4bytes), 此处限制仅用于32bits的图像缩放,不过可以提高缩放速度!
long *pbyDst = reinterpret_cast <long*>(dst);

for(long i = 0; i < dh; i++)
{
// 计算dst中的每一行在源图像中的位置
float inverse_y = i * scaley;
// 取整
long yy = static_cast <long>(inverse_y);
// 获取源图像中此行数据
byte *pbySrc = src + yy * width_bytes;

for(long j = 0; j < dw; j++)
{
// 计算dst中的每一列在源图像中的位置
float inverse_x = j * scalex;
// 取整
long xx = static_cast <long>(inverse_x);
// 获取源图像中对应点的像素值 (long -〉4bits ARGB)
long* pbyCurrent = reinterpret_cast <long*>(pbySrc + pixel_width * xx);
// 赋值
*pbyDst = *pbyCurrent;
// dst中下一个点
pbyDst++;
}
}
}
skyxie 2009-06-14
  • 打赏
  • 举报
回复
为什么现在楼主们提问总是喜欢说 ~异常了~出问题了

而就舍不得描述一下到底出了什么问题,有什么异常呢???
jtujtujtu 2009-06-13
  • 打赏
  • 举报
回复
简单分析下

void CImgProcessDlg::zoom(byte *dst, byte *src, long sw, long sh, long dw,long dh)
{
assert(dst != 0);
assert(src != 0);
assert(sw > 0 && sh > 0);
assert(dw > 0 && dh > 0);

float scalex = static_cast <float>(sw) / static_cast <float>(dw); // x缩放因子
float scaley = static_cast <float>(sh) / static_cast <float>(dh); // y缩放因子

long width_bytes = static_cast <long>(sw) * pixel_width; // 源图像每行字节数

long *pbyDst = reinterpret_cast <long*>(dst); // 将dst看作long* (每个*dst相当于4bytes), 此处限制仅用于32bits的图像缩放,不过可以提高缩放速度!

for(long i = 0; i < dh; i++)
{
float inverse_y = i * scaley; // 计算dst中的每一行在源图像中的位置
long yy = static_cast <long>(inverse_y); // 取整
byte *pbySrc = src + yy * width_bytes; // 获取源图像中此行数据

for(long j = 0; j < dw; j++)
{
float inverse_x = j * scalex; // 计算dst中的每一列在源图像中的位置

long xx = static_cast <long>(inverse_x); // 取整
long* pbyCurrent = reinterpret_cast <long*>(pbySrc + pixel_width * xx); // 获取源图像中对应点的像素值 (long -〉4bits ARGB)

*pbyDst = *pbyCurrent; // 赋值

pbyDst++; // dst中下一个点
}
}
}

注意其中的
long* pbyCurrent = reinterpret_cast <long*>(pbySrc + pixel_width * xx); // 获取源图像中对应点的像素值 (long -〉4bits ARGB)
确认你所写的
*lpDIBBits++ = r; // 红
*lpDIBBits++ = g; // 绿
*lpDIBBits++ = b; // 蓝
*lpDIBBits++ = a; // 透明色
顺序是否正确
我记得好像是ARGB的顺序,也就是
*lpDIBBits++ = b; // 蓝
*lpDIBBits++ = g; // 绿
*lpDIBBits++ = r; // 红
*lpDIBBits++ = a; // 透明色
楼主试试 , 或者我记错了, 多试试
tkminigame 2009-06-12
  • 打赏
  • 举报
回复
申明成COLORREF* 更方便。
tkminigame 2009-06-12
  • 打赏
  • 举报
回复
COLORREF pixel = m_MyImage.GetPixel( j, i);

r = GetRValue(pixel); // 红
g = GetGValue(pixel); // 绿
b = GetBValue(pixel); // 蓝
a = 0; // 透明色

*lpDIBBits++ = r; // 红
*lpDIBBits++ = g; // 绿
*lpDIBBits++ = b; // 蓝
*lpDIBBits++ = a; // 透明色

这个不如一开始就申明UINT* lpDIBBits
直接就*lpDIBBits++ = m_MyImage.GetPixel( j, i);

byte *dst = new BYTE[iDestWidth*iDestHeight*pixel_width];
这句很可能有问题。用heapalloc分配内存试试吧。

后面的算法就有点看不懂了,不知道缩放怎么做的,应该用插值吧,有个D3DXColorLerp方法,你试试。

19,464

社区成员

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

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