单色图的缩小

来源:互联网 发布:富士康java工程师待遇 编辑:程序博客网 时间:2024/04/28 18:32

///////////////////////////////////////////////////////////////////

// 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 JpegFile::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 (int 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;

}