现在急需一个vc6.0下面的dib缩放的函数,但是因为以前对图形处理不太熟悉,所以请教各位了。
找到一个vc.net的代码,不过在vc6.0无法通过编译,如何通过一些修改使其在vc6.0下工作?HDIB ChangeDIBSize(HDIB hDIB, int nWidth, int nHeight)
{
    LPBITMAPINFO  lpbmi = NULL;
    LPBYTE         lpSourceBits, lpTargetBits, lpResult;
    HDC           hDC = NULL, hSourceDC, hTargetDC;
    HBITMAP        hSourceBitmap, hTargetBitmap,
  hOldTargetBitmap, hOldSourceBitmap;
    DWORD           dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize;
    HDIB          hNewDIB;
    DWORD        dwSize;     WaitCursorBegin();     // Get DIB pointer
    if (! hDIB)
    {
        WaitCursorEnd();
        return NULL;
    }    LPBITMAPINFO lpSrcDIB = (LPBITMAPINFO)GlobalLock(hDIB);
    if (! lpSrcDIB)
    {
        WaitCursorEnd();
        return NULL;
    }     // Allocate and fill out a BITMAPINFO struct for the new DIB    dwTargetHeaderSize = sizeof( BITMAPINFOHEADER ) +PaletteSize(lpSrcDIB);    lpbmi = (LPBITMAPINFO)malloc( dwTargetHeaderSize );    memcpy(lpbmi, lpSrcDIB, dwTargetHeaderSize);    lpbmi->bmiHeader.biWidth = nWidth;    lpbmi->bmiHeader.biHeight = nHeight;     // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em    hDC = GetDC( NULL );    hTargetBitmap = CreateDIBSection( hDC, lpbmi,DIB_RGB_COLORS, (VOID **)&lpTargetBits, NULL, 0 );    hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB,DIB_RGB_COLORS, (VOID **)&lpSourceBits, NULL, 0 );    hSourceDC = CreateCompatibleDC( hDC );    hTargetDC = CreateCompatibleDC( hDC );     // Flip the bits on the source DIBSection to match the source DIB    dwSourceBitsSize = lpSrcDIB->bmiHeader.biHeight *BytesPerLine((LPBYTE)&(lpSrcDIB->bmiHeader));    dwTargetBitsSize = lpbmi->bmiHeader.biHeight *BytesPerLine((LPBYTE)&(lpbmi->bmiHeader));    memcpy( lpSourceBits, FindDIBBits((LPBYTE)lpSrcDIB), dwSourceBitsSize );    lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;     // Select DIBSections into DCs    hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );    hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );     // put old bitmap in new bitmap    SetStretchBltMode( hTargetDC, COLORONCOLOR );    StretchBlt( hTargetDC, 0, 0,lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight,hSourceDC, 0, 0,lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight,SRCCOPY );     // Clean up and delete the DCs    SelectObject( hSourceDC, hOldSourceBitmap );    SelectObject( hTargetDC, hOldTargetBitmap );
    DeleteDC( hSourceDC );
    DeleteDC( hTargetDC );
    ReleaseDC( NULL, hDC );     // Flush the GDI batch, so we can play with the bits
    GdiFlush();    // Allocate enough memory for the new CF_DIB, and copy bits    dwSize = dwTargetHeaderSize + dwTargetBitsSize;
    hNewDIB = GlobalAlloc(GHND, dwSize);
    lpResult = (LPBYTE)GlobalLock(hNewDIB);
    memcpy( lpResult, lpbmi, dwTargetHeaderSize );
    memcpy( FindDIBBits( (LPBYTE)lpResult ), lpTargetBits, dwTargetBitsSize );
 
    // final cleanup    DeleteObject( hTargetBitmap );
    DeleteObject( hSourceBitmap );
    free( lpbmi );
    GlobalUnlock(hDIB);
    GlobalUnlock(hNewDIB);
    WaitCursorEnd();
    return hNewDIB;}

