是下面这三步吗?
(1)为逻辑调色板分配内存空间
(2)从BITMAPINFO或BITMAPCOREINFO中复制颜色分量等信息到逻辑调色板中
(3)按逻辑调色板创建调色板
请兄弟们补充下,另外,想问一下,最后创建的调色板不是逻辑调色板了吧,那是位图的系统调色板吗?
多谢了~~~

解决方案 »

  1.   

    MSDN中的例子DIBLOOK 说明如何使用设备无关位图 (DIB) 和调色板。
      

  2.   

    今天太晚了,明天给你回复吧。Mark一下
      

  3.   

    BOOL CMyBitmap::SetPal(PBITMAPINFO pInfo)
    {
    HLOCAL hPal;
    LOGPALETTE *pPal;
    LPRGBQUAD lpRGB;
    int m_iNumColors;

    if(pInfo->bmiHeader.biClrUsed != 0)
    m_iNumColors = (UINT) pInfo->bmiHeader.biClrUsed; 
    else 
    {
    switch(pInfo->bmiHeader.biBitCount)
    {
    case 1:
    m_iNumColors = 2;
    break;
    case 4:
    m_iNumColors = 16;
    break;
    case 8:
    m_iNumColors = 256;
    break;
    case 24:
    m_iNumColors = 0; 
    break;
    case 32:
    m_iNumColors = 0; 
    break;
    default: 
    TRACE("Invalid color numbers!");
    return FALSE;
    }
    }
    if(m_iNumColors != 0) 
    {
    hPal = LocalAlloc(
    LHND, 
    sizeof(LOGPALETTE) + m_iNumColors*sizeof(PALETTEENTRY) );

    pPal = (LOGPALETTE *)LocalLock(hPal);

    pPal->palNumEntries = (short)m_iNumColors;
    pPal->palVersion = 0x300;

    lpRGB = (LPRGBQUAD)((LPSTR)pInfo + (DWORD)sizeof(BITMAPINFOHEADER));

    for (DWORD i = 0; i < m_iNumColors; i++)
    {
    pPal->palPalEntry[i].peRed = lpRGB->rgbRed;
    pPal->palPalEntry[i].peGreen = lpRGB->rgbGreen;
    pPal->palPalEntry[i].peBlue = lpRGB->rgbBlue;
    pPal->palPalEntry[i].peFlags = (BYTE)0;
    lpRGB++; 
    }

    if(m_hPalette)
    DeleteObject(m_hPalette);
    m_hPalette = CreatePalette(pPal);

    LocalUnlock(hPal);
    LocalFree(hPal);
    }
    return TRUE;
    }
      

  4.   

    //每一行的字节数必须是4的整倍数,调用宏完成这一换算
    //WIDTHBYTES(bi.biWidth*bi.biBitCount)就能进行调整
    #define WIDTHBYTES(i)    ((i+31)/32*4)HGLOBAL hImgData;
    HPALETTE hPalette;
    HBITMAP hBitmap;
    BITMAPFILEHEADER bf;
    BITMAPINFOHEADER bi;BOOL LoadBmpFile(HWND hWnd,char *BmpFileName)
    {   
    HANDLE                hfile; //文件句柄
    LPBITMAPINFOHEADER    lpImgData; //指向BITMAPINFOHEADER结构的指针  
    LOGPALETTE            *pPal; //指向逻辑调色板结构的指针
    LPRGBQUAD             lpRGB; //指向RGBQUAD结构的指针
    HPALETTE              hPrevPalette; //用来保存设备中原来的调色板
    HDC                   hDc; //设备句柄
    HLOCAL                hPal; //存储调色板的局部内存句柄
    DWORD                 LineBytes; //每一行的字节数
    DWORD                 ImgSize; //实际的图象数据占用的字节数
    DWORD                 NumColors; //实际用到的颜色数,即调色板数组中的颜色个数
    DWORD                 i;
    hfile=CreateFile(BmpFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
    if(hfile==NULL)
    {
    MessageBox(hWnd,"File open failed!","Error",MB_OK|MB_ICONEXCLAMATION);
    return FALSE; //打开文件错误返回
    }
    //ReadFile读取后按实际读的位置调整文件指针
    if(!ReadFile(hfile,&bf,sizeof(BITMAPFILEHEADER),NULL,NULL))
    return FALSE; //读BITMAPFILEHEADER失败
    if(!ReadFile(hfile,&bi,sizeof(BITMAPINFOHEADER),NULL,NULL))
    return FALSE; //读BITMAPINFOHEADER失败
    //计算实际数据的大小,4倍调整
    LineBytes=(DWORD)WIDTHBYTES(bi.biWidth*bi.biBitCount); //每一行的字节数
    ImgSize=(DWORD)LineBytes*bi.biHeight; //实际的图象数据占用的字节数
    //进行颜色数的处理
    if(bi.biClrUsed!=0) //如果bi.biClrUsed不为零,即为实际用到的颜色数
    NumColors=(DWORD)bi.biClrUsed; 
    else //否则,用到的颜色数为2的biBitCount次幂
    switch(bi.biBitCount)
    {
    case 1:
    NumColors=2;
                break;
            case 4:
    NumColors=16;
                break;
    case 8:
    NumColors=256;
    break;
    case 24:
    NumColors=0; //对于真彩色图,没用到调色板
    break;
    default: //不处理其它的颜色数,认为出错。
    MessageBox(hWnd,"Invalid color numbers!","Error",MB_OK|MB_ICONEXCLAMATION);
    CloseFile(hfile);
    return FALSE; //关闭文件,返回FALSE
    }
    //计算出的偏移量与实际偏移量不符,一定是颜色数出错
    if(bf.bfOffBits!=(DWORD)(NumColors*sizeof(RGBQUAD)+
    sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)))
    {
    MessageBox(hWnd,"Invalid color numbers!","Error",MB_OK|MB_ICONEXCLAMATION);
    CloseHandle(hfile);
    return FALSE; //关闭文件,返回FALSE
    }
    //计算整个BMP文件的大小
    bf.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+
    NumColors*sizeof(RGBQUAD)+ImgSize;
    //申请内存空间,忽略了BITMAPFILEHEADER的大小
    if((hImgData=GlobalAlloc(GHND,(DWORD)(sizeof(BITMAPINFOHEADER)+
    NumColors*sizeof(RGBQUAD)+ImgSize)))==NULL)
    {
    MessageBox(hWnd,"Error alloc memory!","Error",MB_OK|MB_ICONEXCLAMATION);
    CloseHandle(hfile);
    return FALSE; //关闭文件,返回FALSE
    }
    //GlobalLock将一个内存区域转为一个指针
    lpImgData=(LPBITMAPINFOHEADER)GlobalLock(hImgData);
    //文件指针重新定位到BITMAPINFOHEADER开始处
    SetFilePointer(hfile,sizeof(BITMAPFILEHEADER),NULL,FILE_BEGIN);
    //将文件内容读入lpImgData
    ReadFile(hfile,(char *)lpImgData,(long)sizeof(BITMAPINFOHEADER)+
    (long)NumColors*sizeof(RGBQUAD)+ImgSize);
    CloseHandle(hfile); //关闭文件
    //如果需要调色板数据,NumColors不为零
    if(NumColors!=0) 
    {
    //为逻辑调色板分配局部内存,大小为逻辑调色板结构长度加NumColors个PALETTENTRY
    hPal=LocalAlloc(LHND,sizeof(LOGPALETTE)+NumColors* sizeof(PALETTEENTRY));
    //指针pPal指向该内存区
    pPal =(LOGPALETTE *)LocalLock(hPal);
    //填写逻辑调色板结构的头
    pPal->palNumEntries = NumColors;
    pPal->palVersion = 0X300;
    //lpRGB指向的是调色板开始的位置
    lpRGB = (LPRGBQUAD)((LPSTR)lpImgData + (DWORD)sizeof(BITMAPINFOHEADER));
    //填写每一项
    for(i = 0; i < NumColors; i++)
    {
    pPal->palPalEntry[i].peRed=lpRGB->rgbRed;
    pPal->palPalEntry[i].peGreen=lpRGB->rgbGreen;
    pPal->palPalEntry[i].peBlue=lpRGB->rgbBlue;
    pPal->palPalEntry[i].peFlags=(BYTE)0;
    lpRGB++; //指针移到下一项
    }
    //产生逻辑调色板,hPalette是一个全局变量
    hPalette=CreatePalette(pPal);
    //释放局部内存
    LocalUnlock(hPal);
    LocalFree(hPal);
    }
    //获得设备上下文句柄
    HDC hDc=GetDC(hWnd);
    if(hPalette) //如果刚才产生了逻辑调色板
    {
    //将新的逻辑调色板选入DC,将旧的逻辑调色板句柄保存在hPrevPalette
    hPrevPalette=SelectPalette(hDc,hPalette,FALSE);
    RealizePalette(hDc);
    }
    //产生位图句柄
    hBitmap=CreateDIBitmap(hDc,(LPBITMAPINFOHEADER)lpImgData, (LONG)CBM_INIT,
    (LPSTR)lpImgData+sizeof(BITMAPINFOHEADER)+NumColors*sizeof(RGBQUAD),
    (LPBITMAPINFO)lpImgData, DIB_RGB_COLORS);
    //将原来的调色板(如果有的话)选入设备上下文句柄
    if(hPalette && hPrevPalette)
    {
    SelectPalette(hDc,hPrevPalette,FALSE);
    RealizePalette(hDc);
    }
    ReleaseDC(hWnd,hDc); //释放设备上下文
    GlobalUnlock(hImgData); //解锁内存区
    return TRUE; //成功返回
    }