dibapi.cpp
上传用户:gzboli
上传日期:2013-04-10
资源大小:471k
文件大小:239k
- // RotateBitmapNT - Create a new bitmap with rotated image
- // Returns - Returns new bitmap with rotated image
- // hBitmap - Bitmap to rotate
- // fDegrees - Angle of rotation in degree
- // clrBack - Color of pixels in the resulting bitmap that do
- // not get covered by source pixels
- HBITMAP RotateBitmapNT(HBITMAP hBitmap, double fDegrees, COLORREF clrBack)
- {
- // Create a memory DC compatible with the display
- CDC sourceDC, destDC;
- sourceDC.CreateCompatibleDC( NULL );
- destDC.CreateCompatibleDC( NULL );
- // Get logical coordinates
- BITMAP bm;
- ::GetObject( hBitmap, sizeof( bm ), &bm );
-
- // Convert angle degree to radians
- #define PI 3.1415926
- double radians = (fDegrees/90.0)*(PI/2);
- // Compute the cosine and sine only once
- float cosine = (float)cos(radians);
- float sine = (float)sin(radians);
- // Compute dimensions of the resulting bitmap
- // First get the coordinates of the 3 corners other than origin
- int x1 = (int)(bm.bmHeight * sine);
- int y1 = (int)(bm.bmHeight * cosine);
- int x2 = (int)(bm.bmWidth * cosine + bm.bmHeight * sine);
- int y2 = (int)(bm.bmHeight * cosine - bm.bmWidth * sine);
- int x3 = (int)(bm.bmWidth * cosine);
- int y3 = (int)(-bm.bmWidth * sine);
- int minx = min(0,min(x1, min(x2,x3)));
- int miny = min(0,min(y1, min(y2,y3)));
- int maxx = max(0,max(x1, max(x2,x3)));
- int maxy = max(0,max(y1, max(y2,y3)));
- int w = maxx - minx;
- int h = maxy - miny;
- // Create a bitmap to hold the result
- HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL), w, h);
- HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
- HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
- // Draw the background color before we change mapping mode
- HBRUSH hbrBack = CreateSolidBrush( clrBack );
- HBRUSH hbrOld = (HBRUSH)::SelectObject( destDC.m_hDC, hbrBack );
- destDC.PatBlt( 0, 0, w, h, PATCOPY );
- ::DeleteObject( ::SelectObject( destDC.m_hDC, hbrOld ) );
- // We will use world transform to rotate the bitmap
- SetGraphicsMode(destDC.m_hDC, GM_ADVANCED);
- XFORM xform;
- xform.eM11 = cosine;
- xform.eM12 = -sine;
- xform.eM21 = sine;
- xform.eM22 = cosine;
- xform.eDx = (float)-minx;
- xform.eDy = (float)-miny;
- SetWorldTransform( destDC.m_hDC, &xform );
- // Now do the actual rotating - a pixel at a time
- destDC.BitBlt(0,0,bm.bmWidth, bm.bmHeight, &sourceDC, 0, 0, SRCCOPY );
- // Restore DCs
- ::SelectObject( sourceDC.m_hDC, hbmOldSource );
- ::SelectObject( destDC.m_hDC, hbmOldDest );
- return hbmResult;
- }
- // RotateBitmap - Create a new bitmap with rotated image
- // Returns - Returns new bitmap with rotated image
- // hBitmap - Bitmap to rotate
- // fDegrees - Angle of rotation in degree
- // clrBack - Color of pixels in the resulting bitmap that do
- // not get covered by source pixels
- // Note - If the bitmap uses colors not in the system palette
- // then the result is unexpected. You can fix this by
- // adding an argument for the logical palette.
- HBITMAP RotateBitmap(HBITMAP hBitmap, double fDegrees, COLORREF clrBack)
- {
- // Create a memory DC compatible with the display
- CDC sourceDC, destDC;
- sourceDC.CreateCompatibleDC( NULL );
- destDC.CreateCompatibleDC( NULL );
- // Get logical coordinates
- BITMAP bm;
- ::GetObject( hBitmap, sizeof( bm ), &bm );
- // Convert angle degree to radians
- #define PI 3.1415926
- double radians = (fDegrees/90.0)*(PI/2);
- // Compute the cosine and sine only once
- float cosine = (float)cos(radians);
- float sine = (float)sin(radians);
- // Compute dimensions of the resulting bitmap
- // First get the coordinates of the 3 corners other than origin
- int x1 = (int)(-bm.bmHeight * sine);
- int y1 = (int)(bm.bmHeight * cosine);
- int x2 = (int)(bm.bmWidth * cosine - bm.bmHeight * sine);
- int y2 = (int)(bm.bmHeight * cosine + bm.bmWidth * sine);
- int x3 = (int)(bm.bmWidth * cosine);
- int y3 = (int)(bm.bmWidth * sine);
- int minx = min(0,min(x1, min(x2,x3)));
- int miny = min(0,min(y1, min(y2,y3)));
- int maxx = max(x1, max(x2,x3));
- int maxy = max(y1, max(y2,y3));
- int w = maxx - minx;
- int h = maxy - miny;
- // Create a bitmap to hold the result
- HBITMAP hbmResult = ::CreateCompatibleBitmap(CClientDC(NULL), w, h);
- HBITMAP hbmOldSource = (HBITMAP)::SelectObject( sourceDC.m_hDC, hBitmap );
- HBITMAP hbmOldDest = (HBITMAP)::SelectObject( destDC.m_hDC, hbmResult );
- // Draw the background color before we change mapping mode
- HBRUSH hbrBack = CreateSolidBrush( clrBack );
- HBRUSH hbrOld = (HBRUSH)::SelectObject( destDC.m_hDC, hbrBack );
- destDC.PatBlt( 0, 0, w, h, PATCOPY );
- ::DeleteObject( ::SelectObject( destDC.m_hDC, hbrOld ) );
- // Set mapping mode so that +ve y axis is upwords
- sourceDC.SetMapMode(MM_ISOTROPIC);
- sourceDC.SetWindowExt(1,1);
- sourceDC.SetViewportExt(1,-1);
- sourceDC.SetViewportOrg(0, bm.bmHeight-1);
- destDC.SetMapMode(MM_ISOTROPIC);
- destDC.SetWindowExt(1,1);
- destDC.SetViewportExt(1,-1);
- destDC.SetWindowOrg(minx, maxy);
- // Now do the actual rotating - a pixel at a time
- // Computing the destination point for each source point
- // will leave a few pixels that do not get covered
- // So we use a reverse transform - e.i. compute the source point
- // for each destination point
- for( int y = miny; y < maxy; y++ )
- {
- for( int x = minx; x < maxx; x++ )
- {
- int sourcex = (int)(x*cosine + y*sine);
- int sourcey = (int)(y*cosine - x*sine);
- if( sourcex >= 0 && sourcex < bm.bmWidth && sourcey >= 0
- && sourcey < bm.bmHeight )
- destDC.SetPixel(x,y,sourceDC.GetPixel(sourcex,sourcey));
- }
- }
- // Restore DCs
- ::SelectObject( sourceDC.m_hDC, hbmOldSource );
- ::SelectObject( destDC.m_hDC, hbmOldDest );
- return hbmResult;
- }
- // RotateDIB - Create a new bitmap with rotated image
- // Returns - Returns new bitmap with rotated image
- // hDIB - Device-independent bitmap to rotate
- // fDegrees - Angle of rotation in degree
- // clrBack - Color of pixels in the resulting bitmap that do
- // not get covered by source pixels
- HDIB RotateDIB(HDIB hDIB, double fDegrees, COLORREF clrBack)
- {
- WaitCursorBegin();
- // Get source bitmap info
- LPBITMAPINFO lpBmInfo = (LPBITMAPINFO)GlobalLock(hDIB);
- int bpp = lpBmInfo->bmiHeader.biBitCount; // Bits per pixel
-
- int nColors = lpBmInfo->bmiHeader.biClrUsed ? lpBmInfo->bmiHeader.biClrUsed :
- 1 << bpp;
- int nWidth = lpBmInfo->bmiHeader.biWidth;
- int nHeight = lpBmInfo->bmiHeader.biHeight;
- int nRowBytes = ((((nWidth * bpp) + 31) & ~31) / 8);
- // Make sure height is positive and biCompression is BI_RGB or BI_BITFIELDS
- DWORD compression = lpBmInfo->bmiHeader.biCompression;
- if( nHeight < 0 || (compression!=BI_RGB))
- {
- GlobalUnlock(hDIB);
- WaitCursorEnd();
- return NULL;
- }
- LPSTR lpDIBBits = FindDIBBits((LPSTR)lpBmInfo);
-
- // Convert angle degree to radians
- #define PI 3.1415926
- double radians = (fDegrees/90.0)*(PI/2);
- // Compute the cosine and sine only once
- float cosine = (float)cos(radians);
- float sine = (float)sin(radians);
- // Compute dimensions of the resulting bitmap
- // First get the coordinates of the 3 corners other than origin
- int x1 = (int)(-nHeight * sine);
- int y1 = (int)(nHeight * cosine);
- int x2 = (int)(nWidth * cosine - nHeight * sine);
- int y2 = (int)(nHeight * cosine + nWidth * sine);
- int x3 = (int)(nWidth * cosine);
- int y3 = (int)(nWidth * sine);
- int minx = min(0,min(x1, min(x2,x3)));
- int miny = min(0,min(y1, min(y2,y3)));
- int maxx = max(x1, max(x2,x3));
- int maxy = max(y1, max(y2,y3));
- int w = maxx - minx;
- int h = maxy - miny;
- // Create a DIB to hold the result
- int nResultRowBytes = ((((w * bpp) + 31) & ~31) / 8);
- long len = nResultRowBytes * h;
- int nHeaderSize = ((LPSTR)lpDIBBits-(LPSTR)lpBmInfo) ;
- HANDLE hDIBResult = GlobalAlloc(GHND,len+nHeaderSize);
- // Initialize the header information
- LPBITMAPINFO lpBmInfoResult = (LPBITMAPINFO)GlobalLock(hDIBResult);
- memcpy( (void*)lpBmInfoResult, (void*)lpBmInfo, nHeaderSize);
- lpBmInfoResult->bmiHeader.biWidth = w;
- lpBmInfoResult->bmiHeader.biHeight = h;
- lpBmInfoResult->bmiHeader.biSizeImage = len;
- LPSTR lpDIBBitsResult = FindDIBBits((LPSTR)lpBmInfoResult);
- // Get the back color value (index)
- ZeroMemory( lpDIBBitsResult, len );
- DWORD dwBackColor;
- switch(bpp)
- {
- case 1: //Monochrome
- if( clrBack == RGB(255,255,255) )
- memset( lpDIBBitsResult, 0xff, len );
- break;
- case 4:
- case 8: //Search the color table
- int i;
- for(i = 0; i < nColors; i++ )
- {
- if( lpBmInfo->bmiColors[i].rgbBlue == GetBValue(clrBack)
- && lpBmInfo->bmiColors[i].rgbGreen == GetGValue(clrBack)
- && lpBmInfo->bmiColors[i].rgbRed == GetRValue(clrBack) )
- {
- if(bpp==4) i = i | i<<4;
- memset( lpDIBBitsResult, i, len );
- break;
- }
- }
- // If not match found the color remains black
- break;
- case 16:
- // Windows95 supports 5 bits each for all colors or 5 bits for red & blue
- // and 6 bits for green - Check the color mask for RGB555 or RGB565
- if( *((DWORD*)lpBmInfo->bmiColors) == 0x7c00 )
- {
- // Bitmap is RGB555
- dwBackColor = ((GetRValue(clrBack)>>3) << 10) +
- ((GetRValue(clrBack)>>3) << 5) +
- (GetBValue(clrBack)>>3) ;
- }
- else
- {
- // Bitmap is RGB565
- dwBackColor = ((GetRValue(clrBack)>>3) << 11) +
- ((GetRValue(clrBack)>>2) << 5) +
- (GetBValue(clrBack)>>3) ;
- }
- break;
- case 24:
- case 32:
- dwBackColor = (((DWORD)GetRValue(clrBack)) << 16) |
- (((DWORD)GetGValue(clrBack)) << 8) |
- (((DWORD)GetBValue(clrBack)));
- break;
- }
- // Now do the actual rotating - a pixel at a time
- // Computing the destination point for each source point
- // will leave a few pixels that do not get covered
- // So we use a reverse transform - e.i. compute the source point
- // for each destination point
- for( int y = 0; y < h; y++ )
- {
- for( int x = 0; x < w; x++ )
- {
- int sourcex = (int)((x+minx)*cosine + (y+miny)*sine);
- int sourcey = (int)((y+miny)*cosine - (x+minx)*sine);
- if( sourcex >= 0 && sourcex < nWidth && sourcey >= 0
- && sourcey < nHeight )
- {
- // Set the destination pixel
- switch(bpp)
- {
- BYTE mask;
- case 1: //Monochrome
- mask = *((LPSTR)lpDIBBits + nRowBytes*sourcey +
- sourcex/8) & (0x80 >> sourcex%8);
- //Adjust mask for destination bitmap
- mask = mask ? (0x80 >> x%8) : 0;
- *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) +
- (x/8)) &= ~(0x80 >> x%8);
- *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) +
- (x/8)) |= mask;
- break;
- case 4:
- mask = *((LPSTR)lpDIBBits + nRowBytes*sourcey +
- sourcex/2) & ((sourcex&1) ? 0x0f : 0xf0);
- //Adjust mask for destination bitmap
- if( (sourcex&1) != (x&1) )
- mask = (mask&0xf0) ? (mask>>4) : (mask<<4);
- *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) +
- (x/2)) &= ~((x&1) ? 0x0f : 0xf0);
- *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) +
- (x/2)) |= mask;
- break;
- case 8:
- BYTE pixel ;
- pixel = *((LPSTR)lpDIBBits + nRowBytes*sourcey +
- sourcex);
- *((LPSTR)lpDIBBitsResult + nResultRowBytes*(y) +
- (x)) = pixel;
- break;
- case 16:
- DWORD dwPixel;
- dwPixel = *((LPWORD)((LPSTR)lpDIBBits +
- nRowBytes*sourcey + sourcex*2));
- *((LPWORD)((LPSTR)lpDIBBitsResult +
- nResultRowBytes*y + x*2)) = (WORD)dwPixel;
- break;
- case 24:
- dwPixel = *((LPDWORD)((LPSTR)lpDIBBits +
- nRowBytes*sourcey + sourcex*3)) & 0xffffff;
- *((LPDWORD)((LPSTR)lpDIBBitsResult +
- nResultRowBytes*y + x*3)) |= dwPixel;
- break;
- case 32:
- dwPixel = *((LPDWORD)((LPSTR)lpDIBBits +
- nRowBytes*sourcey + sourcex*4));
- *((LPDWORD)((LPSTR)lpDIBBitsResult +
- nResultRowBytes*y + x*4)) = dwPixel;
- }
- }
- else
- {
- // Draw the background color. The background color
- // has already been drawn for 8 bits per pixel and less
- switch(bpp)
- {
- case 16:
- *((LPWORD)((LPSTR)lpDIBBitsResult +
- nResultRowBytes*y + x*2)) =
- (WORD)dwBackColor;
- break;
- case 24:
- *((LPDWORD)((LPSTR)lpDIBBitsResult +
- nResultRowBytes*y + x*3)) |= dwBackColor;
- break;
- case 32:
- *((LPDWORD)((LPSTR)lpDIBBitsResult +
- nResultRowBytes*y + x*4)) = dwBackColor;
- break;
- }
- }
- }
- }
- GlobalUnlock(hDIB);
- GlobalUnlock(hDIBResult);
- WaitCursorEnd();
- return hDIBResult;
- }
- /*************************************************************************
- *
- * RotateDIB()
- *
- * Parameters:
- *
- * HDIB hDIB - handle of DIB to rotate
- *
- * Return Value:
- *
- * HDIB - Handle to new DIB
- *
- * Description:
- *
- * This function rotate DIB 90 degree counter clockwise, and return
- * the rotated DIB in a new DIB handle, let the source DIB unchanged
- *
- ************************************************************************/
- HDIB RotateDIB(HDIB hDib)
- {
- WaitCursorBegin();
- // old DIB
- LPSTR lpDIBSrc = (LPSTR)GlobalLock(hDib);
- DWORD lSrcWidth = DIBWidth(lpDIBSrc);
- DWORD lSrcHeight = DIBHeight(lpDIBSrc);
- WORD wBitCount = ((LPBITMAPINFOHEADER)lpDIBSrc)->biBitCount;
- // bits position
- LPSTR lpOldBits = FindDIBBits(lpDIBSrc);
- // get bytes/pixel, bytes/row of new DIB
- double fColorBytes = (double)((double)wBitCount/8.0);
- DWORD lSrcRowBytes = WIDTHBYTES(lSrcWidth*((DWORD)wBitCount));
- DWORD lDestRowBytes = WIDTHBYTES(lSrcHeight*((DWORD)wBitCount));
- // adjust new DIB size
- DWORD dwDataLength = GlobalSize(hDib);
- dwDataLength += lDestRowBytes*(lSrcWidth-1)+(DWORD)((lSrcHeight-1)*fColorBytes) -
- lSrcRowBytes*(lSrcHeight-1)+(DWORD)((lSrcWidth-1)*fColorBytes);
- HDIB hNewDib = GlobalAlloc(GHND, dwDataLength);
- if (! hNewDib)
- {
- WaitCursorEnd();
- return NULL;
- }
- // new DIB buffer
- LPSTR lpDIB = (LPSTR)GlobalLock(hNewDib);
- // copy LPBITMAPINFO from old to new
- memcpy(lpDIB, lpDIBSrc, sizeof(BITMAPINFOHEADER)+PaletteSize(lpDIBSrc));
- // swap width and height
- ((LPBITMAPINFOHEADER)lpDIB)->biHeight = lSrcWidth;
- ((LPBITMAPINFOHEADER)lpDIB)->biWidth = lSrcHeight;
- // new bits position
- LPSTR lpData = FindDIBBits(lpDIB);
- // trandform bits
- DWORD i, j;
- switch (wBitCount)
- {
- case 1:
- for (i=0; i<lSrcHeight; ++i)
- {
- for (j=0; j<lSrcWidth; ++j)
- {
- *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)/8)) &= ~(1<<(7-((lSrcHeight-i-1)%8)));
- *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)/8)) |=
- ((*(lpOldBits+(lSrcRowBytes*i+j/8))<<(j%8))>>7)<<(7-((lSrcHeight-i-1)%8));
- }
- }
- break;
- case 4:
- for (i=0; i<lSrcHeight; ++i)
- {
- for (j=0; j<lSrcWidth; ++j)
- {
- *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)/2)) &= ((lSrcHeight-i-1)%2) ? 0xf0 : 0x0f;
- *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)/2)) |=
- ((*(lpOldBits+(lSrcRowBytes*i+j/2))<<(j%2 ? 4 : 0))>>4)<<(((lSrcHeight-i-1)%2) ? 0 : 4);
- }
- }
- break;
- case 8:
- for (i=0; i<lSrcHeight; ++i)
- {
- for (j=0; j<lSrcWidth; ++j)
- {
- *(lpData+(lDestRowBytes*j+lSrcHeight-i-1))
- = *(lpOldBits+(lSrcRowBytes*i+j));
- }
- }
- break;
- case 24:
- for (i=0; i<lSrcHeight; ++i)
- {
- for (j=0; j<lSrcWidth; j++)
- {
- *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)*3))
- = *(lpOldBits+(lSrcRowBytes*i+j*3));
- *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)*3)+1)
- = *(lpOldBits+(lSrcRowBytes*i+j*3)+1);
- *(lpData+(lDestRowBytes*j+(lSrcHeight-i-1)*3)+2)
- = *(lpOldBits+(lSrcRowBytes*i+j*3)+2);
- }
- }
- break;
- }
- // cleanup
- GlobalUnlock(hDib);
- GlobalUnlock(hNewDib);
- WaitCursorEnd();
-
- return hNewDib;
- }
- /*************************************************************************
- *
- * FlipHorzDIB()
- *
- * Parameters:
- *
- * HDIB hDIB - handle of DIB to flip horzonly
- *
- * Return Value:
- *
- * HDIB - Handle to new DIB
- *
- * Description:
- *
- * This function flip DIB horzonly, and return
- * the flipped DIB in a new DIB handle, let the source DIB unchanged
- *
- ************************************************************************/
- HDIB FlipHorzDIB(HDIB hDib)
- {
- WaitCursorBegin();
- // create new DIB
- DWORD dwDataLength = GlobalSize(hDib);
- HDIB hNewDib = GlobalAlloc(GHND, dwDataLength);
- if (! hNewDib)
- {
- WaitCursorEnd();
- return NULL;
- }
- LPSTR lpDIB = (LPSTR)GlobalLock(hNewDib);
- if (lpDIB == NULL)
- {
- WaitCursorEnd();
- return FALSE;
- }
- // old DIB buffer
- LPSTR lpDIBSrc = (LPSTR)GlobalLock(hDib);
- // copy LPBITMAPINFO from old to new
- memcpy(lpDIB, lpDIBSrc, sizeof(BITMAPINFOHEADER)+PaletteSize(lpDIBSrc));
-
- DWORD lSrcWidth = DIBWidth(lpDIBSrc);
- DWORD lSrcHeight = DIBHeight(lpDIBSrc);
- WORD wBitCount = ((LPBITMAPINFOHEADER)lpDIBSrc)->biBitCount;
- // get bytesbytes/pixel, bytes/row
- double fColorBytes = (double)((double)wBitCount/8.0);
- DWORD lSrcRowBytes = WIDTHBYTES(lSrcWidth*((DWORD)wBitCount));
- // bits position
- LPSTR lpOldBits = FindDIBBits(lpDIBSrc);
- LPSTR lpData = FindDIBBits(lpDIB);
- // trandform bits
- DWORD i, j;
- switch (wBitCount)
- {
- case 1:
- for (i=0; i<lSrcHeight; ++i)
- for (j=0; j<lSrcWidth; ++j)
- {
- *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)/8)) &= ~(1<<(7-((lSrcWidth-j-1)%8)));
- *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)/8)) |=
- ((*(lpOldBits+(lSrcRowBytes*i+j/8))<<(j%8))>>7)<<(7-(lSrcWidth-j-1)%8);
- }
- break;
- case 4:
- for (i=0; i<lSrcHeight; ++i)
- {
- for (j=0; j<lSrcWidth; ++j)
- {
- *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)/2)) &= ((lSrcWidth-j-1)%2) ? 0xf0 : 0x0f;
- *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)/2)) |=
- ((*(lpOldBits+(lSrcRowBytes*i+j/2))<<(j%2 ? 4 : 0))>>4)<<(((lSrcWidth-j-1)%2) ? 0 : 4);
- }
- }
- break;
- case 8:
- for (i=0; i<lSrcHeight; ++i)
- for (j=0; j<lSrcWidth; ++j)
- *(lpData+(lSrcRowBytes*i+lSrcWidth-j-1))
- = *(lpOldBits+(lSrcRowBytes*i+j));
- break;
- case 24:
- for (i=0; i<lSrcHeight; ++i)
- for (j=0; j<lSrcWidth; j++)
- {
- *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)*3))
- = *(lpOldBits+(lSrcRowBytes*i+j*3));
- *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)*3)+1)
- = *(lpOldBits+(lSrcRowBytes*i+j*3)+1);
- *(lpData+(lSrcRowBytes*i+(lSrcWidth-j-1)*3)+2)
- = *(lpOldBits+(lSrcRowBytes*i+j*3)+2);
- }
- break;
- }
- GlobalUnlock(hDib);
- GlobalUnlock(hNewDib);
- WaitCursorEnd();
- return hNewDib;
- }
- /*************************************************************************
- *
- * FlipVertDIB()
- *
- * Parameters:
- *
- * HDIB hDIB - handle of DIB to flip vertically
- *
- * Return Value:
- *
- * HDIB - Handle to new DIB
- *
- * Description:
- *
- * This function flip DIB vertically, and return
- * the flipped DIB in a new DIB handle, let the source DIB unchanged
- *
- ************************************************************************/
- HDIB FlipVertDIB(HDIB hDib)
- {
- WaitCursorBegin();
- // create new DIB
- DWORD dwDataLength = GlobalSize(hDib);
- HDIB hNewDib = GlobalAlloc(GHND, dwDataLength);
- if (! hNewDib)
- {
- WaitCursorEnd();
- return NULL;
- }
- LPSTR lpDIB = (LPSTR)GlobalLock(hNewDib);
- if (lpDIB == NULL)
- {
- WaitCursorEnd();
- return FALSE;
- }
- // old DIB buffer
- LPSTR lpDIBSrc = (LPSTR)GlobalLock(hDib);
- // copy LPBITMAPINFO from old to new
- memcpy(lpDIB, lpDIBSrc, sizeof(BITMAPINFOHEADER)+PaletteSize(lpDIBSrc));
-
- DWORD lSrcWidth = DIBWidth(lpDIBSrc);
- DWORD lSrcHeight = DIBHeight(lpDIBSrc);
- WORD wBitCount = ((LPBITMAPINFOHEADER)lpDIBSrc)->biBitCount;
- // get bytesbytes/pixel, bytes/row
- double fColorBytes = (double)((double)wBitCount/8.0);
- DWORD lSrcRowBytes = WIDTHBYTES(lSrcWidth*((DWORD)wBitCount));
- // bits position
- LPSTR lpOldBits = FindDIBBits(lpDIBSrc);
- LPSTR lpData = FindDIBBits(lpDIB);
- // trandform bits
- for (DWORD i=0; i<lSrcHeight; ++i)
- for (DWORD j=0; j<lSrcRowBytes; ++j)
- *(lpData+(lSrcRowBytes*(lSrcHeight-i-1)+j))
- = *(lpOldBits+(lSrcRowBytes*i+j));
- GlobalUnlock(hDib);
- GlobalUnlock(hNewDib);
- WaitCursorEnd();
- return hNewDib;
- }
- /*************************************************************************
- *
- * ChangeDIBSize()
- *
- * Parameters:
- *
- * HDIB hDIB - handle of DIB to zoom
- * int nWidth, int nHeight - new size of DIB
- *
- * Return Value:
- *
- * HDIB - Handle to new DIB
- *
- * Description:
- *
- * This function zoom a DIB to specified size, and return
- * the zoomed DIB in a new DIB handle, let the source DIB unchanged
- *
- ************************************************************************/
- HDIB ChangeDIBSize(HDIB hDIB, int nWidth, int nHeight)
- {
- LPBITMAPINFO lpbmi = NULL;
- LPSTR 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((LPSTR)&(lpSrcDIB->bmiHeader));
- dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader));
- memcpy( lpSourceBits, FindDIBBits((LPSTR)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 = (LPSTR)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize );
- memcpy( lpResult, lpbmi, dwTargetHeaderSize );
- memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize );
-
- // final cleanup
- DeleteObject( hTargetBitmap );
- DeleteObject( hSourceBitmap );
- free( lpbmi );
- GlobalUnlock(hDIB);
- GlobalUnlock(hNewDIB);
- WaitCursorEnd();
-
- return hNewDIB;
- }
- /*************************************************************************
- *
- * ChangeDIBCanvasSize()
- *
- * Parameters:
- *
- * HDIB hDIB - handle of DIB to change
- * int nWidth, int nHeight - new size of DIB
- * int nPosition - position of source DIB in new DIB
- *
- * Return Value:
- *
- * HDIB - Handle to new DIB
- *
- * Description:
- *
- * This function change the canvas of DIB, and put source DIB in the
- * specified position of new DIB (canvas), and return the changed DIB
- * in a new DIB handle, let the source DIB unchanged
- *
- ************************************************************************/
- HDIB ChangeDIBCanvasSize(HDIB hDIB, int nWidth, int nHeight, int nPosition)
- {
- LPBITMAPINFO lpbmi = NULL;
- LPSTR 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((LPSTR)&(lpSrcDIB->bmiHeader));
- dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine((LPSTR)&(lpbmi->bmiHeader));
- memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize );
- lpbmi->bmiHeader.biSizeImage = dwTargetBitsSize;
-
- // Select DIBSections into DCs
- hOldSourceBitmap = (HBITMAP)SelectObject( hSourceDC, hSourceBitmap );
- hOldTargetBitmap = (HBITMAP)SelectObject( hTargetDC, hTargetBitmap );
-
- // old bitmap position in new bitmap
- int x = 0;
- int y = 0;
- int nOldWidth = lpSrcDIB->bmiHeader.biWidth;
- int nOldHeight = lpSrcDIB->bmiHeader.biHeight;
- switch (nPosition)
- {
- case LEFT_UP:
- x = 0;
- y = 0;
- break;
- case CENTER_UP:
- x = (nWidth-nOldWidth)/2;
- y = 0;
- break;
- case RIGHT_UP:
- x = nWidth-nOldWidth;
- y = 0;
- break;
- case LEFT_CENTER:
- x = 0;
- y = (nHeight-nOldHeight)/2;
- break;
- case CENTER_CENTER:
- x = (nWidth-nOldWidth)/2;
- y = (nHeight-nOldHeight)/2;
- break;
- case CENTER_RIGHT:
- x = nWidth-nOldWidth;
- y = (nHeight-nOldHeight)/2;
- break;
- case LEFT_DOWN:
- x = 0;
- y = nHeight-nOldHeight;
- break;
- case CENTER_DOWN:
- x = (nWidth-nOldWidth)/2;
- y = nHeight-nOldHeight;
- break;
- case RIGHT_DOWN:
- x = nWidth-nOldWidth;
- y = nHeight-nOldHeight;
- break;
- }
- // first clear the new bitmap with whitwness
- HBRUSH hBrush = CreateSolidBrush(RGB(255,255,255));
- HPEN hPen = CreatePen(PS_SOLID, 1, RGB(255,255,255));
- HBRUSH hOldBrush = (HBRUSH)SelectObject(hTargetDC, hBrush);
- HPEN hOldPen = (HPEN)SelectObject(hTargetDC, hPen);
- Rectangle(hTargetDC, 0, 0, nWidth, nHeight);
- SelectObject(hTargetDC, hOldBrush);
- SelectObject(hTargetDC, hOldPen);
- // put old bitmap in new bitmap
- BitBlt(hTargetDC, x, y, nOldWidth, nOldHeight, hSourceDC, 0, 0, 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 = (LPSTR)GlobalLock(hNewDIB);//malloc( dwTargetHeaderSize + dwTargetBitsSize );
- memcpy( lpResult, lpbmi, dwTargetHeaderSize );
- memcpy( FindDIBBits( (LPSTR)lpResult ), lpTargetBits, dwTargetBitsSize );
-
- // final cleanup
- DeleteObject( hTargetBitmap );
- DeleteObject( hSourceBitmap );
- free( lpbmi );
- GlobalUnlock(hDIB);
- GlobalUnlock(hNewDIB);
- WaitCursorEnd();
-
- return hNewDIB;
- }
- /*************************************************************************
- *
- * ColorQuantizeDIB()
- *
- * Parameters:
- *
- * HDIB hDIB - handle to global memory with a DIB spec
- * in it followed by the DIB bits
- *
- * UINT nColorBits - reduced DIB color bits
- *
- * UINT nMaxColors - reduced DIB color number
- *
- *
- * Return Value:
- *
- * HDIB - destination DIB handle
- *
- * Description:
- * Perform DIB color quatization
- *
- ************************************************************************/
- HDIB ColorQuantizeDIB(HDIB hDIB, UINT nColorBits, UINT nMaxColors)
- {
- HPALETTE hPal = NULL;
- WaitCursorBegin();
- // color quantization palette
- LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
- hPal = CreateOctreePalette(lpDIB, nMaxColors, nColorBits);
- GlobalUnlock(hDIB);
- // convert DIB to new format
- HDIB hNewDIB = ConvertDIBFormat(hDIB, nColorBits, hPal);
- WaitCursorEnd();
- return hNewDIB;
- }
- /*************************************************************************
- *
- * ConvertToGrayscale()
- *
- * Parameters:
- *
- * HDIB hDIB - handle to global memory with a DIB spec
- * in it followed by the DIB bits
- *
- * int nMethod - method used to convert color to grayscale
- *
- * double fRedWeight - weight of Red
- *
- * double fGreenWeight - weight of Green
- *
- * double fBlueWeight - weight of Blue
- *
- * Return Value:
- *
- * HPALETTE - handle of result grayscale palette
- *
- * Description:
- * Change DIB color table from color to grayscale
- *
- ************************************************************************/
- HPALETTE ConvertToGrayscale(HDIB hDib, int nMethod,
- double fRedWeight, double fGreenWeight, double fBlueWeight)
- {
- if (hDib == NULL)
- return NULL;
- BITMAPINFO* lpbi = (BITMAPINFO *)GlobalLock(hDib);
- if (! lpbi)
- return NULL;
- WaitCursorBegin();
- // get color number
- WORD wNumColors = DIBNumColors((LPSTR)lpbi);
- if (wNumColors == 0) // There is no palette
- {
- GlobalUnlock(hDib);
- // reduce colors to 256
- HDIB hNewDib = ColorQuantizeDIB(hDib, 8, 256);
- LPSTR lpDIB = (LPSTR)GlobalLock(hNewDib);
- if (! lpDIB)
- {
- WaitCursorEnd();
- return NULL;
- }
- DWORD dwSize = DIBlockSize(lpDIB);
- hDib = GlobalReAlloc(hDib, dwSize, 0);
- lpbi = (BITMAPINFO *)GlobalLock(hDib);
- CopyMemory((LPSTR)lpbi, (LPSTR)lpDIB, dwSize);
- GlobalUnlock(hNewDib);
- GlobalFree(hNewDib);
- }
- wNumColors = DIBNumColors((LPSTR)lpbi);
- BYTE GrayValue = 0;
- WORD i;
- switch (nMethod)
- {
- case MAXIMUM_GRAY:
- for (i=0; i<wNumColors; i++)
- {
- GrayValue = max(max(lpbi->bmiColors[i].rgbRed,
- lpbi->bmiColors[i].rgbGreen),
- lpbi->bmiColors[i].rgbBlue);
- lpbi->bmiColors[i].rgbRed =
- lpbi->bmiColors[i].rgbGreen =
- lpbi->bmiColors[i].rgbBlue = GrayValue;
- }
- break;
- case MEAN_GRAY:
- for (i=0; i<wNumColors; i++)
- {
- GrayValue = min(255,
- (lpbi->bmiColors[i].rgbRed +
- lpbi->bmiColors[i].rgbGreen +
- lpbi->bmiColors[i].rgbBlue)/3);
- lpbi->bmiColors[i].rgbRed =
- lpbi->bmiColors[i].rgbGreen =
- lpbi->bmiColors[i].rgbBlue = GrayValue;
- }
- break;
- case WEIGHT_GRAY:
- for (i=0; i<wNumColors; i++)
- {
- GrayValue = min(255,
- (BYTE)(lpbi->bmiColors[i].rgbRed*fRedWeight +
- lpbi->bmiColors[i].rgbGreen*fGreenWeight +
- lpbi->bmiColors[i].rgbBlue*fBlueWeight));
- lpbi->bmiColors[i].rgbRed =
- lpbi->bmiColors[i].rgbGreen =
- lpbi->bmiColors[i].rgbBlue = GrayValue;
- }
- break;
- }
- GlobalUnlock(hDib);
- WaitCursorEnd();
- return CreateDIBPalette(hDib);
- }
- /*************************************************************************
- *
- * AdjustDIBColor()
- *
- * Parameters:
- *
- * HDIB hDIB - handle to global memory with a DIB spec
- * in it followed by the DIB bits
- *
- * int nColorModel - color model type, maybe RGB, HSI, HLS or CMYK
- *
- * int v1, v2, v3 - changed value to color value
- *
- *
- * Return Value:
- *
- * BOOL - TRUE is success, else FALSE
- *
- * Description:
- * Adjust DIB color by RGB, CMYK, HSI, HLS color model
- *
- ************************************************************************/
- BOOL AdjustDIBColor(HDIB hDib, int nColorModel, int v1, int v2, int v3)
- {
- BYTE r, g, b, c, m, y, k;
- int dr, dg, db, dc, dm, dy;
- double dh, ds, dv, dl, h, s, v, l;
- if (hDib == NULL)
- return FALSE;
- BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hDib);
- if (! bmi)
- return FALSE;
- WaitCursorBegin();
- switch (nColorModel)
- {
- case RGB_COLOR:
- dr = v1;
- dg = v2;
- db = v3;
- break;
- case CMYK_COLOR:
- dc = v1;
- dm = v2;
- dy = v3;
- break;
- case HSI_COLOR:
- if (v1 < 0)
- v1 += 360;
- dh = v1;
- ds = v2;
- dv = v3;
- break;
- case HLS_COLOR:
- if (v1 < 0)
- v1 += 360;
- dh = v1;
- dl = v2/100.0;
- ds = v3/100.0;
- break;
- }
- // get color number
- WORD wNumColors = DIBNumColors((LPSTR)bmi);
- if (wNumColors) // There is palette
- {
- WORD i;
- switch (nColorModel)
- {
- case RGB_COLOR:
- for (i=0; i<wNumColors; i++)
- {
- bmi->bmiColors[i].rgbRed = BOUND(bmi->bmiColors[i].rgbRed+dr, 0, 255);
- bmi->bmiColors[i].rgbGreen = BOUND(bmi->bmiColors[i].rgbGreen+dg, 0, 255);
- bmi->bmiColors[i].rgbBlue = BOUND(bmi->bmiColors[i].rgbBlue+db, 0, 255);
- }
- break;
- case CMYK_COLOR:
- for (i=0; i<wNumColors; i++)
- {
- r = bmi->bmiColors[i].rgbRed;
- g = bmi->bmiColors[i].rgbGreen;
- b = bmi->bmiColors[i].rgbBlue;
- RGBtoCMYK(r, g, b, &c, &m, &y, &k);
- c += dc;
- m += dm;
- y += dy;
- CMYKtoRGB(c, m, y, k, &r, &g, &b);
- bmi->bmiColors[i].rgbRed = r;
- bmi->bmiColors[i].rgbGreen = g;
- bmi->bmiColors[i].rgbBlue = b;
- }
- break;
- case HSI_COLOR:
- for (i=0; i<wNumColors; i++)
- {
- r = bmi->bmiColors[i].rgbRed;
- g = bmi->bmiColors[i].rgbGreen;
- b = bmi->bmiColors[i].rgbBlue;
- RGBtoHSI(r, g, b, &h, &s, &v);
- h += dh;
- s += ds;
- v += dv;
- HSItoRGB(h, s, v, &r, &g, &b);
- bmi->bmiColors[i].rgbRed = r;
- bmi->bmiColors[i].rgbGreen = g;
- bmi->bmiColors[i].rgbBlue = b;
- }
- break;
- case HLS_COLOR:
- for (i=0; i<wNumColors; i++)
- {
- r = bmi->bmiColors[i].rgbRed;
- g = bmi->bmiColors[i].rgbGreen;
- b = bmi->bmiColors[i].rgbBlue;
- RGBtoHLS(r, g, b, &h, &l, &s);
- if (h != UNDEFINED)
- h = BOUND(h+dh, 0.0, 360.0);
- l = BOUND(l+dl, 0.0, 1.0);
- s = BOUND(s+ds, 0.0, 1.0);
- HLStoRGB(h, l, s, &r, &g, &b);
- bmi->bmiColors[i].rgbRed = r;
- bmi->bmiColors[i].rgbGreen = g;
- bmi->bmiColors[i].rgbBlue = b;
- }
- break;
- }
- }
- else // No palette
- {
- // bits position
- LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
- LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
- int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
- int nx, ny;
- switch (nColorModel)
- {
- case RGB_COLOR:
- for (ny=0; ny<lpbi->biHeight; ny++)
- {
- for (nx=0; nx<lpbi->biWidth; nx++)
- {
- b = (BYTE)*(lpBits);
- g = (BYTE)*(lpBits+1);
- r = (BYTE)*(lpBits+2);
- *lpBits++ = BOUND(b+db, 0, 255);
- *lpBits++ = BOUND(g+dg, 0, 255);
- *lpBits++ = BOUND(r+dr, 0, 255);
- }
- lpBits += nDelta;
- }
- break;
- case CMYK_COLOR:
- for (ny=0; ny<lpbi->biHeight; ny++)
- {
- for (nx=0; nx<lpbi->biWidth; nx++)
- {
- b = (BYTE)*(lpBits);
- g = (BYTE)*(lpBits+1);
- r = (BYTE)*(lpBits+2);
- RGBtoCMYK(r, g, b, &c, &m, &y, &k);
- c += dc;
- m += dm;
- y += dy;
- CMYKtoRGB(c, m, y, k, &r, &g, &b);
- *lpBits++ = b;
- *lpBits++ = g;
- *lpBits++ = r;
- }
- lpBits += nDelta;
- }
- break;
- case HSI_COLOR:
- for (ny=0; ny<lpbi->biHeight; ny++)
- {
- for (nx=0; nx<lpbi->biWidth; nx++)
- {
- b = (BYTE)*(lpBits);
- g = (BYTE)*(lpBits+1);
- r = (BYTE)*(lpBits+2);
- RGBtoHSI(r, g, b, &h, &s, &v);
- h += dh;
- s += ds;
- v += dv;
- HSItoRGB(h, s, v, &r, &g, &b);
- *lpBits++ = b;
- *lpBits++ = g;
- *lpBits++ = r;
- }
- lpBits += nDelta;
- }
- break;
- case HLS_COLOR:
- for (ny=0; ny<lpbi->biHeight; ny++)
- {
- for (nx=0; nx<lpbi->biWidth; nx++)
- {
- b = (BYTE)*(lpBits);
- g = (BYTE)*(lpBits+1);
- r = (BYTE)*(lpBits+2);
- RGBtoHLS(r, g, b, &h, &l, &s);
- if (h != UNDEFINED)
- h = BOUND(h+dh, 0.0, 360.0);
- l = BOUND(l+dl, 0.0, 1.0);
- s = BOUND(s+ds, 0.0, 1.0);
- HLStoRGB(h, l, s, &r, &g, &b);
- *lpBits++ = b;
- *lpBits++ = g;
- *lpBits++ = r;
- }
- lpBits += nDelta;
- }
- break;
- }
- }
- GlobalUnlock(hDib);
- WaitCursorEnd();
- return TRUE;
- }
- /*************************************************************************
- *
- * SeparateRGBfromDIB()
- *
- * Parameters:
- *
- * HDIB hDIB - handle to global memory with a DIB spec
- * in it followed by the DIB bits
- *
- * int nIndex - index to specify the color to Separate from DIB
- *
- *
- * Return Value:
- *
- * HDIB - the handle of result DIB
- *
- *
- * Description:
- * Separate DIB to R, G, B
- *
- ************************************************************************/
- HDIB SeparateRGBfromDIB(HDIB hDib, int nIndex)
- {
- if (hDib == NULL)
- return NULL;
- HDIB hNewDIB = CopyHandle(hDib);
- if (hNewDIB == NULL)
- return NULL;
- BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hNewDIB);
- if (! bmi)
- return NULL;
- WaitCursorBegin();
- // get color number
- WORD wNumColors = DIBNumColors((LPSTR)bmi);
- if (wNumColors) // There is palette
- {
- for (WORD i=0; i<wNumColors; i++)
- {
- switch (nIndex)
- {
- case SEPARATE_RED:
- bmi->bmiColors[i].rgbGreen = 0;
- bmi->bmiColors[i].rgbBlue = 0;
- break;
- case SEPARATE_GREEN:
- bmi->bmiColors[i].rgbRed = 0;
- bmi->bmiColors[i].rgbBlue = 0;
- break;
- case SEPARATE_BLUE:
- bmi->bmiColors[i].rgbRed = 0;
- bmi->bmiColors[i].rgbGreen = 0;
- break;
- }
- }
- }
- else // No palette
- {
- // bits position
- LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
- LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
- int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
- for (int ny=0; ny<lpbi->biHeight; ny++)
- {
- for (int nx=0; nx<lpbi->biWidth; nx++)
- {
- switch (nIndex)
- {
- case SEPARATE_RED:
- *lpBits++ = 0;
- *lpBits++ = 0;
- lpBits++;
- break;
- case SEPARATE_GREEN:
- *lpBits++ = 0;
- lpBits++;
- *lpBits++ = 0;
- break;
- case SEPARATE_BLUE:
- lpBits++;
- *lpBits++ = 0;
- *lpBits++ = 0;
- break;
- }
- }
- lpBits += nDelta;
- }
- }
- GlobalUnlock(hNewDIB);
- WaitCursorEnd();
- return hNewDIB;
- }
- /*************************************************************************
- *
- * FilteRGBfromDIB()
- *
- * Parameters:
- *
- * HDIB hDIB - handle to global memory with a DIB spec
- * in it followed by the DIB bits
- *
- * int nIndex - index to specify the color to filte from DIB
- *
- *
- * Return Value:
- *
- * HDIB - the handle of result DIB
- *
- *
- * Description:
- * Filte DIB to R, G, B
- *
- ************************************************************************/
- HDIB FilteRGBfromDIB(HDIB hDib, int nIndex)
- {
- if (hDib == NULL)
- return NULL;
- HDIB hNewDIB = CopyHandle(hDib);
- if (hNewDIB == NULL)
- return NULL;
- BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hNewDIB);
- if (! bmi)
- return NULL;
- WaitCursorBegin();
- // get color number
- WORD wNumColors = DIBNumColors((LPSTR)bmi);
- if (wNumColors) // There is palette
- {
- for (WORD i=0; i<wNumColors; i++)
- {
- switch (nIndex)
- {
- case FILTE_RED:
- bmi->bmiColors[i].rgbRed = 0;
- break;
- case FILTE_GREEN:
- bmi->bmiColors[i].rgbGreen = 0;
- break;
- case FILTE_BLUE:
- bmi->bmiColors[i].rgbBlue = 0;
- break;
- }
- }
- }
- else // No palette
- {
- // bits position
- LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
- LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
- int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
- for (int ny=0; ny<lpbi->biHeight; ny++)
- {
- for (int nx=0; nx<lpbi->biWidth; nx++)
- {
- switch (nIndex)
- {
- case FILTE_RED:
- lpBits++;
- lpBits++;
- *lpBits++ = 0;
- break;
- case FILTE_GREEN:
- lpBits++;
- *lpBits++ = 0;
- lpBits++;
- break;
- case FILTE_BLUE:
- *lpBits++ = 0;
- lpBits++;
- lpBits++;
- break;
- }
- }
- lpBits += nDelta;
- }
- }
- GlobalUnlock(hNewDIB);
- WaitCursorEnd();
- return hNewDIB;
- }
- /*************************************************************************
- *
- * AdjustDIBBrightness()
- *
- * Parameters:
- *
- * HDIB hDIB - handle to global memory with a DIB spec
- * in it followed by the DIB bits
- *
- * int v - changed value to color value
- *
- *
- * Return Value:
- *
- * BOOL - TRUE is success, else FALSE
- *
- * Description:
- * Adjust DIB brightness
- *
- ************************************************************************/
- BOOL AdjustDIBBrightness(HDIB hDib, int v)
- {
- if (hDib == NULL)
- return FALSE;
- BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hDib);
- if (! bmi)
- return FALSE;
- WaitCursorBegin();
- // get color number
- WORD wNumColors = DIBNumColors((LPSTR)bmi);
- if (wNumColors) // There is palette
- {
- for (WORD i=0; i<wNumColors; i++)
- {
- ChangeBrightness(v,
- &(bmi->bmiColors[i].rgbRed),
- &(bmi->bmiColors[i].rgbGreen),
- &(bmi->bmiColors[i].rgbBlue));
- }
- }
- else // No palette
- {
- // bits position
- LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
- LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
- int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
- BYTE r, g, b;
- for (int ny=0; ny<lpbi->biHeight; ny++)
- {
- for (int nx=0; nx<lpbi->biWidth; nx++)
- {
- b = (BYTE)*(lpBits);
- g = (BYTE)*(lpBits+1);
- r = (BYTE)*(lpBits+2);
- ChangeBrightness(v, &r, &g, &b);
- *lpBits++ = b;
- *lpBits++ = g;
- *lpBits++ = r;
- }
- lpBits += nDelta;
- }
- }
- GlobalUnlock(hDib);
- WaitCursorEnd();
- return TRUE;
- }
- /*************************************************************************
- *
- * AdjustDIBContrast()
- *
- * Parameters:
- *
- * HDIB hDIB - handle to global memory with a DIB spec
- * in it followed by the DIB bits
- *
- * int v - changed value to color value
- *
- *
- * Return Value:
- *
- * BOOL - TRUE is success, else FALSE
- *
- * Description:
- * Adjust DIB contrast
- *
- ************************************************************************/
- BOOL AdjustDIBContrast(HDIB hDib, int v)
- {
- if (hDib == NULL)
- return FALSE;
- BITMAPINFO *bmi = (BITMAPINFO *)GlobalLock(hDib);
- if (! bmi)
- return FALSE;
- WaitCursorBegin();
- // get color number
- WORD wNumColors = DIBNumColors((LPSTR)bmi);
- if (wNumColors) // There is palette
- {
- for (WORD i=0; i<wNumColors; i++)
- {
- ChangeContrast(v,
- &(bmi->bmiColors[i].rgbRed),
- &(bmi->bmiColors[i].rgbGreen),
- &(bmi->bmiColors[i].rgbBlue));
- }
- }
- else // No palette
- {
- // bits position
- LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)bmi;
- LPSTR lpBits = (LPSTR)lpbi + lpbi->biSize;
- int nDelta = WIDTHBYTES(lpbi->biBitCount*lpbi->biWidth) - lpbi->biWidth*lpbi->biBitCount/8;
- BYTE r, g, b;
- for (int ny=0; ny<lpbi->biHeight; ny++)
- {
- for (int nx=0; nx<lpbi->biWidth; nx++)
- {
- b = (BYTE)*(lpBits);
- g = (BYTE)*(lpBits+1);
- r = (BYTE)*(lpBits+2);
- ChangeContrast(v, &r, &g, &b);
- *lpBits++ = b;
- *lpBits++ = g;
- *lpBits++ = r;
- }
- lpBits += nDelta;
- }
- }
- GlobalUnlock(hDib);
- WaitCursorEnd();
- return TRUE;
- }
- /*************************************************************************
- *
- * HSItoRGB()
- *
- * Parameters:
- *
- * h, s, i - input h, s, i value
- *
- * r, g, b - output r, g, b value
- *
- *
- * Return Value: none
- *
- *
- * Description:
- * Change HSI color to RGB color
- *
- ************************************************************************/
- void HSItoRGB(double h, double s, double i, BYTE *r, BYTE *g, BYTE *b)
- {
- double V1 = s * cos(h);
- double V2 = s * sin(h);
- int iR = (int)( 0.816496*V2 + 0.57735*i);
- int iG = (int)( 0.7071 *V1 - 0.40824*V2 + 0.57735*i);
- int iB = (int)(-0.7071 *V1 - 0.40824*V2 + 0.57735*i);
- *r = BOUND(iR, 0, 255);
- *g = BOUND(iG, 0, 255);
- *b = BOUND(iB, 0, 255);
- }
- /*************************************************************************
- *
- * RGBtoHSI()
- *
- * Parameters:
- *
- * r, g, b - input r, g, b value
- *
- * h, s, i - output h, s, i value
- *
- *
- * Return Value: none
- *
- *
- * Description:
- * Change RGB color to HSI color
- *
- ************************************************************************/
- void RGBtoHSI(BYTE r, BYTE g, BYTE b, double *h, double *s, double *i)
- {
- double V1 = 0.7071*((double)g-(double)b);
- double V2 = 0.816496*(double)r-0.40824*((double)g+(double)b);
- *h = atan2(V1, V2);
- *s = sqrt(V1*V1+V2*V2);
- *i = 0.57735*((double)r+(double)g+(double)b);
- }
- // local function used in HLStoRGB
- double Value(double n1, double n2, double hue)
- {
- if (hue > 360.0)
- hue -= 360.0;
- else if (hue < 0.0)
- hue += 360.0;
-
- if (hue < 60.0)
- return (n1+(n2-n1)*hue/60.0);
- else if (hue < 180.0)
- return n2;
- else if (hue < 240.0)
- return (n1+(n2-n1)*(240.0-hue)/60.0);
- else
- return n1;
- }
- /*************************************************************************
- *
- * HLStoRGB()
- *
- * Parameters:
- *
- * h, l, s - input h, l, s value
- *
- * r, g, b - output r, g, b value
- *
- *
- * Return Value: none
- *
- *
- * Description:
- * Change HLS color to RGB color
- *
- ************************************************************************/
- void HLStoRGB(double h, double l, double s, BYTE *r, BYTE *g, BYTE *b)
- {
- double m1, m2;
- double R, G, B;
- if (l <= 0.5)
- m2 = l*(1.0+s);
- else
- m2 = l+s-l*s;
- m1 = 2.0*l-m2;
- if (s == 0)
- {
- if (h == UNDEFINED)
- R = G = B = l;
- else // error!!
- R = G = B = 0.0;
- }
- else
- {
- R = Value(m1, m2, h+120.0);
- G = Value(m1, m2, h);
- B = Value(m1, m2, h-120.0);
- }
- int iR = (int)(R*255.0);
- int iG = (int)(G*255.0);
- int iB = (int)(B*255.0);
- *r = (BYTE)BOUND(iR, 0, 255);
- *g = (BYTE)BOUND(iG, 0, 255);
- *b = (BYTE)BOUND(iB, 0, 255);
- }
- /*************************************************************************
- *
- * RGBtoHLS()
- *
- * Parameters:
- *
- * r, g, b - input r, g, b value
- *
- * h, l, s - output h, l, s value
- *
- *
- * Return Value: none
- *
- *
- * Description:
- * Change RGB color to HLS color
- *
- ************************************************************************/
- void RGBtoHLS(BYTE r, BYTE g, BYTE b, double *h, double *l, double *s)
- {
- double mx, mn, delta;
- double R, G, B;
- R = (double)r/255.0;
- G = (double)g/255.0;
- B = (double)b/255.0;
- mx = max(R, max(G, B));
- mn = min(R, min(G, B));
- *l = (mx+mn)/2.0;
- if (mx == mn)
- {
- *s = 0.0;
- *h = UNDEFINED; // undefined!
- }
- else
- {
- delta = mx-mn;
- if (*l < 0.5)
- *s = delta/(mx+mn);
- else
- *s = delta/(2.0-mx-mn);
- if (R == mx)
- *h = (G-B)/delta;
- else if (G == mx)
- *h = 2.0+(B-R)/delta;
- else if (B == mx)
- *h = 4.0+(R-G)/delta;
- *h *= 60.0;
- if (*h < 0.0)
- *h += 360.0;
- else if (*h > 360.0)
- *h -= 360.0;
- }
- }
- /*************************************************************************
- *
- * CMYKtoRGB()
- *
- * Parameters:
- *
- * c, m, y, k - input c, m, y, k value
- *
- * r, g, b - output r, g, b value
- *
- *
- * Return Value: none
- *
- *
- * Description:
- * Change CMYK color to RGB color
- *
- ************************************************************************/
- void CMYKtoRGB(BYTE c, BYTE m, BYTE y, BYTE k, BYTE *r, BYTE *g, BYTE *b)
- {
- c += k;
- m += k;
- y += k;
- *r = 255 - c;
- *g = 255 - m;
- *b = 255 - y;
- }
- /*************************************************************************
- *
- * RGBtoCMYK()
- *
- * Parameters:
- *
- * r, g, b - input r, g, b value
- *
- * c, m, y, k - output c, m, y, k value
- *
- *
- * Return Value: none
- *
- *
- * Description:
- * Change RGB color to CMYK color
- *
- ************************************************************************/
- void RGBtoCMYK(BYTE r, BYTE g, BYTE b, BYTE *c, BYTE *m, BYTE *y, BYTE *k)
- {
- *c = 255 - r;
- *m = 255 - g;
- *y = 255 - b;
- *k = min(*c, min(*m, *y));
- *c -= *k;
- *m -= *k;
- *y -= *k;
- }
- // IncreaseContrast
- void IncreaseContrast(BYTE *pByte, const int Low, const int High, const float Grad)
- {
- if (*pByte <= Low)
- *pByte = 0;
- else if ((Low < *pByte) && (*pByte < High))
- *pByte = (BYTE)( (*pByte - Low) / Grad);
- else // pElem->rgbGreen >= High
- *pByte = 255;
- }
- // DecreaseContrast
- void DecreaseContrast(BYTE *pByte, const int Level, const float Grad)
- {
- ASSERT(pByte);
- ASSERT(Grad != 0.0);
- *pByte = (BYTE) ( ((int) (*pByte / Grad)) - Level);
- }
- /*************************************************************************
- *
- * ChangeContrast()
- *
- * Parameters:
- *
- * int nDelta - delta value to R, G, B
- *
- * r, g, b - r, g, b value to change
- *
- *
- * Return Value: none
- *
- *
- * Description:
- * Change contrast
- *
- ************************************************************************/
- void ChangeContrast(int nDelta, BYTE *r, BYTE *g, BYTE *b)
- {
- if (nDelta >= 0)
- {
- int Low = 0 + nDelta;
- int High = 255 - nDelta;
- float Grad= ((float)(High - Low)) / 255;
- IncreaseContrast(r, Low, High, Grad);
- IncreaseContrast(g, Low, High, Grad);
- IncreaseContrast(b, Low, High, Grad);
- }
- else
- {
- float Grad = 255 / (255 + (float)nDelta + (float)nDelta);
- DecreaseContrast(r, nDelta, Grad);
- DecreaseContrast(g, nDelta, Grad);
- DecreaseContrast(b, nDelta, Grad);
- }
- }
- /*************************************************************************
- *
- * ChangeBrightness()
- *
- * Parameters:
- *
- * int nDelta - delta value to R, G, B
- *
- * r, g, b - r, g, b value to change
- *
- *
- * Return Value: none
- *
- *
- * Description:
- * Change brightness
- *
- ************************************************************************/
- void ChangeBrightness(int nDelta, BYTE *r, BYTE *g, BYTE *b)
- {
- int R = *r + nDelta;
- int G = *g + nDelta;
- int B = *b + nDelta;
- *r = (BYTE)BOUND(R, 0, 255);
- *g = (BYTE)BOUND(G, 0, 255);
- *b = (BYTE)BOUND(B, 0, 255);
- }
- ///////////////////// local used only !!! /////////////////////////////
- // macros used to dither
- #define ALIGN_DWORD(x) (((x)+3)/4 * 4) // Double word alignment macro
- // Macros used to facilitate RGB pixel access for dithering
- #define GetRGBPixel(Addr, Red, Green, Blue)
- Blue = (int) *(Addr);
- Green = (int) *(Addr+1);
- Red = (int) *(Addr+2);
- #define PutRGBPixel(Addr, Red, Green, Blue)
- Red = (Red<0) ? 0 : Red;
- Red = (Red>255) ? 255 : Red;
- Green = (Green<0) ? 0 : Green;
- Green = (Green>255) ? 255 : Green;
- Blue = (Blue<0) ? 0 : Blue;
- Blue = (Blue>255) ? 255 : Blue;
- *(Addr) = (BYTE)Blue;
- *(Addr+1) = (BYTE)Green;
- *(Addr+2) = (BYTE)Red;
- // This is the palette with which all true color images will be
- // displayed when hardware support is unavailable.
- typedef struct
- {
- BYTE Red;
- BYTE Green;
- BYTE Blue;
- } RGBCOLOR;
- RGBCOLOR DitherPalette[256] =
- {
- {0, 0, 0}, {0, 0, 85}, {0, 0, 170}, {0, 0, 255},
- {0, 36, 0}, {0, 36, 85}, {0, 36, 170}, {0, 36, 255},
- {0, 73, 0}, {0, 73, 85}, {0, 73, 170}, {0, 73, 255},
- {0, 109, 0}, {0, 109, 85}, {0, 109, 170}, {0, 109, 255},
- {0, 146, 0}, {0, 146, 85}, {0, 146, 170}, {0, 146, 255},
- {0, 182, 0}, {0, 182, 85}, {0, 182, 170}, {0, 182, 255},
- {0, 219, 0}, {0, 219, 85}, {0, 219, 170}, {0, 219, 255},
- {0, 255, 0}, {0, 255, 85}, {0, 255, 170}, {0, 255, 255},
- {36, 0, 0}, {36, 0, 85}, {36, 0, 170}, {36, 0, 255},
- {36, 36, 0}, {36, 36, 85}, {36, 36, 170}, {36, 36, 255},
- {36, 73, 0}, {36, 73, 85}, {36, 73, 170}, {36, 73, 255},
- {36, 109, 0}, {36, 109, 85}, {36, 109, 170}, {36, 109, 255},
- {36, 146, 0}, {36, 146, 85}, {36, 146, 170}, {36, 146, 255},
- {36, 182, 0}, {36, 182, 85}, {36, 182, 170}, {36, 182, 255},
- {36, 219, 0}, {36, 219, 85}, {36, 219, 170}, {36, 219, 255},
- {36, 255, 0}, {36, 255, 85}, {36, 255, 170}, {36, 255, 255},
- {73, 0, 0}, {73, 0, 85}, {73, 0, 170}, {73, 0, 255},
- {73, 36, 0}, {73, 36, 85}, {73, 36, 170}, {73, 36, 255},
- {73, 73, 0}, {73, 73, 85}, {73, 73, 170}, {73, 73, 255},
- {73, 109, 0}, {73, 109, 85}, {73, 109, 170}, {73, 109, 255},
- {73, 146, 0}, {73, 146, 85}, {73, 146, 170}, {73, 146, 255},
- {73, 182, 0}, {73, 182, 85}, {73, 182, 170}, {73, 182, 255},
- {73, 219, 0}, {73, 219, 85}, {73, 219, 170}, {73, 219, 255},
- {73, 255, 0}, {73, 255, 85}, {73, 255, 170}, {73, 255, 255},
- {109, 0, 0}, {109, 0, 85}, {109, 0, 170}, {109, 0, 255},
- {109, 36, 0}, {109, 36, 85}, {109, 36, 170}, {109, 36, 255},
- {109, 73, 0}, {109, 73, 85}, {109, 73, 170}, {109, 73, 255},
- {109, 109, 0}, {109, 109, 85}, {109, 109, 170}, {109, 109, 255},
- {109, 146, 0}, {109, 146, 85}, {109, 146, 170}, {109, 146, 255},
- {109, 182, 0}, {109, 182, 85}, {109, 182, 170}, {109, 182, 255},
- {109, 219, 0}, {109, 219, 85}, {109, 219, 170}, {109, 219, 255},
- {109, 255, 0}, {109, 255, 85}, {109, 255, 170}, {109, 255, 255},
- {146, 0, 0}, {146, 0, 85}, {146, 0, 170}, {146, 0, 255},
- {146, 36, 0}, {146, 36, 85}, {146, 36, 170}, {146, 36, 255},
- {146, 73, 0}, {146, 73, 85}, {146, 73, 170}, {146, 73, 255},
- {146, 109, 0}, {146, 109, 85}, {146, 109, 170}, {146, 109, 255},
- {146, 146, 0}, {146, 146, 85}, {146, 146, 170}, {146, 146, 255},
- {146, 182, 0}, {146, 182, 85}, {146, 182, 170}, {146, 182, 255},
- {146, 219, 0}, {146, 219, 85}, {146, 219, 170}, {146, 219, 255},
- {146, 255, 0}, {146, 255, 85}, {146, 255, 170}, {146, 255, 255},
- {182, 0, 0}, {182, 0, 85}, {182, 0, 170}, {182, 0, 255},
- {182, 36, 0}, {182, 36, 85}, {182, 36, 170}, {182, 36, 255},
- {182, 73, 0}, {182, 73, 85}, {182, 73, 170}, {182, 73, 255},
- {182, 109, 0}, {182, 109, 85}, {182, 109, 170}, {182, 109, 255},
- {182, 146, 0}, {182, 146, 85}, {182, 146, 170}, {182, 146, 255},
- {182, 182, 0}, {182, 182, 85}, {182, 182, 170}, {182, 182, 255},
- {182, 219, 0}, {182, 219, 85}, {182, 219, 170}, {182, 219, 255},
- {182, 255, 0}, {182, 255, 85}, {182, 255, 170}, {182, 255, 255},
- {219, 0, 0}, {219, 0, 85}, {219, 0, 170}, {219, 0, 255},
- {219, 36, 0}, {219, 36, 85}, {219, 36, 170}, {219, 36, 255},
- {219, 73, 0}, {219, 73, 85}, {219, 73, 170}, {219, 73, 255},
- {219, 109, 0}, {219, 109, 85}, {219, 109, 170}, {219, 109, 255},
- {219, 146, 0}, {219, 146, 85}, {219, 146, 170}, {219, 146, 255},
- {219, 182, 0}, {219, 182, 85}, {219, 182, 170}, {219, 182, 255},
- {219, 219, 0}, {219, 219, 85}, {219, 219, 170}, {219, 219, 255},
- {219, 255, 0}, {219, 255, 85}, {219, 255, 170}, {219, 255, 255},
- {255, 0, 0}, {255, 0, 85}, {255, 0, 170}, {255, 0, 255},
- {255, 36, 0}, {255, 36, 85}, {255, 36, 170}, {255, 36, 255},
- {255, 73, 0}, {255, 73, 85}, {255, 73, 170}, {255, 73, 255},
- {255, 109, 0}, {255, 109, 85}, {255, 109, 170}, {255, 109, 255},
- {255, 146, 0}, {255, 146, 85}, {255, 146, 170}, {255, 146, 255},
- {255, 182, 0}, {255, 182, 85}, {255, 182, 170}, {255, 182, 255},
- {255, 219, 0}, {255, 219, 85}, {255, 219, 170}, {255, 219, 255},
- {255, 255, 0}, {255, 255, 85}, {255, 255, 170}, {255, 255, 255}
- };
- // Define temporary vars as global, try to speedup...
- int TRed, TGreen, TBlue;
- int RedError, GreenError, BlueError;
- BYTE PaletteIndex;
- int BlueOffset;
- LPSTR PixelAddr;
- LPSTR RPixelAddr;
- LPSTR DPixelAddr;
- // Dither a single row of image data
- void DitherLine(WORD Width, LPSTR pLine1, LPSTR pLine2)
- {
- for (register WORD Pixel=0; Pixel < Width; Pixel++)
- {
- // Get the pixel of interest for the dither
- PixelAddr = pLine1 + (Pixel * 3);
- GetRGBPixel(PixelAddr, TRed, TGreen, TBlue);
- // Determine which blue entry from palette to use
- BlueOffset = (TBlue/85);
- if ((TBlue - (BlueOffset * 85)) > 43)
- BlueOffset += 1;
- // Calculate palette entry address from color
- // PaletteIndex = ((TRed/32)*32) + ((TGreen/32)*4) + BlueOffset;
- // For speed we will calculate the color index as follows
- PaletteIndex = (TRed & 0xE0) + ((TGreen >> 5) << 2) + BlueOffset;
- // Store the palette back into the same buffer
- *(pLine1 + Pixel) = PaletteIndex;
- /*
- Pixel is set, now distribute the error to adjacent pixels
- using a modified version of the Floyd-Steinberg algorithm.
- In this implementation the error is distributed as follows
- Pixel
- o 1/2->o
- 1/4 |
- o
- The algorithm is modified to increase performance.
- */
- // Calculate errors between the desired color and color used
- // for this pixel. Actual error / 4. Use pointers for speed.
- BYTE *pColor = (BYTE *) &DitherPalette[PaletteIndex]; // Ptr to color
- RedError = (TRed - *(pColor)) >> 2;
- GreenError = (TGreen - *(pColor+1)) >> 2;
- BlueError = (TBlue - *(pColor+2)) >> 2;
- // Do the pixel directly below target pixel
- DPixelAddr = pLine2 + (Pixel * 3);
- GetRGBPixel(DPixelAddr, TRed, TGreen, TBlue);
- TRed += RedError; // 1/4 error
- TGreen += GreenError;
- TBlue += BlueError;
- PutRGBPixel(DPixelAddr, TRed, TGreen, TBlue);
- // Do the pixel directly to the right
- if (Pixel != Width - 1)
- {
- RPixelAddr = PixelAddr + 3;
- GetRGBPixel(RPixelAddr, TRed, TGreen, TBlue);
- TRed += RedError + RedError; // 1/2 error
- TGreen += GreenError + GreenError;
- TBlue += BlueError + BlueError;
- PutRGBPixel(RPixelAddr, TRed, TGreen, TBlue);
- }
- }
- }
- // This function dithers the image contained in this object. It returns
- // a handle to a global memory block containing the dithered data.
- HGLOBAL DitherImage(LPSTR lpImageData, WORD Width, WORD Height)
- {
- // Calculate width in bytes of a row of RGB data
- WORD BytesPerLine = ALIGN_DWORD(Width * 3); // Source 24 BPP image
- // Calculate width in bytes of a row of palettized data
- WORD BytesPerLineDest = ALIGN_DWORD(Width); // Dest 8 BPP image
- // Allocate two lines of RGB buffer for dithering
- HLOCAL hLine1Buffer = LocalAlloc(LMEM_MOVEABLE, BytesPerLine);
- if (!hLine1Buffer)
- return NULL;
- HLOCAL hLine2Buffer = LocalAlloc(LMEM_MOVEABLE, BytesPerLine);
- if (!hLine2Buffer)
- {
- LocalFree(hLine1Buffer);
- return NULL;
- }
- // Allocate the destination dither buffer
- HGLOBAL hMem = GlobalAlloc(GHND, (DWORD) BytesPerLineDest * Height);
- if (!hMem)
- {
- LocalFree(hLine1Buffer);
- LocalFree(hLine2Buffer);
- return NULL;
- }
- // Now lock the pointers for access
- LPSTR Line1Buffer = (LPSTR) LocalLock(hLine1Buffer);
- LPSTR Line2Buffer = (LPSTR) LocalLock(hLine2Buffer);
- LPSTR lpDitheredRasterData = (LPSTR) GlobalLock(hMem);
- // Move the first two lines of the source image to dither buffers
- memcpy(Line1Buffer, lpImageData, BytesPerLine);
- memcpy(Line2Buffer, lpImageData + BytesPerLine, BytesPerLine);
- for (register WORD Row = 2; Row < Height; Row++)
- {
- DitherLine(Width, Line1Buffer, Line2Buffer);
- // Copy the dithered data in Line1Buffer to destination
- memcpy(lpDitheredRasterData + ((Row-2) * (DWORD) BytesPerLineDest),
- Line1Buffer, BytesPerLineDest);
- // Copy Line2Buffer to Line1Buffer so it can be dithered
- memcpy(Line1Buffer, Line2Buffer, BytesPerLine);
- // Move new data to Line2Buffer
- memcpy(Line2Buffer, lpImageData + (Row * (DWORD) BytesPerLine),
- BytesPerLine);
- }
- // Must complete the two rows in the line buffers
- DitherLine(Width, Line1Buffer, Line2Buffer);
- // Copy the dithered data in Line1Buffer to destination
- memcpy(lpDitheredRasterData + ((Height-2) * (DWORD) BytesPerLineDest),
- Line1Buffer, BytesPerLineDest);
- memcpy(Line1Buffer, Line2Buffer, BytesPerLine);
- DitherLine(Width, Line1Buffer, Line2Buffer);
- // Copy the dithered data in Line1Buffer to destination
- memcpy(lpDitheredRasterData + ((Height-1) * (DWORD) BytesPerLineDest),
- Line1Buffer, BytesPerLineDest);
- // Free the local line buffers
- LocalUnlock(hLine1Buffer);
- LocalFree(hLine1Buffer);
- LocalUnlock(hLine2Buffer);
- LocalFree(hLine2Buffer);
- // Signal all is well
- GlobalUnlock(hMem); // Unlock the dithered raster data
- return hMem; // Return the handle of the data
- }
- ///////////////////// local used only !!! /////////////////////////////
- // create a dithered 8bpp DIB for 24bpp DIB in not true color device
- HDIB CreateDither8BppDIB(HDIB hDIB)
- {
- WaitCursorBegin();
- if (DIBBitCount(hDIB) <= 8)
- {
- WaitCursorEnd();
- return CopyHandle(hDIB);
- }
- // dithering DIB
- LPSTR lpDIB = (LPSTR)GlobalLock(hDIB);
- LPSTR lpBits = FindDIBBits(lpDIB);
- WORD wWidth = (WORD)DIBWidth(lpDIB);
- WORD wHeight = (WORD)DIBHeight(lpDIB);
- HGLOBAL hDitheredBits = DitherImage(lpBits, wWidth, wHeight);
- GlobalUnlock(hDIB);
- if (! hDitheredBits)
- {
- WaitCursorEnd();
- return NULL;
- }
- // create a new 8bpp DIB
- HDIB hNewDib = ChangeDIBFormat(hDIB, 8, BI_RGB);;
- LPBITMAPINFO lpBmi = (LPBITMAPINFO)GlobalLock(hNewDib);
- lpBmi->bmiHeader.biClrUsed = 256;
-
- // set the entries of dither palette to DIB color table
- for (int Index=0; Index < 256; Index++)
- {
- lpBmi->bmiColors[Index].rgbRed = DitherPalette[Index].Red;
- lpBmi->bmiColors[Index].rgbGreen = DitherPalette[Index].Green;
- lpBmi->bmiColors[Index].rgbBlue = DitherPalette[Index].Blue;
- lpBmi->bmiColors[Index].rgbReserved = 0;
- }
- // copy dithered image bits to hNewDib
- DWORD dwSize = GlobalSize(hDitheredBits);
- LPSTR lpDitheredBits = (LPSTR)GlobalLock(hDitheredBits);
- LPSTR lpNewBits = FindDIBBits((LPSTR)lpBmi);
- memcpy(lpNewBits, lpDitheredBits, dwSize);
- // cleanup
- GlobalUnlock(hDitheredBits);
- GlobalFree(hDitheredBits);
- GlobalUnlock(hNewDib);
- // map dithered DIB to dither palette
- HPALETTE hPal = CreateDitherPalette();
- MapDIBColorsToPalette(hNewDib, hPal);
- DeleteObject(hPal);
- WaitCursorEnd();
- return hNewDib;
- }
- // create dither palette for dithering
- HPALETTE CreateDitherPalette()
- {
- LPLOGPALETTE lpPal; // pointer to a logical palette
- HANDLE hLogPal; // handle to a logical palette
- HPALETTE hPal = NULL; // handle to a palette
- HPALETTE hPalette = NULL; // handle to a palette
- int i; // loop index, number of colors in color table
-
- // allocate memory block for logical palette
- hLogPal = GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * 256);
- // if not enough memory, clean up and return NULL
- if (!hLogPal)
- return NULL;
- // lock memory block and get pointer to it
- lpPal = (LPLOGPALETTE)GlobalLock(hLogPal);
- // set version and number of palette entries
- lpPal->palVersion = PALVERSION;
- lpPal->palNumEntries = 256;
- // set dithered palette value
- for (i = 0; i < 256; i++)
- {
- lpPal->palPalEntry[i].peRed = DitherPalette[i].Red;
- lpPal->palPalEntry[i].peGreen = DitherPalette[i].Green;
- lpPal->palPalEntry[i].peBlue = DitherPalette[i].Blue;
- lpPal->palPalEntry[i].peFlags = 0;
- }
- // create the palette and get handle to it
- hPal = CreatePalette(lpPal);
- // if error getting handle to palette, clean up and return NULL
- if (!hPal)
- {
- GlobalUnlock(hLogPal);
- GlobalFree(hLogPal);
- return NULL;
- }
- // clean up
-
- GlobalUnlock(hLogPal);
- GlobalFree(hLogPal);
- // change palette to identify palette
-
- hPalette = CreateIdentifyPalette(hPal);
- // return idenify palette is it's ok
- // else return the original one
- if (hPalette)
- {
- DeleteObject(hPal);
- return hPalette;
- }
- else
- return hPal;
- }
- /*************************************************************************
- *
- * CreateOctreePalette()
- *
- * Parameters:
- *
- * HDIB hDIB - Handle to source DIB
- * UINT nMaxColors - destination color number
- * UINT nColorBits - destination color bits
- *
- * Return Value:
- *
- * HPALETTE - Handle to the result palette
- *
- * Description:
- *
- * This function use Octree color quantization algorithm to get
- * optimal m kinds of color to represent total n kinds of color
- * in a DIB, and use the m kinds of color to build a palette.
- * With the palette, we can display the DIB on reasonable accuracy.
- *
- ************************************************************************/
- HPALETTE CreateOctreePalette(HDIB hDIB, UINT nMaxColors, UINT nColorBits)
- {
- HANDLE hImage;
- hImage = DIBToDIBSection(hDIB);
- if (! hImage)
- return NULL;
- return BuildOctreePalette(hImage, nMaxColors, nColorBits);
- }
- /*************************************************************************
- *
- * CreateOctreePalette()
- *
- * Parameters:
- *
- * LPBYTE lpDIB - Pointer to DIB data buffer
- * UINT nMaxColors - destination color number
- * UINT nColorBits - destination color bits
- *
- * Return Value:
- *
- * HPALETTE - Handle to the result palette
- *
- * Description:
- *
- * This function use Octree color quantization algorithm to get
- * optimal m kinds of color to represent total n kinds of color
- * in a DIB, and use the m kinds of color to build a palette.
- * With the palette, we can display the DIB on reasonable accuracy.
- *
- ************************************************************************/
- HPALETTE CreateOctreePalette(LPSTR lpDIB, UINT nMaxColors, UINT nColorBits)
- {
- HANDLE hImage;
- hImage = DIBToDIBSection(lpDIB);
- if (! hImage)
- return NULL;
- return BuildOctreePalette(hImage, nMaxColors, nColorBits);
- }
- // local function to build optimal palette from DIBSection
- /*
- HPALETTE CreateOctreePalette(HDIB hDIB, UINT nMaxColors, UINT nColorBits)
- {
- DIBSECTION ds;
- int i, j, nPad;
- BYTE* pbBits;
- WORD* pwBits;
- DWORD* pdwBits;
- DWORD rmask, gmask, bmask;
- int rright, gright, bright;
- int rleft, gleft, bleft;
- BYTE r, g, b;
- WORD wColor;
- DWORD dwColor, dwSize;
- LOGPALETTE* plp;
- HPALETTE hPalette;
- NODE* pTree;
- UINT nLeafCount, nIndex;
- NODE* pReducibleNodes[9];
- HDC hdc;
- BYTE* pBuffer = NULL;
- BITMAPINFO bmi;
- // Initialize octree variables
- pTree = NULL;
- nLeafCount = 0;
- if (nColorBits > 8) // Just in case
- return NULL;
- for (i=0; i<=(int) nColorBits; i++)
- pReducibleNodes[i] = NULL;
- // Scan the DIB and build the octree
- GetObject (hImage, sizeof (ds), &ds);
- nPad = ds.dsBm.bmWidthBytes - (((ds.dsBmih.biWidth *
- ds.dsBmih.biBitCount) + 7) / 8);
- switch (ds.dsBmih.biBitCount) {
- case 1: // 1-bit DIB
- case 4: // 4-bit DIB
- case 8: // 8-bit DIB
- //
- // The strategy here is to use ::GetDIBits to convert the
- // image into a 24-bit DIB one scan line at a time. A pleasant
- // side effect of using ::GetDIBits in this manner is that RLE-
- // encoded 4-bit and 8-bit DIBs will be uncompressed. //
- hdc = GetDC (NULL);
- pBuffer = new BYTE[ds.dsBmih.biWidth * 3];
- ZeroMemory (&bmi, sizeof (bmi));
- bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = ds.dsBmih.biWidth;
- bmi.bmiHeader.biHeight = ds.dsBmih.biHeight;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 24;
- bmi.bmiHeader.biCompression = BI_RGB;
- for (i=0; i<ds.dsBmih.biHeight; i++)
- {
- GetDIBits (hdc, (HBITMAP) hImage, i, 1, pBuffer, &bmi,
- DIB_RGB_COLORS);
- pbBits = pBuffer;
- for (j=0; j<ds.dsBmih.biWidth; j++)
- {
- b = *pbBits++;
- g = *pbBits++;
- r = *pbBits++;
- AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
- pReducibleNodes);
- while (nLeafCount > nMaxColors)
- ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
- }
- }
- ReleaseDC (NULL, hdc);
- break;
-
- case 16: // One case for 16-bit DIBs
- if (ds.dsBmih.biCompression == BI_BITFIELDS) {
- rmask = ds.dsBitfields[0];
- gmask = ds.dsBitfields[1];
- bmask = ds.dsBitfields[2];
- }
- else {
- rmask = 0x7C00;
- gmask = 0x03E0;
- bmask = 0x001F;
- }
- rright = GetRightShiftCount (rmask);
- gright = GetRightShiftCount (gmask);
- bright = GetRightShiftCount (bmask);
- rleft = GetLeftShiftCount (rmask);
- gleft = GetLeftShiftCount (gmask);
- bleft = GetLeftShiftCount (bmask);
- pwBits = (WORD*) ds.dsBm.bmBits;
- for (i=0; i<ds.dsBmih.biHeight; i++) {
- for (j=0; j<ds.dsBmih.biWidth; j++) {
- wColor = *pwBits++;
- b = (BYTE) (((wColor & (WORD) bmask) >> bright) << bleft);
- g = (BYTE) (((wColor & (WORD) gmask) >> gright) << gleft);
- r = (BYTE) (((wColor & (WORD) rmask) >> rright) << rleft);
- AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
- pReducibleNodes);
- while (nLeafCount > nMaxColors)
- ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
- }
- pwBits = (WORD*) (((BYTE*) pwBits) + nPad);
- }
- break;
- case 24: // Another for 24-bit DIBs
- pbBits = (BYTE*) ds.dsBm.bmBits;
- for (i=0; i<ds.dsBmih.biHeight; i++) {
- for (j=0; j<ds.dsBmih.biWidth; j++) {
- b = *pbBits++;
- g = *pbBits++;
- r = *pbBits++;
- AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
- pReducibleNodes);
- while (nLeafCount > nMaxColors)
- ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
- }
- pbBits += nPad;
- }
- break;
- case 32: // And another for 32-bit DIBs
- if (ds.dsBmih.biCompression == BI_BITFIELDS) {
- rmask = ds.dsBitfields[0];
- gmask = ds.dsBitfields[1];
- bmask = ds.dsBitfields[2];
- }
- else {
- rmask = 0x00FF0000;
- gmask = 0x0000FF00;
- bmask = 0x000000FF;
- }
- rright = GetRightShiftCount (rmask);
- gright = GetRightShiftCount (gmask);
- bright = GetRightShiftCount (bmask);
- pdwBits = (DWORD*) ds.dsBm.bmBits;
- for (i=0; i<ds.dsBmih.biHeight; i++) {
- for (j=0; j<ds.dsBmih.biWidth; j++) {
- dwColor = *pdwBits++;
- b = (BYTE) ((dwColor & bmask) >> bright);
- g = (BYTE) ((dwColor & gmask) >> gright);
- r = (BYTE) ((dwColor & rmask) >> rright);
- AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
- pReducibleNodes);
- while (nLeafCount > nMaxColors)
- ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
- }
- pdwBits = (DWORD*) (((BYTE*) pdwBits) + nPad);
- }
- break;
- default: // DIB must be 16, 24, or 32-bit!
- return NULL;
- }
- // cleanup
- //if (pBuffer)
- // delete[] pBuffer;
- if (nLeafCount > nMaxColors)
- { // Sanity check
- DeleteTree (&pTree);
- return NULL;
- }
- // Create a logical palette from the colors in the octree
- dwSize = sizeof (LOGPALETTE) + ((nLeafCount - 1) * sizeof (PALETTEENTRY));
- if ((plp = (LOGPALETTE*) HeapAlloc (GetProcessHeap (), 0,
- dwSize)) == NULL) {
- DeleteTree (&pTree);
- return NULL;
- }
- plp->palVersion = 0x300;
- plp->palNumEntries = (WORD) nLeafCount;
- nIndex = 0;
- GetPaletteColors (pTree, plp->palPalEntry, &nIndex);
- hPalette = CreatePalette (plp);
- HeapFree (GetProcessHeap (), 0, plp);
- DeleteTree (&pTree);
- return hPalette;
- }
- */
- HPALETTE BuildOctreePalette(HANDLE hImage, UINT nMaxColors, UINT nColorBits)
- {
- DIBSECTION ds;
- int i, j, nPad;
- BYTE* pbBits;
- WORD* pwBits;
- DWORD* pdwBits;
- DWORD rmask, gmask, bmask;
- int rright, gright, bright;
- int rleft, gleft, bleft;
- BYTE r, g, b;
- WORD wColor;
- DWORD dwColor, dwSize;
- LOGPALETTE* plp;
- HPALETTE hPalette;
- NODE* pTree;
- UINT nLeafCount, nIndex;
- NODE* pReducibleNodes[9];
- HDC hdc;
- BYTE* pBuffer = NULL;
- BITMAPINFO bmi;
- // Initialize octree variables
- pTree = NULL;
- nLeafCount = 0;
- if (nColorBits > 8) // Just in case
- return NULL;
- for (i=0; i<=(int) nColorBits; i++)
- pReducibleNodes[i] = NULL;
- // Scan the DIB and build the octree
- GetObject (hImage, sizeof (ds), &ds);
- nPad = ds.dsBm.bmWidthBytes - (((ds.dsBmih.biWidth *
- ds.dsBmih.biBitCount) + 7) / 8);
- switch (ds.dsBmih.biBitCount) {
- case 1: // 1-bit DIB
- case 4: // 4-bit DIB
- case 8: // 8-bit DIB
- //
- // The strategy here is to use ::GetDIBits to convert the
- // image into a 24-bit DIB one scan line at a time. A pleasant
- // side effect of using ::GetDIBits in this manner is that RLE-
- // encoded 4-bit and 8-bit DIBs will be uncompressed. //
- hdc = GetDC (NULL);
- pBuffer = new BYTE[ds.dsBmih.biWidth * 3];
- ZeroMemory (&bmi, sizeof (bmi));
- bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
- bmi.bmiHeader.biWidth = ds.dsBmih.biWidth;
- bmi.bmiHeader.biHeight = ds.dsBmih.biHeight;
- bmi.bmiHeader.biPlanes = 1;
- bmi.bmiHeader.biBitCount = 24;
- bmi.bmiHeader.biCompression = BI_RGB;
- for (i=0; i<ds.dsBmih.biHeight; i++)
- {
- GetDIBits (hdc, (HBITMAP) hImage, i, 1, pBuffer, &bmi,
- DIB_RGB_COLORS);
- pbBits = pBuffer;
- for (j=0; j<ds.dsBmih.biWidth; j++)
- {
- b = *pbBits++;
- g = *pbBits++;
- r = *pbBits++;
- AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
- pReducibleNodes);
- while (nLeafCount > nMaxColors)
- ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
- }
- }
- ReleaseDC (NULL, hdc);
- break;
-
- case 16: // One case for 16-bit DIBs
- if (ds.dsBmih.biCompression == BI_BITFIELDS) {
- rmask = ds.dsBitfields[0];
- gmask = ds.dsBitfields[1];
- bmask = ds.dsBitfields[2];
- }
- else {
- rmask = 0x7C00;
- gmask = 0x03E0;
- bmask = 0x001F;
- }
- rright = GetRightShiftCount (rmask);
- gright = GetRightShiftCount (gmask);
- bright = GetRightShiftCount (bmask);
- rleft = GetLeftShiftCount (rmask);
- gleft = GetLeftShiftCount (gmask);
- bleft = GetLeftShiftCount (bmask);
- pwBits = (WORD*) ds.dsBm.bmBits;
- for (i=0; i<ds.dsBmih.biHeight; i++) {
- for (j=0; j<ds.dsBmih.biWidth; j++) {
- wColor = *pwBits++;
- b = (BYTE) (((wColor & (WORD) bmask) >> bright) << bleft);
- g = (BYTE) (((wColor & (WORD) gmask) >> gright) << gleft);
- r = (BYTE) (((wColor & (WORD) rmask) >> rright) << rleft);
- AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
- pReducibleNodes);
- while (nLeafCount > nMaxColors)
- ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
- }
- pwBits = (WORD*) (((BYTE*) pwBits) + nPad);
- }
- break;
- case 24: // Another for 24-bit DIBs
- pbBits = (BYTE*) ds.dsBm.bmBits;
- for (i=0; i<ds.dsBmih.biHeight; i++) {
- for (j=0; j<ds.dsBmih.biWidth; j++) {
- b = *pbBits++;
- g = *pbBits++;
- r = *pbBits++;
- AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
- pReducibleNodes);
- while (nLeafCount > nMaxColors)
- ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
- }
- pbBits += nPad;
- }
- break;
- case 32: // And another for 32-bit DIBs
- if (ds.dsBmih.biCompression == BI_BITFIELDS) {
- rmask = ds.dsBitfields[0];
- gmask = ds.dsBitfields[1];
- bmask = ds.dsBitfields[2];
- }
- else {
- rmask = 0x00FF0000;
- gmask = 0x0000FF00;
- bmask = 0x000000FF;
- }
- rright = GetRightShiftCount (rmask);
- gright = GetRightShiftCount (gmask);
- bright = GetRightShiftCount (bmask);
- pdwBits = (DWORD*) ds.dsBm.bmBits;
- for (i=0; i<ds.dsBmih.biHeight; i++) {
- for (j=0; j<ds.dsBmih.biWidth; j++) {
- dwColor = *pdwBits++;
- b = (BYTE) ((dwColor & bmask) >> bright);
- g = (BYTE) ((dwColor & gmask) >> gright);
- r = (BYTE) ((dwColor & rmask) >> rright);
- AddColor (&pTree, r, g, b, nColorBits, 0, &nLeafCount,
- pReducibleNodes);
- while (nLeafCount > nMaxColors)
- ReduceTree (nColorBits, &nLeafCount, pReducibleNodes);
- }
- pdwBits = (DWORD*) (((BYTE*) pdwBits) + nPad);
- }
- break;
- default: // DIB must be 16, 24, or 32-bit!
- return NULL;
- }
- // cleanup
- //if (pBuffer)
- // delete[] pBuffer;
- if (nLeafCount > nMaxColors)
- { // Sanity check
- DeleteTree (&pTree);
- return NULL;
- }
- // Create a logical palette from the colors in the octree
- dwSize = sizeof (LOGPALETTE) + ((nLeafCount - 1) * sizeof (PALETTEENTRY));
- if ((plp = (LOGPALETTE*) HeapAlloc (GetProcessHeap (), 0,
- dwSize)) == NULL) {
- DeleteTree (&pTree);
- return NULL;
- }
- plp->palVersion = 0x300;
- plp->palNumEntries = (WORD) nLeafCount;
- nIndex = 0;
- GetPaletteColors (pTree, plp->palPalEntry, &nIndex);
- hPalette = CreatePalette (plp);
- HeapFree (GetProcessHeap (), 0, plp);
- DeleteTree (&pTree);
- return hPalette;
- }
- /*************************************************************************
- *
- * PaintDIB()
- *
- * Parameters:
- *
- * HDC hDC - DC to do output to
- *
- * LPRECT lpDCRect - rectangle on DC to do output to
- *
- * HDIB hDIB - handle to global memory with a DIB spec
- * in it followed by the DIB bits
- *
- * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
- *
- * CPalette* pPal - pointer to CPalette containing DIB's palette
- *
- * Return Value:
- *
- * BOOL - TRUE if DIB was drawn, FALSE otherwise
- *
- * Description:
- * Painting routine for a DIB. Calls StretchDIBits() or
- * SetDIBitsToDevice() to paint the DIB. The DIB is
- * output to the specified DC, at the coordinates given
- * in lpDCRect. The area of the DIB to be output is
- * given by lpDIBRect.
- *
- ************************************************************************/
- BOOL WINAPI PaintDIB(HDC hDC,
- LPRECT lpDCRect,
- HDIB hDIB,
- LPRECT lpDIBRect,
- CPalette* pPal)
- {
- LPSTR lpDIBHdr; // Pointer to BITMAPINFOHEADER
- LPSTR lpDIBBits; // Pointer to DIB bits
- BOOL bSuccess=FALSE; // Success/fail flag
- HPALETTE hPal=NULL; // Our DIB's palette
- HPALETTE hOldPal=NULL; // Previous palette
-
- /* Check for valid DIB handle */
- if (hDIB == NULL)
- return FALSE;
-
- /* Lock down the DIB, and get a pointer to the beginning of the bit
- * buffer
- */
- lpDIBHdr = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
- lpDIBBits = ::FindDIBBits(lpDIBHdr);
-
- // Get the DIB's palette, then select it into DC
- if (pPal != NULL)
- {
- hPal = (HPALETTE) pPal->m_hObject;
-
- // Select as background since we have
- // already realized in forground if needed
- hOldPal = ::SelectPalette(hDC, hPal, TRUE);
- }
-
- /* Make sure to use the stretching mode best for color pictures */
- ::SetStretchBltMode(hDC, COLORONCOLOR);
-
- /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
- if ((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) &&
- (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
- {
- bSuccess = ::SetDIBitsToDevice(hDC, // hDC
- lpDCRect->left, // DestX
- lpDCRect->top, // DestY
- RECTWIDTH(lpDCRect), // nDestWidth
- RECTHEIGHT(lpDCRect), // nDestHeight
- lpDIBRect->left, // SrcX
- // (int)DIBHeight(lpDIBHdr) -
- lpDIBRect->top,// -
- // RECTHEIGHT(lpDIBRect), // SrcY
- 0, // nStartScan
- (WORD)abs(DIBHeight(lpDIBHdr)), // nNumScans
- lpDIBBits, // lpBits
- (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
- DIB_RGB_COLORS); // wUsage
- }
- else
- {
- bSuccess = ::StretchDIBits(hDC, // hDC
- lpDCRect->left, // DestX
- lpDCRect->top, // DestY
- RECTWIDTH(lpDCRect), // nDestWidth
- RECTHEIGHT(lpDCRect), // nDestHeight
- lpDIBRect->left, // SrcX
- lpDIBRect->top, // SrcY
- RECTWIDTH(lpDIBRect), // wSrcWidth
- RECTHEIGHT(lpDIBRect), // wSrcHeight
- lpDIBBits, // lpBits
- (LPBITMAPINFO)lpDIBHdr, // lpBitsInfo
- DIB_RGB_COLORS, // wUsage
- SRCCOPY); // dwROP
- }
-
- ::GlobalUnlock((HGLOBAL) hDIB);
-
- /* Reselect old palette */
- if (hOldPal != NULL)
- {
- ::SelectPalette(hDC, hOldPal, TRUE);
- }
-
- return bSuccess;
- }
- /*************************************************************************
- *
- * CreateDIBPalette()
- *
- * Parameter:
- *
- * HDIB hDIB - specifies the DIB
- *
- * Return Value:
- *
- * HPALETTE - specifies the palette
- *
- * Description:
- *
- * This function creates a palette from a DIB by allocating memory for the
- * logical palette, reading and storing the colors from the DIB's color table
- * into the logical palette, creating a palette from this logical palette,
- * and then returning the palette's handle. This allows the DIB to be
- * displayed using the best possible colors (important for DIBs with 256 or
- * more colors).
- *
- ************************************************************************/
- BOOL WINAPI CreateDIBPalette(HDIB hDIB, CPalette* pPal)
- {
- LPLOGPALETTE lpPal; // pointer to a logical palette
- HANDLE hLogPal; // handle to a logical palette
- HPALETTE hPal = NULL; // handle to a palette
- int i; // loop index
- WORD wNumColors; // number of colors in color table
- LPSTR lpbi; // pointer to packed-DIB
- LPBITMAPINFO lpbmi; // pointer to BITMAPINFO structure (Win3.0)
- LPBITMAPCOREINFO lpbmc; // pointer to BITMAPCOREINFO structure (old)
- BOOL bWinStyleDIB; // flag which signifies whether this is a Win3.0 DIB
- BOOL bResult = FALSE;
-
- /* if handle to DIB is invalid, return FALSE */
-
- if (hDIB == NULL)
- return FALSE;
-
- lpbi = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
-
- /* get pointer to BITMAPINFO (Win 3.0) */
- lpbmi = (LPBITMAPINFO)lpbi;
-
- /* get pointer to BITMAPCOREINFO (old 1.x) */
- lpbmc = (LPBITMAPCOREINFO)lpbi;
-
- /* get the number of colors in the DIB */
- wNumColors = ::DIBNumColors(lpbi);
-
- if (wNumColors != 0)
- {
- /* allocate memory block for logical palette */
- hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE)
- + sizeof(PALETTEENTRY)
- * wNumColors);
-
- /* if not enough memory, clean up and return NULL */
- if (hLogPal == 0)
- {
- ::GlobalUnlock((HGLOBAL) hDIB);
- return FALSE;
- }
-
- lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
-
- /* set version and number of palette entries */
- lpPal->palVersion = PALVERSION;
- lpPal->palNumEntries = (WORD)wNumColors;
-
- /* is this a Win 3.0 DIB? */
- bWinStyleDIB = IS_WIN30_DIB(lpbi);
- for (i = 0; i < (int)wNumColors; i++)
- {
- if (bWinStyleDIB)
- {
- lpPal->palPalEntry[i].peRed = lpbmi->bmiColors[i].rgbRed;
- lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
- lpPal->palPalEntry[i].peBlue = lpbmi->bmiColors[i].rgbBlue;
- lpPal->palPalEntry[i].peFlags = 0;
- }
- else
- {
- lpPal->palPalEntry[i].peRed = lpbmc->bmciColors[i].rgbtRed;
- lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
- lpPal->palPalEntry[i].peBlue = lpbmc->bmciColors[i].rgbtBlue;
- lpPal->palPalEntry[i].peFlags = 0;
- }
- }
-
- /* create the palette and get handle to it */
- bResult = pPal->CreatePalette(lpPal);
- ::GlobalUnlock((HGLOBAL) hLogPal);
- ::GlobalFree((HGLOBAL) hLogPal);
- }
-
- ::GlobalUnlock((HGLOBAL) hDIB);
-
- return bResult;
- }
- /*************************************************************************
- *
- * FindDIBBits()
- *
- * Parameter:
- *
- * LPSTR lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * LPSTR - pointer to the DIB bits
- *
- * Description:
- *
- * This function calculates the address of the DIB's bits and returns a
- * pointer to the DIB bits.
- *
- ************************************************************************/
- LPSTR WINAPI FindDIBBits(LPSTR lpbi)
- {
- return (lpbi + *(LPDWORD)lpbi + ::PaletteSize(lpbi));
- }
- /*************************************************************************
- *
- * DIBWidth()
- *
- * Parameter:
- *
- * LPSTR lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * DWORD - width of the DIB
- *
- * Description:
- *
- * This function gets the width of the DIB from the BITMAPINFOHEADER
- * width field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
- * width field if it is an other-style DIB.
- *
- ************************************************************************/
- long WINAPI DIBWidth(LPSTR lpDIB)
- {
- LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
- LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB
-
- /* point to the header (whether Win 3.0 and old) */
-
- lpbmi = (LPBITMAPINFOHEADER)lpDIB;
- lpbmc = (LPBITMAPCOREHEADER)lpDIB;
-
- /* return the DIB width if it is a Win 3.0 DIB */
- if (IS_WIN30_DIB(lpDIB))
- return lpbmi->biWidth;
- else /* it is an other-style DIB, so return its width */
- return (long)lpbmc->bcWidth;
- }
- /*************************************************************************
- *
- * DIBHeight()
- *
- * Parameter:
- *
- * LPSTR lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * DWORD - height of the DIB
- *
- * Description:
- *
- * This function gets the height of the DIB from the BITMAPINFOHEADER
- * height field if it is a Windows 3.0-style DIB or from the BITMAPCOREHEADER
- * height field if it is an other-style DIB.
- *
- ************************************************************************/
- long WINAPI DIBHeight(LPSTR lpDIB)
- {
- LPBITMAPINFOHEADER lpbmi; // pointer to a Win 3.0-style DIB
- LPBITMAPCOREHEADER lpbmc; // pointer to an other-style DIB
-
- /* point to the header (whether old or Win 3.0 */
-
- lpbmi = (LPBITMAPINFOHEADER)lpDIB;
- lpbmc = (LPBITMAPCOREHEADER)lpDIB;
-
- /* return the DIB height if it is a Win 3.0 DIB */
- if (IS_WIN30_DIB(lpDIB))
- return lpbmi->biHeight;
- else /* it is an other-style DIB, so return its height */
- return (long)lpbmc->bcHeight;
- }
- /*************************************************************************
- *
- * PaletteSize()
- *
- * Parameter:
- *
- * LPSTR lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * WORD - size of the color palette of the DIB
- *
- * Description:
- *
- * This function gets the size required to store the DIB's palette by
- * multiplying the number of colors by the size of an RGBQUAD (for a
- * Windows 3.0-style DIB) or by the size of an RGBTRIPLE (for an other-
- * style DIB).
- *
- ************************************************************************/
- WORD WINAPI PaletteSize(LPSTR lpbi)
- {
- /* calculate the size required by the palette */
- if (IS_WIN30_DIB (lpbi))
- return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBQUAD));
- else
- return (WORD)(::DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
- }
- /*************************************************************************
- *
- * DIBNumColors()
- *
- * Parameter:
- *
- * LPSTR lpbi - pointer to packed-DIB memory block
- *
- * Return Value:
- *
- * WORD - number of colors in the color table
- *
- * Description:
- *
- * This function calculates the number of colors in the DIB's color table
- * by finding the bits per pixel for the DIB (whether Win3.0 or other-style
- * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
- * if 24, no colors in color table.
- *
- ************************************************************************/
- WORD WINAPI DIBNumColors(LPSTR lpbi)
- {
- WORD wBitCount; // DIB bit count
-
- /* If this is a Windows-style DIB, the number of colors in the
- * color table can be less than the number of bits per pixel
- * allows for (i.e. lpbi->biClrUsed can be set to some value).
- * If this is the case, return the appropriate value.
- */
-
- if (IS_WIN30_DIB(lpbi))
- {
- DWORD dwClrUsed;
-
- dwClrUsed = ((LPBITMAPINFOHEADER)lpbi)->biClrUsed;
- if (dwClrUsed != 0)
- return (WORD)dwClrUsed;
- }
-
- /* Calculate the number of colors in the color table based on
- * the number of bits per pixel for the DIB.
- */
- if (IS_WIN30_DIB(lpbi))
- wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
- else
- wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
-
- /* return number of colors based on bits per pixel */
- switch (wBitCount)
- {
- case 1:
- return 2;
- case 4:
- return 16;
- case 8:
- return 256;
- default:
- return 0;
- }
- }
- //////////////////////////////////////////////////////////////////////////
- //// Clipboard support
- //---------------------------------------------------------------------
- //
- // Function: CopyHandle (from SDK DibView sample clipbrd.c)
- //
- // Purpose: Makes a copy of the given global memory block. Returns
- // a handle to the new memory block (NULL on error).
- //
- // Routine stolen verbatim out of ShowDIB.
- //
- // Parms: h == Handle to global memory to duplicate.
- //
- // Returns: Handle to new global memory block.
- //
- //---------------------------------------------------------------------
- HGLOBAL WINAPI CopyHandle (HGLOBAL h)
- {
- if (h == NULL)
- return NULL;
-
- DWORD dwLen = ::GlobalSize((HGLOBAL) h);
- HGLOBAL hCopy = ::GlobalAlloc(GHND, dwLen);
-
- if (hCopy != NULL)
- {
- void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
- void* lp = ::GlobalLock((HGLOBAL) h);
- memcpy(lpCopy, lp, dwLen);
- ::GlobalUnlock(hCopy);
- ::GlobalUnlock(h);
- }
-
- return hCopy;
- }
- //DIBFILEAPI
- // Source file for Device-Independent Bitmap (DIB) API. Provides
- // the following functions:
- //
- // SaveDIB() - Saves the specified dib in a file
- // ReadDIBFile() - Loads a DIB from a file
- //
- //
- /*
- * Dib Header Marker - used in writing DIBs to files
- */
- #define DIB_HEADER_MARKER ((WORD) ('M' << 8) | 'B')
- /*************************************************************************
- *
- * SaveDIB()
- *
- * Saves the specified DIB into the specified CFile. The CFile
- * is opened and closed by the caller.
- *
- * Parameters:
- *
- * HDIB hDib - Handle to the dib to save
- *
- * CFile& file - open CFile used to save DIB
- *
- * Return value: TRUE if successful, else FALSE or CFileException
- *
- *************************************************************************/
- BOOL WINAPI SaveDIB(HDIB hDib, CFile& file)
- {
- BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
- LPBITMAPINFOHEADER lpBI; // Pointer to DIB info structure
- DWORD dwDIBSize;
-
- if (hDib == NULL)
- return FALSE;
-
- /*
- * Get a pointer to the DIB memory, the first of which contains
- * a BITMAPINFO structure
- */
- lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
- if (lpBI == NULL)
- return FALSE;
-
- if (!IS_WIN30_DIB(lpBI))
- {
- ::GlobalUnlock((HGLOBAL) hDib);
- return FALSE; // It's an other-style DIB (save not supported)
- }
-
- /*
- * Fill in the fields of the file header
- */
-
- /* Fill in file type (first 2 bytes must be "BM" for a bitmap) */
- bmfHdr.bfType = DIB_HEADER_MARKER; // "BM"
-
- // Calculating the size of the DIB is a bit tricky (if we want to
- // do it right). The easiest way to do this is to call GlobalSize()
- // on our global handle, but since the size of our global memory may have
- // been padded a few bytes, we may end up writing out a few too
- // many bytes to the file (which may cause problems with some apps).
- //
- // So, instead let's calculate the size manually (if we can)
- //
- // First, find size of header plus size of color table. Since the
- // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
- // the size of the structure, let's use this.
-
- dwDIBSize = *(LPDWORD)lpBI + ::PaletteSize((LPSTR)lpBI); // Partial Calculation
-
- // Now calculate the size of the image
-
- if ((lpBI->biCompression == BI_RLE8) || (lpBI->biCompression == BI_RLE4))
- {
- // It's an RLE bitmap, we can't calculate size, so trust the
- // biSizeImage field
-
- dwDIBSize += lpBI->biSizeImage;
- }
- else
- {
- DWORD dwBmBitsSize; // Size of Bitmap Bits only
-
- // It's not RLE, so size is Width (DWORD aligned) * Height
-
- dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD)lpBI->biBitCount)) * abs(lpBI->biHeight);
-
- dwDIBSize += dwBmBitsSize;
-
- // Now, since we have calculated the correct size, why don't we
- // fill in the biSizeImage field (this will fix any .BMP files which
- // have this field incorrect).
-
- lpBI->biSizeImage = dwBmBitsSize;
- }
-
- // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
-
- bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
- bmfHdr.bfReserved1 = 0;
- bmfHdr.bfReserved2 = 0;
-
- /*
- * Now, calculate the offset the actual bitmap bits will be in
- * the file -- It's the Bitmap file header plus the DIB header,
- * plus the size of the color table.
- */
- bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize
- + PaletteSize((LPSTR)lpBI);
- TRY
- {
- // Write the file header
- file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
- //
- // Write the DIB header and the bits
- //
- file.Write(lpBI, dwDIBSize);
- }
- CATCH (CFileException, e)
- {
- ::GlobalUnlock((HGLOBAL) hDib);
- THROW_LAST();
- }
- END_CATCH
-
- ::GlobalUnlock((HGLOBAL) hDib);
- return TRUE;
- }
- /*************************************************************************
- *
- Function: ReadDIBFile (CFile&)
- Purpose: Reads in the specified DIB file into a global chunk of
- memory.
- Returns: A handle to a dib (hDIB) if successful.
- NULL if an error occurs.
- Comments: BITMAPFILEHEADER is stripped off of the DIB. Everything
- from the end of the BITMAPFILEHEADER structure on is
- returned in the global memory handle.
- *
- *************************************************************************/
- HDIB WINAPI ReadDIBFile(CFile& file)
- {
- BITMAPFILEHEADER bmfHeader;
- DWORD dwBitsSize;
- HDIB hDIB;
- LPSTR pDIB;
-
- /*
- * get length of DIB in bytes for use when reading
- */
-
- dwBitsSize = file.GetLength();
-
- /*
- * Go read the DIB file header and check if it's valid.
- */
- if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
- return NULL;
-
- if (bmfHeader.bfType != DIB_HEADER_MARKER)
- return NULL;
-
- /*
- * Allocate memory for DIB
- */
- hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize);
- if (hDIB == 0)
- {
- return NULL;
- }
- pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
-
- /*
- * Go read the bits.
- */
- if (file.Read(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)) !=
- dwBitsSize - sizeof(BITMAPFILEHEADER) )
- {
- ::GlobalUnlock((HGLOBAL) hDIB);
- ::GlobalFree((HGLOBAL) hDIB);
- return NULL;
- }
- ::GlobalUnlock((HGLOBAL) hDIB);
- return hDIB;
- }
- //My Add
- ////*************************************/////////////
- HDIB WINAPI ShowJPEG(int iWidth,int iHeight,const BYTE* pByte)
- {
- ASSERT(NULL != pByte);
- HDIB hDIB = NULL;
- DWORD iSize = iWidth;
- // iWidth = (iWidth + 3) / 4 * 4;
- int iDiff = iWidth - iSize;
- iSize = abs(iWidth * iHeight)*3;
-
- hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
- iSize + sizeof(BITMAPINFOHEADER));
- if(hDIB==NULL)
- {
- CString szMsg("DIB is too large!");
- // szMsg.LoadString(IDS_DIB_TOO_BIG);
- MessageBox(NULL, szMsg, NULL, MB_ICONINFORMATION | MB_OK);
- return NULL;
- }
-
- BYTE *pDIB = (BYTE*)GlobalLock(hDIB);
- LPBITMAPINFO lpbi = (LPBITMAPINFO)pDIB;
- //intialize bitmapheader
- lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- lpbi->bmiHeader.biWidth = iWidth;
- lpbi->bmiHeader.biHeight = iHeight;
- lpbi->bmiHeader.biPlanes = 1;
- lpbi->bmiHeader.biBitCount= 24;
- lpbi->bmiHeader.biCompression = BI_RGB;
- lpbi->bmiHeader.biSizeImage = 0;
- lpbi->bmiHeader.biXPelsPerMeter = 0;
- lpbi->bmiHeader.biYPelsPerMeter = 0;
- lpbi->bmiHeader.biClrUsed = 0;
- lpbi->bmiHeader.biClrImportant = 0;
-
- pDIB += (sizeof(BITMAPINFOHEADER));
-
- // if(iDiff == 0)
- {
- memcpy(pDIB,pByte,iSize);
- }
- // else
- // {
- // iDiff = (iWidth - iDiff)*3;
- // iWidth *= 3;
- // for(i=0; i<abs(iHeight); i++)
- // {
- // memcpy(pDIB , pByte,iDiff);
- // pDIB += iWidth;
- // pByte += iDiff;
- // }
- // }
- //
- GlobalUnlock(hDIB);
-
- return hDIB;
- }
- HDIB WINAPI GenBmp(int iWidth,int iHeight,int iBits, const BYTE* pByte)
- {
- ASSERT(NULL != pByte);
- HDIB hDIB=NULL;
- DWORD iSize = iWidth;
- iWidth = (iWidth + 3) / 4 * 4;
- int iDiff = iWidth - iSize;
- iSize = abs(iWidth * iHeight);
- int iColors = (int)pow(2, iBits);
-
- if(iBits < 24)
- {
- hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
- iSize + sizeof(BITMAPINFOHEADER) + iColors * sizeof(RGBQUAD));
- }
- else
- {
- hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, iSize);
- }
- if(hDIB==NULL)
- {
- CString szMsg("DIB is too large!");
- // szMsg.LoadString(IDS_DIB_TOO_BIG);
- MessageBox(NULL, szMsg, NULL, MB_ICONINFORMATION | MB_OK);
- return NULL;
- }
-
- BYTE *pDIB = (BYTE*)GlobalLock(hDIB);
- LPBITMAPINFO lpbi = (LPBITMAPINFO)pDIB;
- //intialize bitmapheader
- lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- lpbi->bmiHeader.biWidth = iWidth;
- lpbi->bmiHeader.biHeight = iHeight;
- lpbi->bmiHeader.biPlanes = 1;
- lpbi->bmiHeader.biBitCount = iBits;
- lpbi->bmiHeader.biCompression = BI_RGB;
- lpbi->bmiHeader.biSizeImage = iSize;
- lpbi->bmiHeader.biXPelsPerMeter = 0;
- lpbi->bmiHeader.biYPelsPerMeter = 0;
- lpbi->bmiHeader.biClrUsed = 0;
- lpbi->bmiHeader.biClrImportant = 0;
-
- //fill in the color table
- int i;
- if(iBits < 24)
- {
- for(i = 0; i < iColors; i++)
- {
- lpbi->bmiColors[i].rgbRed=(BYTE)i;
- lpbi->bmiColors[i].rgbGreen=(BYTE)i;
- lpbi->bmiColors[i].rgbBlue=(BYTE)i;
- lpbi->bmiColors[i].rgbReserved=0;
- }
- pDIB += (sizeof(BITMAPINFOHEADER) + iColors * sizeof(RGBQUAD));
- }
-
- if(iDiff == 0)
- {
- memcpy(pDIB, pByte, int(iSize * (double)iBits / 8.0));
- }
- else
- {
- iDiff = int((iWidth - iDiff) * (double)iBits / 8.0);
- iWidth = (int)(iWidth * (double)iBits / 8.0);
- for(i = 0; i < abs(iHeight); i++)
- {
- memcpy(pDIB , pByte, iDiff);
- pDIB += iWidth;
- pByte += iDiff;
- }
- }
- GlobalUnlock(hDIB);
-
- return hDIB;
- }
- HDIB WINAPI ShowColorBytes(int iWidth,int iHeight, const BYTE* pByte)
- {
- ASSERT(NULL != pByte);
- DWORD iSize = iWidth;
- iWidth = (iWidth + 3) / 4 * 4;
- int iDiff = iWidth - iSize;
- iSize = abs(iWidth * iHeight);
-
- HDIB hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,
- iSize + sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
- if(hDIB == NULL)
- {
- CString szMsg("DIB is too large!");
- // szMsg.LoadString(IDS_DIB_TOO_BIG);
- MessageBox(NULL, szMsg, NULL, MB_ICONINFORMATION | MB_OK);
- return NULL;
- }
-
- BYTE *pDIB = (BYTE*)GlobalLock(hDIB);
- LPBITMAPINFO lpbi = (LPBITMAPINFO)pDIB;
- //intialize bitmapheader
- lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
- lpbi->bmiHeader.biWidth = iWidth;
- lpbi->bmiHeader.biHeight = iHeight;
- lpbi->bmiHeader.biPlanes = 1;
- lpbi->bmiHeader.biBitCount = 8;
- lpbi->bmiHeader.biCompression = BI_RGB;
- lpbi->bmiHeader.biSizeImage = iSize;
- lpbi->bmiHeader.biXPelsPerMeter = 0;
- lpbi->bmiHeader.biYPelsPerMeter = 0;
- lpbi->bmiHeader.biClrUsed = 0;
- lpbi->bmiHeader.biClrImportant = 0;
-
- //fill in the color table
- for(int i = 0; i < 1; i++)
- {
- lpbi->bmiColors[i].rgbRed =12;
- lpbi->bmiColors[i].rgbGreen = (BYTE)(100);
- lpbi->bmiColors[i].rgbBlue = (BYTE)(240);
- lpbi->bmiColors[i].rgbReserved = 0;
- }
- for(i = 1; i < 25; i++)
- {
- lpbi->bmiColors[i].rgbRed = i/2;
- lpbi->bmiColors[i].rgbGreen = 9*(i-1)+30;
- lpbi->bmiColors[i].rgbBlue = i;
- lpbi->bmiColors[i].rgbReserved = 0;
- }
- for(i=25;i<100;i++)
- {
- lpbi->bmiColors[i].rgbRed = BYTE((i-25)+i*1.7);
- lpbi->bmiColors[i].rgbGreen = BYTE((i-25)+i*1.7);
- lpbi->bmiColors[i].rgbBlue = 0;
- lpbi->bmiColors[i].rgbReserved = 0;
- }
- for(i=100;i<255;i++)
- {
- lpbi->bmiColors[i].rgbRed = BYTE(i/2+(i-100)*0.8);
- lpbi->bmiColors[i].rgbGreen = BYTE(i/2+(i-100)*0.8);
- lpbi->bmiColors[i].rgbBlue = BYTE(i/2+(i-100)*0.8);
- lpbi->bmiColors[i].rgbReserved = 0;
- } pDIB += (sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
- if(iDiff == 0)
- {
- memcpy(pDIB, pByte, iSize);
- }
- else
- {
- iDiff = iWidth - iDiff;
- for(i = 0; i < abs(iHeight); i++)
- {
- memcpy(pDIB , pByte, iDiff);
- pDIB += iWidth;
- pByte += iDiff;
- }
- }
- GlobalUnlock(hDIB);
-
- return hDIB;
- }
- BOOL WINAPI DIBToPCX256(LPSTR lpDIB, LPCTSTR lpszPathName)
- {
- CFile file;
- if(!file.Open(lpszPathName, CFile::modeWrite | CFile::modeCreate | CFile::shareExclusive))
- {
- AfxMessageBox("打开指定PCX文件时失败!", MB_ICONINFORMATION | MB_OK);
- return FALSE;
- }
- // 循环变量
- LONG i;
- LONG j;
-
- // DIB高度
- WORD wHeight;
-
- // DIB宽度
- WORD wWidth;
-
- // 中间变量
- BYTE bChar1;
- BYTE bChar2;
-
- // 指向源图像象素的指针
- BYTE * lpSrc;
-
- // 指向编码后图像数据的指针
- BYTE * lpDst;
-
- // 图像每行的字节数
- LONG lLineBytes;
-
- // 重复像素计数
- int iCount;
-
- // 缓冲区已使用的字节数
- DWORD dwBuffUsed;
-
- // 指向DIB象素指针
- LPSTR lpDIBBits;
-
- // 获取DIB高度
- wHeight = (WORD) DIBHeight(lpDIB);
-
- // 获取DIB宽度
- wWidth = (WORD) DIBWidth(lpDIB);
-
- // 找到DIB图像象素起始位置
- lpDIBBits = FindDIBBits(lpDIB);
-
- // 计算图像每行的字节数
- lLineBytes = WIDTHBYTES(wWidth * 8);
-
-
- //*************************************************************************
- // PCX文件头
- PCXHEADER pcxHdr;
-
- // 给文件头赋值
-
- // PCX标识码
- pcxHdr.bManufacturer = 0x0A;
-
- // PCX版本号
- pcxHdr.bVersion = 5;
-
- // PCX编码方式(1表示RLE编码)
- pcxHdr.bEncoding = 1;
-
- // 像素位数(256色为8位)
- pcxHdr.bBpp = 8;
-
- // 图像相对于屏幕的左上角X坐标(以像素为单位)
- pcxHdr.wLeft = 0;
-
- // 图像相对于屏幕的左上角Y坐标(以像素为单位)
- pcxHdr.wTop = 0;
-
- // 图像相对于屏幕的右下角X坐标(以像素为单位)
- pcxHdr.wRight = wWidth - 1;
-
- // 图像相对于屏幕的右下角Y坐标(以像素为单位)
- pcxHdr.wBottom = wHeight - 1;
-
- // 图像的水平分辨率
- pcxHdr.wXResolution = wWidth;
-
- // 图像的垂直分辨率
- pcxHdr.wYResolution = wHeight;
-
- // 调色板数据(对于256色PCX无意义,直接赋值为0)
- for (i = 0; i < 48; i ++)
- {
- pcxHdr.bPalette[i] = 0;
- }
-
- // 保留域,设定为0。
- pcxHdr.bReserved = 0;
-
- // 图像色彩平面数目(对于256色PCX设定为1)。
- pcxHdr.bPlanes = 1;
-
- // 图像的宽度(字节为单位),必须为偶数。
- // if ((wWidth & 1) == 0)
- // {
- pcxHdr.wLineBytes = wWidth;
- // }
- // else
- // {
- // pcxHdr.wLineBytes = wWidth + 1;
- // }
-
- // 图像调色板的类型,1表示彩色或者单色图像,2表示图像是灰度图。
- pcxHdr.wPaletteType = 1;
-
- // 制作该图像的屏幕宽度(像素为单位)
- pcxHdr.wSrcWidth = 0;
-
- // 制作该图像的屏幕高度(像素为单位)
- pcxHdr.wSrcDepth = 0;
-
- // 保留域,取值设定为0。
- for (i = 0; i < 54; i ++)
- {
- pcxHdr.bFiller[i] = 0;
- }
-
- // 写入文件头
- file.Write((LPSTR)&pcxHdr, sizeof(PCXHEADER));
-
- //*******************************************************************************
- // 开始编码
-
- // 开辟一片缓冲区(2被原始图像大小)以保存编码结果
- lpDst = new BYTE[wHeight * wWidth * 2];
-
- // 指明当前已经用了多少缓冲区(字节数)
- dwBuffUsed = 0;
-
- // 每行
- for (i = 0; i < wHeight; i++)
- {
- // 指向DIB第i行,第0个象素的指针
- lpSrc = (BYTE *)lpDIBBits + lLineBytes * (wHeight - 1 - i);
-
- // 给bChar1赋值
- bChar1 = *lpSrc;
-
- // 设置iCount为1
- iCount = 1;
-
- // 剩余列
- for (j = 1; j < wWidth; j ++)
- {
- // 指向DIB第i行,第j个象素的指针
- lpSrc++;
-
- // 读取下一个像素
- bChar2 = *lpSrc;
-
- // 判断是否和bChar1相同并且iCount < 63
- if ((bChar1 == bChar2) && (iCount < 63))
- {
- // 相同,计数加1
- iCount ++;
-
- // 继续读下一个
- }
- else
- {
- // 不同,或者iCount = 63
-
- // 写入缓冲区
- if ((iCount > 1) || (bChar1 >= 0xC0))
- {
- // 保存码长信息
- lpDst[dwBuffUsed] = iCount | 0xC0;
-
- // 保存bChar1
- lpDst[dwBuffUsed + 1] = bChar1;
-
- // 更新dwBuffUsed
- dwBuffUsed += 2;
- }
- else
- {
- // 直接保存该值
- lpDst[dwBuffUsed] = bChar1;
-
- // 更新dwBuffUsed
- dwBuffUsed ++;
- }
-
- // 重新给bChar1赋值
- bChar1 = bChar2;
-
- // 设置iCount为1
- iCount = 1;
- }
- }
-
- // 保存每行最后一部分编码
- if ((iCount > 1) || (bChar1 >= 0xC0))
- {
- // 保存码长信息
- lpDst[dwBuffUsed] = iCount | 0xC0;
-
- // 保存bChar1
- lpDst[dwBuffUsed + 1] = bChar1;
-
- // 更新dwBuffUsed
- dwBuffUsed += 2;
- }
- else
- {
- // 直接保存该值
- lpDst[dwBuffUsed] = bChar1;
-
- // 更新dwBuffUsed
- dwBuffUsed ++;
- }
- }
-
- // 写入编码结果
- file.WriteHuge((LPSTR)lpDst, dwBuffUsed);
-
- // 释放内存
- delete lpDst;
-
- //**************************************************************************
- // 写入调色板信息
-
- // 指向BITMAPINFO结构的指针(Win3.0)
- LPBITMAPINFO lpbmi;
-
- // 指向BITMAPCOREINFO结构的指针
- LPBITMAPCOREINFO lpbmc;
-
- // 表明是否是Win3.0 DIB的标记
- BOOL bWinStyleDIB;
-
- // 开辟一片缓冲区以保存调色板
- lpDst = new BYTE[769];
-
- // 调色板起始字节
- * lpDst = 0x0C;
-
- // 获取指向BITMAPINFO结构的指针(Win3.0)
- lpbmi = (LPBITMAPINFO)lpDIB;
-
- // 获取指向BITMAPCOREINFO结构的指针
- lpbmc = (LPBITMAPCOREINFO)lpDIB;
-
- // 判断是否是WIN3.0的DIB
- bWinStyleDIB = IS_WIN30_DIB(lpDIB);
-
- // 读取当前DIB调色板
- for (i = 0; i < 256; i ++)
- {
- if (bWinStyleDIB)
- {
- // 读取DIB调色板红色分量
- lpDst[i * 3 + 1] = lpbmi->bmiColors[i].rgbRed;
-
- // 读取DIB调色板绿色分量
- lpDst[i * 3 + 2] = lpbmi->bmiColors[i].rgbGreen;
-
- // 读取DIB调色板蓝色分量
- lpDst[i * 3 + 3] = lpbmi->bmiColors[i].rgbBlue;
- }
- else
- {
- // 读取DIB调色板红色分量
- lpDst[i * 3 + 1] = lpbmc->bmciColors[i].rgbtRed;
-
- // 读取DIB调色板绿色分量
- lpDst[i * 3 + 2] = lpbmc->bmciColors[i].rgbtGreen;
-
- // 读取DIB调色板蓝色分量
- lpDst[i * 3 + 3] = lpbmc->bmciColors[i].rgbtBlue;
- }
- }
-
- // 写入调色板信息
- file.Write((LPSTR)lpDst, 769);
- delete lpDst;
- file.Close();
-
- // 返回
- return TRUE;
- }
- /*************************************************************************
- *
- * 函数名称:
- * ReadPCX256()
- *
- * 参数:
- * CFile& file - 要读取的文件
- *
- * 返回值:
- * HDIB - 成功返回DIB的句柄,否则返回NULL。
- *
- * 说明:
- * 该函数将读取指定的256色PCX文件。将读取的结果保存在一个未压缩
- * 编码的DIB对象中。
- *
- *************************************************************************/
- HDIB WINAPI ReadPCX256(LPCTSTR lpszPathName)
- {
- CFile file;
- if(!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite))
- {
- AfxMessageBox("打开指定PCX文件时失败!", MB_ICONINFORMATION | MB_OK);
- return NULL;
- }
- // PCX文件头
- PCXHEADER pcxHdr;
-
- // DIB大小(字节数)
- DWORD dwDIBSize;
-
- // DIB句柄
- HDIB hDIB;
-
- // DIB指针
- LPSTR pDIB;
-
- // 循环变量
- LONG i;
- LONG j;
-
- // 重复像素计数
- int iCount;
-
- // DIB高度
- WORD wHeight;
-
- // DIB宽度
- WORD wWidth;
-
- // 图像每行的字节数
- LONG lLineBytes;
-
- // 中间变量
- BYTE bChar;
-
- // 指向源图像象素的指针
- BYTE * lpSrc;
-
- // 指向编码后图像数据的指针
- BYTE * lpDst;
-
- // 临时指针
- BYTE * lpTemp;
-
- // 尝试读取PCX文件头
- if (file.Read((LPSTR)&pcxHdr, sizeof(PCXHEADER)) != sizeof(PCXHEADER))
- {
- // 大小不对,返回NULL。
- file.Close();
- return NULL;
- }
-
- // 判断是否是256色PCX文件,检查第一个字节是否是0x0A,
- if ((pcxHdr.bManufacturer != 0x0A) || (pcxHdr.bBpp != 8) || (pcxHdr.bPlanes != 1))
- {
- // 非256色PCX文件,返回NULL。
- file.Close();
- return NULL;
- }
-
- // 获取图像高度
- wHeight = pcxHdr.wBottom - pcxHdr.wTop + 1;
-
- // 获取图像宽度
- wWidth = pcxHdr.wRight - pcxHdr.wLeft + 1;
-
- // 计算图像每行的字节数
- lLineBytes = WIDTHBYTES(wWidth * 8);
-
- // 计算DIB长度(字节)
- dwDIBSize = sizeof(BITMAPINFOHEADER) + 1024 + wHeight * lLineBytes;
-
- // 为DIB分配内存
- hDIB = (HDIB) ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, dwDIBSize);
- if (hDIB == 0)
- {
- file.Close();
- // 内存分配失败,返回NULL。
- return NULL;
- }
-
- // 锁定
- pDIB = (LPSTR) ::GlobalLock((HGLOBAL) hDIB);
-
- // 指向BITMAPINFOHEADER的指针
- LPBITMAPINFOHEADER lpBI;
-
- // 赋值
- lpBI = (LPBITMAPINFOHEADER) pDIB;
-
- // 给lpBI成员赋值
- lpBI->biSize = 40;
- lpBI->biWidth = wWidth;
- lpBI->biHeight = wHeight;
- lpBI->biPlanes = 1;
- lpBI->biBitCount = 8;
- lpBI->biCompression = BI_RGB;
- lpBI->biSizeImage = wHeight * lLineBytes;
- lpBI->biXPelsPerMeter = pcxHdr.wXResolution;
- lpBI->biYPelsPerMeter = pcxHdr.wYResolution;
- lpBI->biClrUsed = 0;
- lpBI->biClrImportant = 0;
-
- // 分配内存以读取编码后的象素
- lpSrc = new BYTE[file.GetLength() - sizeof(PCXHEADER) - 769];
- lpTemp = lpSrc;
-
- // 读取编码后的象素
- if (file.ReadHuge(lpSrc, file.GetLength() - sizeof(PCXHEADER) - 769) !=
- file.GetLength() - sizeof(PCXHEADER) - 769 )
- {
- // 大小不对。
-
- // 解除锁定
- ::GlobalUnlock((HGLOBAL) hDIB);
-
- // 释放内存
- ::GlobalFree((HGLOBAL) hDIB);
-
- // 返回NULL。
- file.Close();
- return NULL;
- }
-
- // 计算DIB中像素位置
- lpDst = (BYTE *) FindDIBBits(pDIB);
-
- // 一行一行解码
- for (j = 0; j <wHeight; j++)
- {
- i = 0;
- while (i < wWidth)
- {
- // 读取一个字节
- bChar = *lpTemp;
- lpTemp++;
-
- if ((bChar & 0xC0) == 0xC0)
- {
- // 行程
- iCount = bChar & 0x3F;
-
- // 读取下一个字节
- bChar = *lpTemp;
- lpTemp++;
-
- // bChar重复iCount次保存
- memset(&lpDst[(wHeight - j - 1) * lLineBytes + i], bChar, iCount);
- // 已经读取像素的个数加iCount
- i += iCount;
- }
- else
- {
- // 保存当前字节
- lpDst[(wHeight - j - 1) * lLineBytes + i] = bChar;
-
- // 已经读取像素的个数加1
- i += 1;
- }
- }
- }
-
- // 释放内存
- delete lpSrc;
-
- //*************************************************************
- // 调色板
-
- // 读调色板标志位
- file.Read(&bChar, 1);
- if (bChar != 0x0C)
- {
- // 出错
-
- // 解除锁定
- ::GlobalUnlock((HGLOBAL) hDIB);
-
- // 释放内存
- ::GlobalFree((HGLOBAL) hDIB);
-
- // 返回NULL。
- file.Close();
- return NULL;
- }
-
- // 分配内存以读取编码后的象素
- lpSrc = new BYTE[768];
-
- // 计算DIB中调色板的位置
- lpDst = (BYTE *) pDIB + sizeof(BITMAPINFOHEADER);
-
- // 读取调色板
- if (file.Read(lpSrc, 768) != 768)
- {
- // 大小不对。
-
- // 解除锁定
- ::GlobalUnlock((HGLOBAL) hDIB);
-
- // 释放内存
- ::GlobalFree((HGLOBAL) hDIB);
-
- // 返回NULL。
- file.Close();
- return NULL;
- }
-
- // 给调色板赋值
- for (i = 0; i < 256; i++)
- {
- lpDst[i * 4] = lpSrc[i * 3 + 2];
- lpDst[i * 4 + 1] = lpSrc[i * 3 + 1];
- lpDst[i * 4 + 2] = lpSrc[i * 3];
- lpDst[i * 4 + 3] = 0;
- }
-
- // 释放内存
- delete lpSrc;
-
- // 解除锁定
- ::GlobalUnlock((HGLOBAL) hDIB);
-
- file.Close();
- // 返回DIB句柄
- return hDIB;
- }