解决方案 »

  1.   

    另外,我只需对256色灰度图进行缩放处理,利用 SetStretchBlt有没有问题?
      

  2.   

    对DIB缩放还是自己写算法比较合适:
    下面这个是我写的使用双二次线性插值的图像缩放函数:#ifdef __cplusplus
    extern "C"{
    #endif#define SIZING_BY_PROPORTION           0   //根据比例缩放图像
    #define SIZING_BY_SIZE                 1   //根据给定的新尺寸缩放图像typedef struct tagImageData{
        DWORD dwWidth;
        DWORD dwHeight;
        LPBYTE lpData32;
    }IMAGEDATA,*PIMAGEDATA;typedef struct tagProcessData{
        DWORD dwSize;       // 结构尺寸
        DWORD dwProcType;   // 处理类型
        HWND  hParent;      // 主窗口
        DWORD dwPara1;      // 参数1
        DWORD dwPara2;      // 参数2
        DWORD dwPara3;      // 参数3
        DWORD dwPara4;      // 参数4
        LPVOID lpVoid;      // 附加数据指针
    } PROCESSDATA,*PPROCESSDATA;
    DWORD WINAPI Mirror(IN  PIMAGEDATA dataIn,
                               IN  PPROCESSDATA dataProc,
                               OUT PIMAGEDATA dataOut); 
    DWORD WINAPI Rote(IN  PIMAGEDATA dataIn,
                             IN  PPROCESSDATA dataProc,
                             OUT PIMAGEDATA dataOut); 
    DWORD WINAPI Scale(IN  PIMAGEDATA dataIn,
                                  IN  PPROCESSDATA dataProc,
                                  OUT PIMAGEDATA dataOut); 
    #ifdef __cplusplus
    };
    #endif
    __inline int Bound(int x,int min,int max)
    {
        return (x<min)?min:(x>max)?max:x;
    }
    double SinXpX(double x)
    {
        double absx = fabs(x);
        double xx = absx * absx;
        double xxx = xx * absx;
        if(absx < 1.0) return 1.0 - 2.0 * xx + xxx;
        else if(absx < 2.0) return 4.0 - 8.0 * absx + 5.0 * xx - xxx;
        else return 0.0;
    }
    DWORD WINAPI Scale(IN  PIMAGEDATA dataIn,
                       IN  PPROCESSDATA dataProc,
                       OUT PIMAGEDATA dataOut)
    {
        if(dataIn->lpData32 == NULL || dataIn->dwHeight<=0 || dataIn->dwWidth<=0)
            return -1;
        DWORD dwLineBytes = dataIn->dwWidth * 4;
        DWORD dwLen = dwLineBytes * dataIn->dwHeight;
        if(IsBadReadPtr(dataIn->lpData32,dwLen)) return -1;
        // Old Image Size    // New Image Size
        switch(dataProc->dwProcType){
        case SIZING_BY_PROPORTION:
            dataOut->dwWidth  = (dataIn->dwWidth  * dataProc->dwPara1 + 50) / 100;
            dataOut->dwHeight = (dataIn->dwHeight * dataProc->dwPara2 + 50) / 100;
            break;
        case SIZING_BY_SIZE:
            dataOut->dwWidth = dataProc->dwPara1;
            dataOut->dwHeight = dataProc->dwPara2;
            break;
        default:
            return -1;
        }
        DWORD dwOutLineBytes = dataOut->dwWidth * 4;
        DWORD dwOutLen = dwOutLineBytes * dataOut->dwHeight;    // malloc memory for image data
        try{
            dataOut->lpData32 = new BYTE[dwOutLen];
        }catch(CMemoryException*pe){
            pe->ReportError();
            return -1;
        }    // calc new image pixel value (Use Three Order Interpolate)
        float fScaleX = (float) dataIn->dwWidth / (float) dataOut->dwWidth;
        float fScaleY = (float) dataIn->dwHeight / (float) dataOut->dwHeight;
        
        LPBYTE pOut = dataOut->lpData32;    for(DWORD dwy = 0;dwy<dataOut->dwHeight;++dwy){
            float fInvY = dwy * fScaleY;
            int iy = (int)fInvY;
            float fv = fInvY - iy;        LPBYTE pInLineHead = dataIn->lpData32 + iy * dwLineBytes;        for(DWORD dwx = 0;dwx<dataOut->dwWidth;++dwx){
                float fInvX = dwx * fScaleX;
                int ix = (int)fInvX;
                float fu = fInvX - ix;            LPBYTE pIn = pInLineHead + ix * 4;            //  Three Order Interpolate
                // Get 16 Pixel near the point(fInvX,fInvY).
                int xx[4],yy[4];
                
                xx[0] = -1; xx[1] = 0; xx[2] = 1; xx[3] = 2;
                yy[0] = -1; yy[1] = 0; yy[2] = 1; yy[3] = 2;            if((ix - 1) < 0)                     xx[0] = 0;
                if((ix + 1) > (int)(dataIn->dwWidth - 1)) xx[2] = 0;
                if((ix + 2) > (int)(dataIn->dwWidth - 1)) xx[3] = (xx[2] == 0)?0:1;            if((iy - 1) < 0)                      yy[0] = 0;
                if((iy + 1) > (int)(dataIn->dwHeight - 1)) yy[2] = 0;
                if((iy + 2) > (int)(dataIn->dwHeight - 1)) yy[3] = (yy[2] == 0)?0:1;            // Src pixel value
                BYTE red[4][4],green[4][4],blue[4][4];            int i,j;
                for(i = 0; i < 4; ++i){
                    LPBYTE pBaseLine = pIn + yy[i] * dwLineBytes;
                    for(j = 0; j < 4; ++j){
                        LPBYTE pBase = pBaseLine + xx[j] * 4;
                        red  [i][j] = *pBase++;
                        green[i][j] = *pBase++;
                        blue [i][j] = *pBase++;
                    }
                }            // u,v vector
                float afu[4],afv[4];
                afu[0] = (float)SinXpX(1.0 + fu); afv[0] = (float)SinXpX(1.0 + fv);
                afu[1] = (float)SinXpX(fu);       afv[1] = (float)SinXpX(fv);
                afu[2] = (float)SinXpX(1.0 - fu); afv[2] = (float)SinXpX(1.0 - fv);
                afu[3] = (float)SinXpX(2.0 - fu); afv[3] = (float)SinXpX(2.0 - fv);            float afr[4] = {0.0f, 0.0f, 0.0f, 0.0f};
                float afg[4] = {0.0f, 0.0f, 0.0f, 0.0f};
                float afb[4] = {0.0f, 0.0f, 0.0f, 0.0f};            for(i = 0; i < 4; ++i){
                    for(j = 0; j < 4; ++j){
                        afr[i] += afv[j] * red[j][i];
                        afg[i] += afv[j] * green[j][i];
                        afb[i] += afv[j] * blue[j][i];
                    }
                }            // New pixel value
                *pOut++ = (BYTE)Bound(
                      (int)(afu[0] * afr[0] + afu[1] * afr[1] +
                            afu[2] * afr[2] + afu[3] * afr[3] + 0.5f),0,255);
                *pOut++ = (BYTE)Bound(
                      (int)(afu[0] * afg[0] + afu[1] * afg[1] +
                            afu[2] * afg[2] + afu[3] * afg[3] + 0.5f),0,255);
                *pOut++ = (BYTE)Bound(
                      (int)(afu[0] * afb[0] + afu[1] * afb[1] +
                            afu[2] * afb[2] + afu[3] * afb[3] + 0.5f),0,255);
                *pOut++ = (BYTE)0;        }
        }    return 0;
    }
      

  3.   

    谢谢你。我看见有帖子说256色灰度图的缩放采用二次线性插值效果比较好,如果利用这个算法写函数HDIB ChangeDIBSize(HDIB hDIB, int nWidth, int nHeight) 应该如何写呢?
      

  4.   

    其实差不多. 你读出HDIB的数据,然后按二次线性插值来计算像素值,因为是256色灰度的,直接插值索引就行了.,然后创建新的DIB,返回就可以了