工控编程吧

标题: DDB DIB MBP格式相互转换 [打印本页]

作者: qq263946146    时间: 2019-7-14 11:01
标题: DDB DIB MBP格式相互转换
把位图写入一个BMP文件
如果具有一个设备无关的位图句柄,把一个位图写入BMP文件非常简单:
在位图内容之后写入BITMAPINFOHEADER信息即可。
需要设置BITMAPINFOHEADER的三个成员是bfType,其值为"BM",
bfSize,其值是位图的大小,
以及,bfOffBits,其值为文件开始到位图位的偏移量。
// WriteDIB                - Writes a DIB to file
// Returns                - TRUE on success
// szFile                - Name of file to write to
// hDIB                        - Handle of the DIB
BOOL WriteDIB( LPTSTR szFile, HANDLE hDIB)
{
        BITMAPFILEHEADER        hdr;
        LPBITMAPINFOHEADER        lpbi;

        if (!hDIB)
                return FALSE;

        CFile file;
        if( !file.Open( szFile, CFile::modeWrite|CFile::modeCreate) )
                return FALSE;

        lpbi = (LPBITMAPINFOHEADER)hDIB;

        int nColors = 1 << lpbi->biBitCount;

        // Fill in the fields of the file header
        hdr.bfType                = ((WORD) ('M' << 8) | 'B'); // is always "BM" hdr.bfSize="GlobalSize" (hDIB) + sizeof( hdr ); hdr.bfReserved1="0;" hdr.bfReserved2="0;" hdr.bfOffBits="(DWORD)" (sizeof( hdr ) + lpbi->biSize +
                                                nColors * sizeof(RGBQUAD));

        // Write the file header
        file.Write( &hdr, sizeof(hdr) );

        // Write the DIB header and the bits
        file.Write( lpbi, GlobalSize(hDIB) );

        return TRUE;
}

把DDB转换成DIB
设备相关位图(DDB)显示方式是尽可能与显示设备驱动程序相匹配,
这样,DDB不可能与其他显示设备兼容;而设备无关位图(DIB)能与所有显示设备兼容,
但是,其缺点在于显示速度比较慢。
我们需要把DDB转换为DIB的一种情况是,需要将位图保存到一个文件中。
下面是其实现的代码。
// DDBToDIB                - Creates a DIB from a DDB
// bitmap                - Device dependent bitmap
// dwCompression        - Type of compression - see BITMAPINFOHEADER
// pPal                        - Logical palette
HANDLE DDBToDIB( CBitmap& bitmap, DWORD dwCompression, CPalette* pPal )
{
        BITMAP                        bm;
        BITMAPINFOHEADER        bi;
        LPBITMAPINFOHEADER         lpbi;
        DWORD                        dwLen;
        HANDLE                        hDIB;
        HANDLE                        handle;
        HDC                         hDC;
        HPALETTE                hPal;


        ASSERT( bitmap.GetSafeHandle() );

        // The function has no arg for bitfields
        if( dwCompression == BI_BITFIELDS )
                return NULL;

        // If a palette has not been supplied use defaul palette
        hPal = (HPALETTE) pPal->GetSafeHandle();
        if (hPal==NULL)
                hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);

        // Get bitmap information
        bitmap.GetObject(sizeof(bm),(LPSTR)&bm);

        // Initialize the bitmapinfoheader
        bi.biSize                = sizeof(BITMAPINFOHEADER);
        bi.biWidth                = bm.bmWidth;
        bi.biHeight                 = bm.bmHeight;
        bi.biPlanes                 = 1;
        bi.biBitCount                = bm.bmPlanes * bm.bmBitsPixel;
        bi.biCompression        = dwCompression;
        bi.biSizeImage                = 0;
        bi.biXPelsPerMeter        = 0;
        bi.biYPelsPerMeter        = 0;
        bi.biClrUsed                = 0;
        bi.biClrImportant        = 0;

        // Compute the size of the  infoheader and the color table
        int nColors = (1 << bi.biBitCount); if( nColors> 256 )
                nColors = 0;
        dwLen  = bi.biSize + nColors * sizeof(RGBQUAD);

        // We need a device context to get the DIB from
        hDC = GetDC(NULL);
        hPal = SelectPalette(hDC,hPal,FALSE);
        RealizePalette(hDC);

        // Allocate enough memory to hold bitmapinfoheader and color table
        hDIB = GlobalAlloc(GMEM_FIXED,dwLen);

        if (!hDIB){
                SelectPalette(hDC,hPal,FALSE);
                ReleaseDC(NULL,hDC);
                return NULL;
        }

        lpbi = (LPBITMAPINFOHEADER)hDIB;

        *lpbi = bi;

        // Call GetDIBits with a NULL lpBits param, so the device driver
        // will calculate the biSizeImage field
        GetDIBits(hDC, (HBITMAP)bitmap.GetSafeHandle(), 0L, (DWORD)bi.biHeight,
                        (LPBYTE)NULL, (LPBITMAPINFO)lpbi, (DWORD)DIB_RGB_COLORS);

        bi = *lpbi;

        // If the driver did not fill in the biSizeImage field, then compute it
        // Each scan line of the image is aligned on a DWORD (32bit) boundary
        if (bi.biSizeImage == 0){
                bi.biSizeImage = ((((bi.biWidth * bi.biBitCount) + 31) & ~31) / 8)
                                                * bi.biHeight;

                // If a compression scheme is used the result may infact be larger
                // Increase the size to account for this.
                if (dwCompression != BI_RGB)
                        bi.biSizeImage = (bi.biSizeImage * 3) / 2;
        }

        // Realloc the buffer so that it can hold all the bits
        dwLen += bi.biSizeImage;
        if (handle = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
                hDIB = handle;
        else{
                GlobalFree(hDIB);

                // Reselect the original palette
                SelectPalette(hDC,hPal,FALSE);
                ReleaseDC(NULL,hDC);
                return NULL;
        }

        // Get the bitmap bits
        lpbi = (LPBITMAPINFOHEADER)hDIB;

        // FINALLY get the DIB
        BOOL bGotBits = GetDIBits( hDC, (HBITMAP)bitmap.GetSafeHandle(),
                                0L,                                // Start scan line
                                (DWORD)bi.biHeight,                // # of scan lines
                                (LPBYTE)lpbi                         // address for bitmap bits
                                + (bi.biSize + nColors * sizeof(RGBQUAD)),
                                (LPBITMAPINFO)lpbi,                // address of bitmapinfo
                                (DWORD)DIB_RGB_COLORS);                // Use RGB for color table

        if( !bGotBits )
        {
                GlobalFree(hDIB);
               
                SelectPalette(hDC,hPal,FALSE);
                ReleaseDC(NULL,hDC);
                return NULL;
        }

        SelectPalette(hDC,hPal,FALSE);
        ReleaseDC(NULL,hDC);
        return hDIB;
}

