这段代码是在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++;
}
}
}

解决方案 »

  1.   

    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方法,你试试。
     
      

  2.   

    简单分析下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;  // 透明色 
    楼主试试 , 或者我记错了, 多试试
      

  3.   

    修改 好了,可以任意缩放图像,但是……
    缩放后的结果是 黑白色 ……
    看来换得继续 发帖, 各位帮指点指点
    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++; 
    }

    }
      

  4.   

    发错代码了,是这个
    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++; 
    }

    }
      

  5.   

    错误点: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);