dib.cpp
来自「Windows 图形编程 书籍」· C++ 代码 · 共 1,118 行 · 第 1/2 页
CPP
1,118 行
pFileName = fi.m_TitleName;
}
HANDLE handle = CreateFile(pFileName, GENERIC_WRITE, FILE_SHARE_READ,
NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
if ( handle == INVALID_HANDLE_VALUE )
return FALSE;
BITMAPFILEHEADER bmFH;
int nHeadSize = sizeof(BITMAPINFOHEADER) +
sizeof(RGBQUAD) * GetDIBColorCount(pBMI->bmiHeader);
bmFH.bfType = 0x4D42;
bmFH.bfSize = nHeadSize + GetDIBPixelSize(pBMI->bmiHeader);
bmFH.bfReserved1 = 0;
bmFH.bfReserved2 = 0;
bmFH.bfOffBits = nHeadSize + sizeof(BITMAPFILEHEADER);
DWORD dwRead = 0;
WriteFile(handle, & bmFH, sizeof(bmFH), & dwRead, NULL);
if ( pBits==NULL ) // packed DIB
pBits = (BYTE *) pBMI + nHeadSize;
WriteFile(handle, pBMI, nHeadSize, & dwRead, NULL);
WriteFile(handle, pBits, GetDIBPixelSize(pBMI->bmiHeader), & dwRead, NULL);
CloseHandle(handle);
return TRUE;
}
void SaveWindowToDIB(HWND hWnd, int nBitCount, int nCompression)
{
HBITMAP hBmp = CaptureWindow(hWnd);
if ( hBmp )
{
BITMAPINFO * pDIB = BitmapToDIB(NULL, hBmp, nBitCount, nCompression);
if ( pDIB )
{
SaveDIBToFile(NULL, pDIB, NULL);
delete [] (BYTE *) pDIB;
}
DeleteObject(hBmp);
}
}
const BYTE Shift1bpp[] = { 7, 6, 5, 4, 3, 2, 1, 0 };
const BYTE Mask1bpp [] = { ~0x80, ~0x40, ~0x20, ~0x10, ~0x08, ~0x04, ~0x02, ~0x01 };
const BYTE Shift2bpp[] = { 6, 4, 2, 0 };
const BYTE Mask2bpp [] = { ~0xC0, ~0x30, ~0x0C, ~0x03 };
const BYTE Shift4bpp[] = { 4, 0 };
const BYTE Mask4bpp [] = { ~0xF0, ~0x0F };
DWORD KDIB::GetPixelIndex(int x, int y) const
{
if ( (x<0) || (x>=m_nWidth) )
return -1;
if ( (y<0) || (y>=m_nHeight) )
return -1;
BYTE * pPixel = m_pOrigin + y * m_nDelta;
switch ( m_nImageFormat )
{
case DIB_1BPP:
return ( pPixel[x/8] >> Shift1bpp[x%8] ) & 0x01;
case DIB_2BPP:
return ( pPixel[x/4] >> Shift2bpp[x%4] ) & 0x03;
case DIB_4BPP:
return ( pPixel[x/2] >> Shift4bpp[x%4] ) & 0x0F;
case DIB_8BPP:
return pPixel[x];
case DIB_16RGB555:
case DIB_16RGB565:
return ((WORD *)pPixel)[x];
case DIB_24RGB888:
pPixel += x * 3;
return (pPixel[0]) | (pPixel[1] << 8) | (pPixel[2] << 16);
case DIB_32RGB888:
case DIB_32RGBA8888:
return ((DWORD *)pPixel)[x];
}
return -1;
}
BOOL KDIB::SetPixelIndex(int x, int y, DWORD index)
{
if ( (x<0) || (x>=m_nWidth) )
return FALSE;
if ( (y<0) || (y>=m_nHeight) )
return FALSE;
BYTE * pPixel = m_pOrigin + y * m_nDelta;
switch ( m_nImageFormat )
{
case DIB_1BPP:
pPixel[x/8] = (BYTE) ( ( pPixel[x/8] & Mask1bpp[x%8] ) | ( (index & 1) << Shift1bpp[x%8] ) );
break;
case DIB_2BPP:
pPixel[x/4] = (BYTE) ( ( pPixel[x/4] & Mask2bpp[x%4] ) | ( (index & 3) << Shift2bpp[x%4] ) );
break;
case DIB_4BPP:
pPixel[x/2] = (BYTE) ( ( pPixel[x/2] & Mask4bpp[x%2] ) | ( (index & 15) << Shift4bpp[x%2] ) );
break;
case DIB_8BPP:
pPixel[x] = (BYTE) index;
break;
case DIB_16RGB555:
case DIB_16RGB565:
((WORD *)pPixel)[x] = (WORD) index;
break;
case DIB_24RGB888:
((RGBTRIPLE *)pPixel)[x] = * ((RGBTRIPLE *) & index);
break;
case DIB_32RGB888:
case DIB_32RGBA8888:
((DWORD *)pPixel)[x] = index;
break;
default:
return FALSE;
}
return TRUE;
}
BOOL KDIB::PlgBlt(const POINT * pPoint,
KDIB * pSrc, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
KReverseAffine map(pPoint);
map.Setup(nXSrc, nYSrc, nWidth, nHeight);
for (int dy=map.miny; dy<=map.maxy; dy++)
for (int dx=map.minx; dx<=map.maxx; dx++)
{
float sx, sy;
map.Map(dx, dy, sx, sy);
if ( (sx>=nXSrc) && (sx<(nXSrc+nWidth)) )
if ( (sy>=nYSrc) && (sy<(nYSrc+nHeight)) )
SetPixelIndex(dx, dy, pSrc->GetPixelIndex( (int)sx, (int)sy));
}
return TRUE;
}
BOOL KDIB::PlgBltGetPixel(const POINT * pPoint,
HDC hSrc, int nXSrc, int nYSrc, int nWidth, int nHeight, HDC hDst)
{
KReverseAffine map(pPoint);
map.Setup(nXSrc, nYSrc, nWidth, nHeight);
for (int dy=map.miny; dy<=map.maxy; dy++)
for (int dx=map.minx; dx<=map.maxx; dx++)
{
float sx, sy;
map.Map(dx, dy, sx, sy);
if ( (sx>=nXSrc) && (sx<(nXSrc+nWidth)) )
if ( (sy>=nYSrc) && (sy<(nYSrc+nHeight)) )
SetPixel(hDst, dx, dy, GetPixel(hSrc, (int)sx, (int)sy));
}
return TRUE;
}
BOOL KDIB::PlgBlt24(const POINT * pPoint,
KDIB * pSrc, int nXSrc, int nYSrc, int nWidth, int nHeight)
{
// factor to change FLOAT to fixed point
const int FACTOR = 65536;
// generate reverse transformation from destination to source
KReverseAffine map(pPoint);
map.Setup(nXSrc, nYSrc, nWidth, nHeight);
// make sure within destination bitmap dimension
if ( map.minx < 0 ) map.minx = 0;
if ( map.maxx > m_nWidth ) map.maxx = m_nWidth;
if ( map.miny < 0 ) map.miny = 0;
if ( map.maxy > m_nHeight ) map.maxy = m_nHeight;
// source rectangle in fixed point
int sminx = nXSrc * FACTOR;
int sminy = nYSrc * FACTOR;
int smaxx = ( nXSrc + nWidth ) * FACTOR;
int smaxy = ( nYSrc + nHeight ) * FACTOR;
// transformation matrix in fixed point
int m11 = (int) (map.m_xm.eM11 * FACTOR);
int m12 = (int) (map.m_xm.eM12 * FACTOR);
int m21 = (int) (map.m_xm.eM21 * FACTOR);
int m22 = (int) (map.m_xm.eM22 * FACTOR);
int mdx = (int) (map.m_xm.eDx * FACTOR);
int mdy = (int) (map.m_xm.eDy * FACTOR);
BYTE * SOrigin = pSrc->m_pOrigin;
int SDelta = pSrc->m_nDelta;
// in destination bitmap, scan from first to last scanline
for (int dy=map.miny; dy<map.maxy; dy++)
{
/*
// search for the first pixel on the scanline within source rectangle
int sx = m11 * map.minx + m21 * dy + mdx;
int sy = m12 * map.minx + m22 * dy + mdy;
for (int dx=map.minx; dx<map.maxx; dx++, sx+=m11, sy+=m12)
// if within source rectangle
if ( (sx>=sminx) && (sx<smaxx) )
if ( (sy>=sminy) && (sy<smaxy) )
break;
int minx = dx;
// search for the last pixel on the scaneline within source rectangle
sx = m11 * map.maxx + m21 * dy + mdx;
sy = m12 * map.maxx + m22 * dy + mdy;
for (dx=map.maxx; dx>=map.minx; dx--, sx-=m11, sy-=m12)
// if within source rectangle
if ( (sx>=sminx) && (sx<smaxx) )
if ( (sy>=sminy) && (sy<smaxy) )
break;
int maxx = dx;
*/
// precalculate destination pixel address for first pixel
BYTE * pDPixel = m_pOrigin + dy * m_nDelta + map.minx * 3;
// source pixel address for the first pixel
int sx = m11 * map.minx + m21 * dy + mdx;
int sy = m12 * map.minx + m22 * dy + mdy;
// go through each pixel on the scan line
for (int dx=map.minx; dx<map.maxx; dx++, pDPixel+=3, sx+=m11, sy+=m12)
if ( (sx>=sminx) && (sx<smaxx) )
if ( (sy>=sminy) && (sy<smaxy) )
{
// source pixel address
BYTE * pSPixel = SOrigin + (sy/FACTOR) * SDelta;
// copy three bytes
* ((RGBTRIPLE *)pDPixel) = ((RGBTRIPLE *)pSPixel)[sx/FACTOR];
}
}
return TRUE;
}
BOOL KDIB::Create(int width, int height, int bitcount)
{
KBitmapInfo dibinfo;
dibinfo.SetFormat(width, height, bitcount, BI_RGB);
int nBitsSize = ( width * bitcount + 31 ) /32 * 4 * height;
BYTE * pBits = new BYTE[nBitsSize];
if ( pBits )
return AttachDIB(dibinfo.CopyBMI(), pBits, 0);
else
return FALSE;
}
void Map(XFORM * xm, int x, int y, int & rx, int & ry)
{
rx = (int) ( xm->eM11 * x + xm->eM21 * y + xm->eDx );
ry = (int) ( xm->eM12 * x + xm->eM22 * y + xm->eDy );
}
BOOL Invert(XFORM & xm)
{
FLOAT det = xm.eM11 * xm.eM22 - xm.eM21 * xm.eM12;
if ( det==0 )
return FALSE;
XFORM old = xm;
xm.eM11 = old.eM22 / det;
xm.eM12 = - old.eM12 / det;
xm.eM21 = - old.eM21 / det;
xm.eM22 = old.eM11 / det;
xm.eDx = - ( xm.eM11 * old.eDx + xm.eM21 * old.eDy );
xm.eDy = - ( xm.eM12 * old.eDx + xm.eM22 * old.eDy );
return TRUE;
}
DWORD dibtick;
HBITMAP KDIB::TransformBitmap(XFORM * xm, COLORREF crBack, int method)
{
int x0, y0, x1, y1, x2, y2, x3, y3;
Map(xm, 0, 0, x0, y0); // 0 1
Map(xm, m_nWidth, 0, x1, y1); //
Map(xm, 0, m_nHeight, x2, y2); // 2 3
Map(xm, m_nWidth, m_nHeight, x3, y3);
int xmin, xmax;
int ymin, ymax;
minmax(x0, x1, x2, x3, xmin, xmax);
minmax(y0, y1, y2, y3, ymin, ymax);
int destwidth = xmax - xmin;
int destheight = ymax - ymin;
KBitmapInfo dest;
dest.SetFormat(destwidth, destheight, m_pBMI->bmiHeader.biBitCount, m_pBMI->bmiHeader.biCompression);
if ( m_nClrUsed )
memcpy(dest.m_dibinfo.bmiColors, m_pRGBQUAD, sizeof(RGBQUAD) * m_nClrUsed);
// create destination DIB section
BYTE * pBits;
HBITMAP hBitmap = CreateDIBSection(NULL, dest.GetBMI(), DIB_RGB_COLORS, (void **) & pBits, NULL, NULL);
if ( hBitmap==NULL )
{
assert(false);
return NULL;
}
// For testing GDI GetPixel speed, we need a HDC for the source bitmap
HBITMAP hSrcBmp = NULL;
HDC hSrcDC = NULL;
HGDIOBJ hSrcOld = NULL;
if ( method==method_gdi )
{
hSrcBmp = CreateDIBSection(NULL, m_pBMI, DIB_RGB_COLORS, (void **) & pBits, NULL, NULL);
assert(hSrcBmp);
hSrcDC = CreateCompatibleDC(NULL);
hSrcOld = SelectObject(hSrcDC, hSrcBmp);
// copy pixels from DIB to source DIB section
DrawDIB(hSrcDC, 0, 0, m_nWidth, m_nHeight, 0, 0, m_nWidth, m_nHeight, SRCCOPY);
}
// clear DIB section to background color
HDC hDstDC = CreateCompatibleDC(NULL);
HGDIOBJ hDstOld = SelectObject(hDstDC, hBitmap);
HBRUSH hBrush = CreateSolidBrush(crBack);
RECT rect = { 0, 0, destwidth, destheight };
FillRect(hDstDC, & rect, hBrush);
DeleteObject(hBrush);
KDIB destDIB;
destDIB.AttachDIB(dest.GetBMI(), pBits, 0);
POINT P[3] = { { x0-xmin, y0-ymin }, { x1-xmin, y1-ymin }, { x2-xmin, y2-ymin } };
dibtick = GetTickCount();
if ( (m_nBitCount<=8) && (method==method_24bpp) )
method = method_direct;
switch ( method )
{
case method_gdi:
destDIB.PlgBltGetPixel(P, hSrcDC, 0, 0, m_nWidth, m_nHeight, hDstDC);
break;
case method_direct:
destDIB.PlgBlt(P, this, 0, 0, m_nWidth, m_nHeight);
break;
case method_24bpp:
destDIB.PlgBlt24(P, this, 0, 0, m_nWidth, m_nHeight);
break;
}
dibtick = GetTickCount() - dibtick;
SelectObject(hDstDC, hDstOld);
DeleteObject(hDstDC);
if ( method==method_gdi )
{
SelectObject(hSrcDC, hSrcOld);
DeleteObject(hSrcDC);
DeleteObject(hSrcBmp);
}
return hBitmap;
}
// Calculate DIB pixel offset
inline int GetOffset(BITMAPINFO * pBMI, int x, int y)
{
if ( pBMI->bmiHeader.biHeight > 0 ) // for bottom up, reflect y
y = pBMI->bmiHeader.biHeight - 1 - y;
return ( pBMI->bmiHeader.biWidth * pBMI->bmiHeader.biBitCount + 31 ) / 32 * 4 * y +
( pBMI->bmiHeader.biBitCount / 8 ) * x;
}
// Alpha Blending between two 32-bpp DIBs
BOOL AlphaBlend3232(BITMAPINFO * pBMIDst, BYTE * pBitsDst, int dx, int dy, int w, int h,
BITMAPINFO * pBMISrc, BYTE * pBitsSrc, int sx, int sy,
BLENDFUNCTION blend)
{
int alpha = blend.SourceConstantAlpha; // constant alpha
int beta = 255 - alpha; // constant beta
int format;
if ( blend.AlphaFormat==0 )
format = 0;
else if ( alpha==255 )
format = 1;
else
format = 2;
for (int j=0; j<h; j++)
{
BYTE * D = pBitsDst + GetOffset(pBMIDst, dx, j + dy);
BYTE * S = pBitsSrc + GetOffset(pBMISrc, sx, j + sy);
int i;
switch ( format )
{
case 0: // constant alpha only
for (i=0; i<w; i++)
{
D[0] = ( S[0] * alpha + beta * D[0] + 127 ) / 255;
D[1] = ( S[1] * alpha + beta * D[1] + 127 ) / 255;
D[2] = ( S[2] * alpha + beta * D[2] + 127 ) / 255;
D[3] = ( S[3] * alpha + beta * D[3] + 127 ) / 255;
D += 4; S += 4;
}
break;
case 1: // alpha channel only
for (i=0; i<w; i++)
{
beta = 255 - S[3];
D[0] = S[0] + ( beta * D[0] + 127 ) / 255;
D[1] = S[1] + ( beta * D[1] + 127 ) / 255;
D[2] = S[2] + ( beta * D[2] + 127 ) / 255;
D[3] = S[3] + ( beta * D[3] + 127 ) / 255;
D += 4; S += 4;
}
break;
case 2: // both constant alpha and alpha channel
for (i=0; i<w; i++)
{
beta = 255 - ( S[3] * alpha + 127 ) / 255;
D[0] = ( S[0] * alpha + beta * D[0] + 127 ) / 255;
D[1] = ( S[1] * alpha + beta * D[1] + 127 ) / 255;
D[2] = ( S[2] * alpha + beta * D[2] + 127 ) / 255;
D[3] = ( S[3] * alpha + beta * D[3] + 127 ) / 255;
D += 4; S += 4;
}
}
}
return FALSE;
}
// AlphaBlending a 32-bpp DIB to hdc
BOOL AlphaBlend(HDC hdc, int x0, int y0, const BITMAPINFO *pbmpInfo, const void * pAlphaImageData)
{
if ( pbmpInfo->bmiHeader.biBitCount!=32 )
return FALSE;
if ( pbmpInfo->bmiHeader.biCompression!=BI_RGB )
return FALSE;
int width = pbmpInfo->bmiHeader.biWidth;
int height = pbmpInfo->bmiHeader.biHeight;
BITMAPINFOHEADER bmih = { sizeof(BITMAPINFOHEADER), width, height, 1, 24 };
VOID * pBits;
HBITMAP hBmp = CreateDIBSection(NULL, (BITMAPINFO *) & bmih, DIB_RGB_COLORS, & pBits, NULL, NULL);
if ( hBmp==NULL )
return FALSE;
HDC hMemDC = CreateCompatibleDC(hdc);
HGDIOBJ hOld = SelectObject(hMemDC, hBmp);
BitBlt(hMemDC, 0, 0, width, height, hdc, x0, y0, SRCCOPY); // copy destination, not working on printer
const BYTE * psrc = (const BYTE *) pAlphaImageData;
BYTE * pdst = (BYTE *) pBits;
for (int y = 0; y < abs(height); y++)
{
for (int x = width; x>0; x--)
{
BYTE alpha = psrc[3]; //Get alpha channel byte.
BYTE salpha = 255 - alpha;
pdst[0] = (BYTE)(( psrc[0] * alpha + pdst[0] * salpha) / 255);
pdst[1] = (BYTE)(( psrc[1] * alpha + pdst[1] * salpha) / 255);
pdst[2] = (BYTE)(( psrc[2] * alpha + pdst[2] * salpha) / 255);
pdst += 3;
psrc += 4;
}
pdst += width % 3;
}
BOOL rslt = BitBlt(hdc, x0, y0, width, height, hMemDC, 0, 0, SRCCOPY);
SelectObject(hMemDC, hOld);
DeleteObject(hBmp);
DeleteObject(hMemDC);
return rslt;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?