把DIB转换成DDB
你可以把一个设备无关位图(DIB)在不转换成设备相关位图(DDB)的情况下显示到设备环境中,
但是,这样做显示速度将慢很多。如果进行转换,将提高显示速度。
下面是其实现代码。
HBITMAP DIBToDDB( HANDLE hDIB )
{
        LPBITMAPINFOHEADER        lpbi;
        HBITMAP                 hbm;
        CPalette                pal;
        CPalette*                pOldPal;
        CClientDC                dc(NULL);

        if (hDIB == NULL)
                return NULL;

        lpbi = (LPBITMAPINFOHEADER)hDIB;

        int nColors = lpbi->biClrUsed ? lpbi->biClrUsed :
                                                1 << lpbi->biBitCount;

        BITMAPINFO &bmInfo = *(LPBITMAPINFO)hDIB ;
        LPVOID lpDIBBits;
        if( bmInfo.bmiHeader.biBitCount > 8 )
                lpDIBBits = (LPVOID)((LPDWORD)(bmInfo.bmiColors +
                        bmInfo.bmiHeader.biClrUsed) +
                        ((bmInfo.bmiHeader.biCompression == BI_BITFIELDS) ? 3 : 0));
        else
                lpDIBBits = (LPVOID)(bmInfo.bmiColors + nColors);

        // Create and select a logical palette if needed
        if( nColors <= 256 && dc.GetDeviceCaps(RASTERCAPS) & RC_PALETTE) { UINT nSize="sizeof(LOGPALETTE)" + (sizeof(PALETTEENTRY) * nColors); LOGPALETTE *pLP="(LOGPALETTE" *) new BYTE[nSize]; pLP->palVersion = 0x300;
                pLP->palNumEntries = nColors;

                for( int i=0; i palPalEntry.peRed = bmInfo.bmiColors.rgbRed;
                        pLP->palPalEntry.peGreen = bmInfo.bmiColors.rgbGreen;
                        pLP->palPalEntry.peBlue = bmInfo.bmiColors.rgbBlue;
                        pLP->palPalEntry.peFlags = 0;
                }

                pal.CreatePalette( pLP );

                delete[] pLP;

                // Select and realize the palette
                pOldPal = dc.SelectPalette( &pal, FALSE );
                dc.RealizePalette();
        }

       
        hbm = CreateDIBitmap(dc.GetSafeHdc(),                // handle to device context
                        (LPBITMAPINFOHEADER)lpbi,        // pointer to bitmap info header
                        (LONG)CBM_INIT,                        // initialization flag
                        lpDIBBits,                        // pointer to initialization data
                        (LPBITMAPINFO)lpbi,                // pointer to bitmap info
                        DIB_RGB_COLORS );                // color-data usage

        if (pal.GetSafeHandle())
                dc.SelectPalette(pOldPal,FALSE);

        return hbm;
}







欢迎光临 工控编程吧 (https://www.gkbc8.com/) Powered by Discuz! X3.4