我想用LoadImage函数读入一个位图,并用StretchBlt函数缩小显示到某个窗口,但是发现如果该函数按原来尺寸显示出来没问题,但如果让它缩小显示就不对,感觉图象色彩严重失真,请高手不吝指教。我是调用SDK的这个函数,不是CDC类的,而且SetStretchBltMode(COLORONCOLOR)设置模式,但还是不对。如果知道其它方法可以不失真显示伸缩位图,请相告。虽然分不多,但哪位高手能帮忙搞定,分数一定送出。

解决方案 »

  1.   

    #define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4) // for padding///////////////////////////////////////////////////////////////////
    // Function name    : ZoomOutBmp
    // Description      : creates a new bitmap which is a grayscale 
    //                    zoomed out version of the original
    // Return type      : HDIB - handle to a new bitmap 
    // Argument         : double zoom - number of times to zoom out
    // Argument         : HDIB hSrcDIB - handle to a source bitmap
    ///////////////////////////////////////////////////////////////////
    HDIB ZoomOutBmp(double zoom, HDIB hSrcDIB)
    {
        if (hSrcDIB == NULL) // nothing to do
            return NULL;
        
        if (zoom < 1) // no zoomin in this function
            return NULL;
        
        LPSTR pSrcDIB = (LPSTR) ::GlobalLock((HGLOBAL) hSrcDIB);
        
        BITMAPINFOHEADER& bmihSrc = *(BITMAPINFOHEADER*)pSrcDIB;
        ASSERT(bmihSrc.biBitCount == 1); // only monochrome bitmaps supported
        LPSTR pSrcBits = (LPSTR) (pSrcDIB + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*2);
        
        BITMAPINFOHEADER bmihDst = bmihSrc;
        bmihDst.biWidth = (LONG)(bmihDst.biWidth / zoom + 0.5);
        bmihDst.biHeight = (LONG)(bmihDst.biHeight / zoom + 0.5);
        bmihDst.biBitCount = 8; // grayscale in any case
        bmihDst.biClrUsed = 0;
        
        // prepare destination bitmap
        DWORD dwDIBSize = sizeof(bmihDst) + sizeof(RGBQUAD)*256 +
            WIDTHBYTES(bmihDst.biWidth * bmihDst.biBitCount) * bmihDst.biHeight;
        
        bmihDst.biSizeImage = dwDIBSize;
        
        // allocate space for the new bitmap
        HDIB hDstDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize);
        
        if (hDstDIB == 0) {
            ::GlobalUnlock((HGLOBAL) hSrcDIB);
            return NULL;
        }
        
        LPSTR pDstDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDstDIB);
        
        // copy header
        memcpy(pDstDIB, &bmihDst, sizeof(bmihDst));
        
        // prepare grayscale palette
        for (int i=0; i < (1 << bmihDst.biBitCount); i++) {
            
            RGBQUAD& palEntry = *(RGBQUAD*)(pDstDIB + sizeof(bmihDst) + i * sizeof(RGBQUAD));
            palEntry.rgbRed = palEntry.rgbGreen = palEntry.rgbBlue = i;
            
        }
        
        LPSTR pDstBits = (LPSTR) (pDstDIB + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256);
        
        // now fill the bits
        LPSTR curSrcLineBits, curDstLineBits;
        int j, k;
        int scale = (int)(zoom + 0.5); // integer zoom out factor, i.e. 1:5
        int hBase, vBase;
        unsigned char value;
        
        // for every _scale_ lines in a source bitmap we will get one line
        // in the destination bitmap. Similarly for _scale_ columns in the
        // source we'll obtain one destination column.
        
        for (int strip=0; strip < bmihDst.biHeight; strip++) { // for every dst line
            
            curDstLineBits = pDstBits + strip * WIDTHBYTES(bmihDst.biWidth * bmihDst.biBitCount);
            vBase = int(strip * zoom + 0.5);
            
            for (i=0; i < scale; i++) {  // accumulate _scale_ rows
                
                curSrcLineBits = pSrcBits + (vBase + i) * WIDTHBYTES(bmihSrc.biWidth * bmihSrc.biBitCount);
                
                // prepare horizontally condensed lines for this strip
                for (j=0; j < bmihDst.biWidth; j++) { // for all bits in line
                    
                    hBase = int(j * zoom + 0.5); // mapped index on source
                    for (k=0; k < scale; k++) { // accumulate _scale_ columns
                        
                        value = (curSrcLineBits[(hBase+k)/8] & (1 << (7 - (hBase+k)%8))) ? 0xff : 0;
                        curDstLineBits[j] += value / scale / scale; // main accumulator
                    }
                }
            }
            
        }
        
        // unlock memory
        ::GlobalUnlock((HGLOBAL) hSrcDIB);
        ::GlobalUnlock((HGLOBAL) hDstDIB);
        
        return hDstDIB;
    }This function may be improved in several ways, for example, working with a weighted fraction of a pixel or centering the accumulated source pixels. However, the resulting visual impovement is not significant. 
      

  2.   

    StretchBlt用SRCCOPY
    SetStretchBltMode用COLORONCOLOR
    应该可以