DIB.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:21k
源码类别:
Windows编程
开发平台:
Visual C++
- /****************************************************************************
- *
- * FILE: DIB.C
- *
- * PURPOSE: DIB functions for IconPro Project
- *
- * COMMENTS: Icons are stored in a format almost identical to DIBs. For
- * this reason, it is easiest to deal with the individual
- * icon images as DIBs (or DIBSections). This has the added
- * advantage of retaining color depth even on low-end displays.
- *
- * FUNCTIONS:
- * EXPORTS:
- * FindDIBBits() - Locate the image bits in a DIB
- * DIBNumColors() - Calculate number of color table entries
- * PaletteSize() - Calculate number of color table bytes
- * BytesPerLine() - Calculate number of bytes per scan line
- * ConvertDIBFormat() - Converts DIBs between formats
- * SetMonoDIBPixel() - Sets/Clears a pixel in a 1bpp DIB
- * ReadBMPFile() - Reads a BMP file into CF_DIB memory
- * WriteBMPFile() - Write a BMP file from CF_DIB memory
- * LOCALS:
- * CopyColorTable() - Copies color table from DIB to DIB
- *
- * Copyright 1995 - 1997 Microsoft Corp.
- *
- *
- * History:
- * July '95 - Created
- *
- ****************************************************************************/
- #include <Windows.h>
- #include "Dib.H"
- /****************************************************************************/
- /* Local Function Prototypes */
- BOOL CopyColorTable( LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource );
- /****************************************************************************/
- /****************************************************************************
- *
- * FUNCTION: FindDIBits
- *
- * PURPOSE: Locate the image bits in a CF_DIB format DIB.
- *
- * PARAMS: LPSTR lpbi - pointer to the CF_DIB memory block
- *
- * RETURNS: LPSTR - pointer to the image bits
- *
- * History:
- * July '95 - Copied <g>
- *
- ****************************************************************************/
- LPSTR FindDIBBits( LPSTR lpbi )
- {
- return ( lpbi + *(LPDWORD)lpbi + PaletteSize( lpbi ) );
- }
- /* End FindDIBits() *********************************************************/
- /****************************************************************************
- *
- * FUNCTION: DIBNumColors
- *
- * PURPOSE: Calculates the number of entries in the color table.
- *
- * PARAMS: LPSTR lpbi - pointer to the CF_DIB memory block
- *
- * RETURNS: WORD - Number of entries in the color table.
- *
- * History:
- * July '95 - Copied <g>
- *
- ****************************************************************************/
- WORD DIBNumColors( LPSTR lpbi )
- {
- WORD wBitCount;
- DWORD dwClrUsed;
- dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
- if (dwClrUsed)
- return (WORD) dwClrUsed;
- wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
- switch (wBitCount)
- {
- case 1: return 2;
- case 4: return 16;
- case 8: return 256;
- default:return 0;
- }
- return 0;
- }
- /* End DIBNumColors() ******************************************************/
- /****************************************************************************
- *
- * FUNCTION: PaletteSize
- *
- * PURPOSE: Calculates the number of bytes in the color table.
- *
- * PARAMS: LPSTR lpbi - pointer to the CF_DIB memory block
- *
- * RETURNS: WORD - number of bytes in the color table
- *
- *
- * History:
- * July '95 - Copied <g>
- *
- ****************************************************************************/
- WORD PaletteSize( LPSTR lpbi )
- {
- return ( DIBNumColors( lpbi ) * sizeof( RGBQUAD ) );
- }
- /* End PaletteSize() ********************************************************/
- /****************************************************************************
- *
- * FUNCTION: BytesPerLine
- *
- * PURPOSE: Calculates the number of bytes in one scan line.
- *
- * PARAMS: LPBITMAPINFOHEADER lpBMIH - pointer to the BITMAPINFOHEADER
- * that begins the CF_DIB block
- *
- * RETURNS: DWORD - number of bytes in one scan line (DWORD aligned)
- *
- * History:
- * July '95 - Created
- *
- ****************************************************************************/
- DWORD BytesPerLine( LPBITMAPINFOHEADER lpBMIH )
- {
- return WIDTHBYTES(lpBMIH->biWidth * lpBMIH->biPlanes * lpBMIH->biBitCount);
- }
- /* End BytesPerLine() ********************************************************/
- /****************************************************************************
- *
- * FUNCTION: ConvertDIBFormat
- *
- * PURPOSE: Creates a new DIB of the requested format, copies the source
- * image to the new DIB.
- *
- * PARAMS: LPBITMAPINFO lpSrcDIB - the source CF_DIB
- * UINT nWidth - width for new DIB
- * UINT nHeight - height for new DIB
- * UINT nbpp - bpp for new DIB
- * BOOL bStretch - TRUE to stretch source to dest
- * FALSE to take upper left of image
- *
- * RETURNS: LPBYTE - pointer to new CF_DIB memory block with new image
- * NULL on failure
- *
- * History:
- * July '95 - Created
- *
- ****************************************************************************/
- LPBYTE ConvertDIBFormat( LPBITMAPINFO lpSrcDIB, UINT nWidth, UINT nHeight, UINT nbpp, BOOL bStretch )
- {
- LPBITMAPINFO lpbmi = NULL;
- LPBYTE lpSourceBits, lpTargetBits, lpResult;
- HDC hDC = NULL, hSourceDC, hTargetDC;
- HBITMAP hSourceBitmap, hTargetBitmap, hOldTargetBitmap, hOldSourceBitmap;
- DWORD dwSourceBitsSize, dwTargetBitsSize, dwTargetHeaderSize;
- // Allocate and fill out a BITMAPINFO struct for the new DIB
- // Allow enough room for a 256-entry color table, just in case
- dwTargetHeaderSize = sizeof( BITMAPINFO ) + ( 256 * sizeof( RGBQUAD ) );
- lpbmi = malloc( dwTargetHeaderSize );
- lpbmi->bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
- lpbmi->bmiHeader.biWidth = nWidth;
- lpbmi->bmiHeader.biHeight = nHeight;
- lpbmi->bmiHeader.biPlanes = 1;
- lpbmi->bmiHeader.biBitCount = nbpp;
- lpbmi->bmiHeader.biCompression = BI_RGB;
- lpbmi->bmiHeader.biSizeImage = 0;
- lpbmi->bmiHeader.biXPelsPerMeter = 0;
- lpbmi->bmiHeader.biYPelsPerMeter = 0;
- lpbmi->bmiHeader.biClrUsed = 0;
- lpbmi->bmiHeader.biClrImportant = 0;
- // Fill in the color table
- if( ! CopyColorTable( lpbmi, (LPBITMAPINFO)lpSrcDIB ) )
- {
- free( lpbmi );
- return NULL;
- }
- // Gonna use DIBSections and BitBlt() to do the conversion, so make 'em
- hDC = GetDC( NULL );
- hTargetBitmap = CreateDIBSection( hDC, lpbmi, DIB_RGB_COLORS, &lpTargetBits, NULL, 0 );
- hSourceBitmap = CreateDIBSection( hDC, lpSrcDIB, DIB_RGB_COLORS, &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(&(lpSrcDIB->bmiHeader));
- dwTargetBitsSize = lpbmi->bmiHeader.biHeight * BytesPerLine(&(lpbmi->bmiHeader));
- memcpy( lpSourceBits, FindDIBBits((LPSTR)lpSrcDIB), dwSourceBitsSize );
- // Select DIBSections into DCs
- hOldSourceBitmap = SelectObject( hSourceDC, hSourceBitmap );
- hOldTargetBitmap = SelectObject( hTargetDC, hTargetBitmap );
- // Set the color tables for the DIBSections
- if( lpSrcDIB->bmiHeader.biBitCount <= 8 )
- SetDIBColorTable( hSourceDC, 0, 1 << lpSrcDIB->bmiHeader.biBitCount, lpSrcDIB->bmiColors );
- if( lpbmi->bmiHeader.biBitCount <= 8 )
- SetDIBColorTable( hTargetDC, 0, 1 << lpbmi->bmiHeader.biBitCount, lpbmi->bmiColors );
- // If we are asking for a straight copy, do it
- if( (lpSrcDIB->bmiHeader.biWidth==lpbmi->bmiHeader.biWidth) && (lpSrcDIB->bmiHeader.biHeight==lpbmi->bmiHeader.biHeight) )
- {
- BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
- }
- else
- {
- // else, should we stretch it?
- if( bStretch )
- {
- SetStretchBltMode( hTargetDC, COLORONCOLOR );
- StretchBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, lpSrcDIB->bmiHeader.biWidth, lpSrcDIB->bmiHeader.biHeight, SRCCOPY );
- }
- else
- {
- // or just take the upper left corner of the source
- BitBlt( hTargetDC, 0, 0, lpbmi->bmiHeader.biWidth, lpbmi->bmiHeader.biHeight, hSourceDC, 0, 0, SRCCOPY );
- }
- }
- // Clean up and delete the DCs
- SelectObject( hSourceDC, hOldSourceBitmap );
- SelectObject( hSourceDC, 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
- lpResult = malloc( dwTargetHeaderSize + dwTargetBitsSize );
- memcpy( lpResult, lpbmi, dwTargetHeaderSize );
- memcpy( FindDIBBits( lpResult ), lpTargetBits, dwTargetBitsSize );
- // final cleanup
- DeleteObject( hTargetBitmap );
- DeleteObject( hSourceBitmap );
- free( lpbmi );
- return lpResult;
- }
- /* End ConvertDIBFormat() ***************************************************/
- /****************************************************************************
- *
- * FUNCTION: CopyColorTable
- *
- * PURPOSE: Copies the color table from one CF_DIB to another.
- *
- * PARAMS: LPBITMAPINFO lpTarget - pointer to target DIB
- * LPBITMAPINFO lpSource - pointer to source DIB
- *
- * RETURNS: BOOL - TRUE for success, FALSE for failure
- *
- * History:
- * July '95 - Created
- *
- ****************************************************************************/
- BOOL CopyColorTable( LPBITMAPINFO lpTarget, LPBITMAPINFO lpSource )
- {
- // What we do depends on the target's color depth
- switch( lpTarget->bmiHeader.biBitCount )
- {
- // 8bpp - need 256 entry color table
- case 8:
- if( lpSource->bmiHeader.biBitCount == 8 )
- { // Source is 8bpp too, copy color table
- memcpy( lpTarget->bmiColors, lpSource->bmiColors, 256*sizeof(RGBQUAD) );
- return TRUE;
- }
- else
- { // Source is != 8bpp, use halftone palette
- HPALETTE hPal;
- HDC hDC = GetDC( NULL );
- PALETTEENTRY pe[256];
- UINT i;
- hPal = CreateHalftonePalette( hDC );
- ReleaseDC( NULL, hDC );
- GetPaletteEntries( hPal, 0, 256, pe );
- DeleteObject( hPal );
- for(i=0;i<256;i++)
- {
- lpTarget->bmiColors[i].rgbRed = pe[i].peRed;
- lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen;
- lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue;
- lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags;
- }
- return TRUE;
- }
- break; // end 8bpp
- // 4bpp - need 16 entry color table
- case 4:
- if( lpSource->bmiHeader.biBitCount == 4 )
- { // Source is 4bpp too, copy color table
- memcpy( lpTarget->bmiColors, lpSource->bmiColors, 16*sizeof(RGBQUAD) );
- return TRUE;
- }
- else
- { // Source is != 4bpp, use system palette
- HPALETTE hPal;
- PALETTEENTRY pe[256];
- UINT i;
- hPal = GetStockObject( DEFAULT_PALETTE );
- GetPaletteEntries( hPal, 0, 16, pe );
- for(i=0;i<16;i++)
- {
- lpTarget->bmiColors[i].rgbRed = pe[i].peRed;
- lpTarget->bmiColors[i].rgbGreen = pe[i].peGreen;
- lpTarget->bmiColors[i].rgbBlue = pe[i].peBlue;
- lpTarget->bmiColors[i].rgbReserved = pe[i].peFlags;
- }
- return TRUE;
- }
- break; // end 4bpp
- // 1bpp - need 2 entry mono color table
- case 1:
- lpTarget->bmiColors[0].rgbRed = 0;
- lpTarget->bmiColors[0].rgbGreen = 0;
- lpTarget->bmiColors[0].rgbBlue = 0;
- lpTarget->bmiColors[0].rgbReserved = 0;
- lpTarget->bmiColors[1].rgbRed = 255;
- lpTarget->bmiColors[1].rgbGreen = 255;
- lpTarget->bmiColors[1].rgbBlue = 255;
- lpTarget->bmiColors[1].rgbReserved = 0;
- break; // end 1bpp
- // no color table for the > 8bpp modes
- case 32:
- case 24:
- case 16:
- default:
- return TRUE;
- break;
- }
- return TRUE;
- }
- /* End CopyColorTable() *****************************************************/
- /****************************************************************************
- *
- * FUNCTION: SetMonoDIBPixel
- *
- * PURPOSE: Sets/Clears a pixel in a 1bpp DIB by directly poking the bits.
- *
- * PARAMS: LPBYTE pANDBits - pointer to the 1bpp image bits
- * DWORD dwWidth - width of the DIB
- * DWORD dwHeight - height of the DIB
- * DWORD x - x location of pixel to set/clear
- * DWORD y - y location of pixel to set/clear
- * BOOL bWhite - TRUE to set pixel, FALSE to clear it
- *
- * RETURNS: void
- *
- * History:
- * July '95 - Created
- *
- ****************************************************************************/
- void SetMonoDIBPixel( LPBYTE pANDBits, DWORD dwWidth, DWORD dwHeight, DWORD x, DWORD y, BOOL bWhite )
- {
- DWORD ByteIndex;
- BYTE BitNumber;
- // Find the byte on which this scanline begins
- ByteIndex = (dwHeight - y - 1) * WIDTHBYTES(dwWidth);
- // Find the byte containing this pixel
- ByteIndex += (x >> 3);
- // Which bit is it?
- BitNumber = (BYTE)( 7 - (x % 8) );
- if( bWhite )
- // Turn it on
- pANDBits[ByteIndex] |= (1<<BitNumber);
- else
- // Turn it off
- pANDBits[ByteIndex] &= ~(1<<BitNumber);
- }
- /* End SetMonoDIBPixel() *****************************************************/
- /****************************************************************************
- *
- * FUNCTION: ReadBMPFile
- *
- * PURPOSE: Reads a BMP file into CF_DIB format
- *
- * PARAMS: LPCTSTR szFileName - the name of the file to read
- *
- * RETURNS: LPBYTE - pointer to the CF_DIB, NULL for failure
- *
- * History:
- * July '95 - Created
- *
- ****************************************************************************/
- LPBYTE ReadBMPFile( LPCTSTR szFileName )
- {
- HANDLE hFile;
- BITMAPFILEHEADER bfh;
- DWORD dwBytes;
- LPBYTE lpDIB = NULL, lpTemp = NULL;
- WORD wPaletteSize = 0;
- DWORD dwBitsSize = 0;
- // Open the file
- if( (hFile=CreateFile( szFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE )
- {
- MessageBox( NULL, "Error opening file", szFileName, MB_OK );
- return NULL;
- }
- // Read the header
- if( ( ! ReadFile( hFile, &bfh, sizeof(BITMAPFILEHEADER), &dwBytes, NULL ) ) || ( dwBytes != sizeof( BITMAPFILEHEADER ) ) )
- {
- CloseHandle( hFile );
- MessageBox( NULL, "Error reading file", szFileName, MB_OK );
- return NULL;
- }
- // Does it look like a BMP file?
- if( ( bfh.bfType != 0x4d42 ) || (bfh.bfReserved1!=0) || (bfh.bfReserved2!=0) )
- {
- CloseHandle( hFile );
- MessageBox( NULL, "Not a recognised BMP format file", szFileName, MB_OK );
- return NULL;
- }
- // Allocate some memory
- if( (lpDIB = malloc( sizeof( BITMAPINFO ) )) == NULL )
- {
- CloseHandle( hFile );
- MessageBox( NULL, "Failed to allocate memory for DIB", szFileName, MB_OK );
- return NULL;
- }
- // Read in the BITMAPINFOHEADER
- if( (!ReadFile( hFile, lpDIB, sizeof(BITMAPINFOHEADER), &dwBytes, NULL )) || (dwBytes!=sizeof(BITMAPINFOHEADER)) )
- {
- CloseHandle( hFile );
- free( lpDIB );
- MessageBox( NULL, "Error reading file", szFileName, MB_OK );
- return NULL;
- }
- if( ((LPBITMAPINFOHEADER)lpDIB)->biSize != sizeof( BITMAPINFOHEADER ) )
- {
- CloseHandle( hFile );
- free( lpDIB );
- MessageBox( NULL, "OS/2 style BMPs Not Supported", szFileName, MB_OK );
- return NULL;
- }
- // How big are the elements?
- wPaletteSize = PaletteSize((LPSTR)lpDIB);
- dwBitsSize = ((LPBITMAPINFOHEADER)lpDIB)->biHeight * BytesPerLine((LPBITMAPINFOHEADER)lpDIB);
- // realloc to account for the total size of the DIB
- if( (lpTemp = realloc( lpDIB, sizeof( BITMAPINFOHEADER ) + wPaletteSize + dwBitsSize )) == NULL )
- {
- CloseHandle( hFile );
- MessageBox( NULL, "Failed to allocate memory for DIB", szFileName, MB_OK );
- free( lpDIB );
- return NULL;
- }
- lpDIB = lpTemp;
- // If there is a color table, read it
- if( wPaletteSize != 0 )
- {
- if( (!ReadFile( hFile, ((LPBITMAPINFO)lpDIB)->bmiColors, wPaletteSize, &dwBytes, NULL )) || (dwBytes!=wPaletteSize) )
- {
- CloseHandle( hFile );
- free( lpDIB );
- MessageBox( NULL, "Error reading file", szFileName, MB_OK );
- return NULL;
- }
- }
- // Seek to the bits
- // checking against 0 in case some bogus app didn't set this element
- if( bfh.bfOffBits != 0 )
- {
- if( SetFilePointer( hFile, bfh.bfOffBits, NULL, FILE_BEGIN ) == 0xffffffff )
- {
- CloseHandle( hFile );
- free( lpDIB );
- MessageBox( NULL, "Error reading file", szFileName, MB_OK );
- return NULL;
- }
- }
- // Read the image bits
- if( (!ReadFile( hFile, FindDIBBits(lpDIB), dwBitsSize, &dwBytes, NULL )) || (dwBytes!=dwBitsSize) )
- {
- CloseHandle( hFile );
- free( lpDIB );
- MessageBox( NULL, "Error reading file", szFileName, MB_OK );
- return NULL;
- }
- // clean up
- CloseHandle( hFile );
- return lpDIB;
- }
- /* End ReadBMPFile() ********************************************************/
- /****************************************************************************
- *
- * FUNCTION: WriteBMPFile
- *
- * PURPOSE: Writes a BMP file from CF_DIB format
- *
- * PARAMS: LPCTSTR szFileName - the name of the file to read
- * LPBYTE - pointer to the CF_DIB, NULL for failure
- *
- * RETURNS: BOOL - TRUE for success, FALSE for Failure
- *
- * History:
- * July '95 - Created
- *
- ****************************************************************************/
- BOOL WriteBMPFile( LPCTSTR szFileName, LPBYTE lpDIB )
- {
- HANDLE hFile;
- BITMAPFILEHEADER bfh;
- DWORD dwBytes, dwBytesToWrite;
- LPBITMAPINFOHEADER lpbmih;
- // Open the file
- if( (hFile=CreateFile( szFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE )
- {
- MessageBox( NULL, "Error opening file", szFileName, MB_OK );
- return FALSE;
- }
- bfh.bfType = 0x4d42;
- bfh.bfReserved1 = 0;
- bfh.bfReserved2 = 0;
- bfh.bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER ) + PaletteSize( lpDIB );
- bfh.bfSize = (bfh.bfOffBits + ((LPBITMAPINFOHEADER)lpDIB)->biHeight * BytesPerLine((LPBITMAPINFOHEADER)lpDIB))/4;
- // Write the header
- if( ( ! WriteFile( hFile, &bfh, sizeof(BITMAPFILEHEADER), &dwBytes, NULL ) ) || ( dwBytes != sizeof( BITMAPFILEHEADER ) ) )
- {
- CloseHandle( hFile );
- MessageBox( NULL, "Error Writing file", szFileName, MB_OK );
- return FALSE;
- }
- lpbmih = (LPBITMAPINFOHEADER)lpDIB;
- lpbmih->biHeight /= 2;
- dwBytesToWrite = bfh.bfOffBits + (lpbmih->biHeight * BytesPerLine(lpbmih));
- if( ( ! WriteFile( hFile, lpDIB, dwBytesToWrite, &dwBytes, NULL ) ) || ( dwBytes != dwBytesToWrite ) )
- {
- CloseHandle( hFile );
- MessageBox( NULL, "Error Writing file", szFileName, MB_OK );
- return FALSE;
- }
- lpbmih->biHeight *= 2;
- CloseHandle( hFile );
- return TRUE;
- }
- /* End WriteBMPFile() *******************************************************/