#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;
// 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
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.
// 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.
SetStretchBltMode用COLORONCOLOR
应该可以