码迷,mamicode.com
首页 > 其他好文 > 详细

第16章 调色板管理器_16.3 调色板和现实世界中的图像

时间:2015-08-04 09:22:08      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:

16.3.1 调色板和紧凑DIB

(1)对于16、24、32位的DIB,没有颜色表,就不必创建调色板。但在8位视频模式下,只会用标准的20种保留色来显示。由DIB颜色表创建的调色板被称为“原生调色板”

(2)dwPixel =PackedDibGetPixel(pPackedDib,x,y),当这类函数多次调用时会使程序变慢。

(3)很多函数,需要对OS/2兼容DIB作不同处理。

【ShowDib3程序】——原生(Native)调色板

效果图
技术分享
//PackedDIB.h文件
/*------------------------------------------------------------------
PACKEDDIB.H -- Header file for PACKDIB.C
(c) Charles Petzold,1998
------------------------------------------------------------------*/
#pragma once

#include <windows.h>

BITMAPINFO* PackedDibLoad(PTSTR szFileName);

int PackedDibGetWidth(BITMAPINFO* pPackedDib);
int PackedDibGetHeight(BITMAPINFO* pPackedDib);
int PackedDibGetBitCount(BITMAPINFO* pPackedDib);
int PackedDibGetRowLength(BITMAPINFO* pPackedDib);

int PackedDibGetInfoHeaderSize(BITMAPINFO* pPackedDib);
int PackedDibGetColorsUsed(BITMAPINFO* pPackedDib);
int PackedDibGetNumColors(BITMAPINFO* pPackedDib);

RGBQUAD* PackedDibGetColorTableSize(BITMAPINFO* pPackedDib);
RGBQUAD* PackedDibGetColorTableEntry(BITMAPINFO*, int i);

BYTE* PackedDibGetBitsPtr(BITMAPINFO* pPackedDib);
int PackedDibGetBitsSize(BITMAPINFO* pPackedDib);

HPALETTE PackedDibCreatePalette(BITMAPINFO* pPackedDib);

//PackedDIB.c文件

/*-----------------------------------------------------------------
PACKEDDIB.C -- Routines for using packed DIBs
(c) Charles Petzold,1998
-----------------------------------------------------------------*/
#include <windows.h>

/*---------------------------------------------------------
PackedDibLoad:将DIB文件作以紧缩型格式加载进内存中
---------------------------------------------------------*/
BITMAPINFO* PackedDibLoad(PTSTR szFileName)
{
    BITMAPFILEHEADER   bmfh;
    BITMAPINFO*        pbmi;
    HANDLE  hFile;
    BOOL bSuccess;
    DWORD  dwBytesRead, dwPackedDibSize;

    //打开文件,指定读和写属性
    hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                       OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);

    if (hFile == INVALID_HANDLE_VALUE)
        return NULL;

    //读取文件头
    bSuccess = ReadFile(hFile, &bmfh, sizeof(BITMAPFILEHEADER), &dwBytesRead, NULL);
    if (!bSuccess || (dwBytesRead != sizeof(BITMAPFILEHEADER))
        || (bmfh.bfType != *(WORD*)"BM"))
    {
        CloseHandle(hFile);
        return NULL;
    }

    //计算紧缩型DIB的大小
    dwPackedDibSize = bmfh.bfSize - sizeof(BITMAPFILEHEADER); //文件大小减小文件头的大小

    //分配内存,并读入信息(含信息头与像素数据)
    pbmi = malloc(dwPackedDibSize);
    bSuccess = ReadFile(hFile, pbmi, dwPackedDibSize, &dwBytesRead, NULL);
    CloseHandle(hFile);

    if (!bSuccess || (dwPackedDibSize != dwBytesRead))
    {
        free(pbmi);
        return NULL;
    }
    return pbmi;
}

/*----------------------------------------------
获取紧缩型DIB信息的函数
----------------------------------------------*/

int PackedDibGetWidth(BITMAPINFO* pPackedDib)
{
    if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
        return  ((BITMAPCOREINFO*)pPackedDib)->bmciHeader.bcWidth;
    else
        return pPackedDib->bmiHeader.biWidth;
}

int PackedDibGetHeight(BITMAPINFO* pPackedDib)
{
    if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
        return  ((BITMAPCOREINFO*)pPackedDib)->bmciHeader.bcHeight;
    else
        return abs(pPackedDib->bmiHeader.biHeight);  //取绝对值
}

int PackedDibGetBitCount(BITMAPINFO* pPackedDib)
{
    if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
        return  ((BITMAPCOREINFO*)pPackedDib)->bmciHeader.bcBitCount;
    else
        return pPackedDib->bmiHeader.biBitCount;
}

int PackedDibGetRowLength(BITMAPINFO* pPackedDib)
{
    return ((PackedDibGetWidth(pPackedDib)*PackedDibGetBitCount(pPackedDib) + 31) & ~31) >> 3;
}

/*-----------------------------------------------------------
获取DIB信息头大小(含可能的颜色遮罩)——单位:字节
-----------------------------------------------------------*/
int PackedDibGetInfoHeaderSize(BITMAPINFO* pPackedDib)
{
    if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
        return  ((BITMAPCOREINFO*)pPackedDib)->bmciHeader.bcSize;
    else if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPINFOHEADER))
        return pPackedDib->bmiHeader.biSize +
        (pPackedDib->bmiHeader.biCompression ==
        BI_BITFIELDS ? 12 : 0); //颜色遮罩
    else return pPackedDib->bmiHeader.biSize;
}

/*-------------------------------------------------------------
PackedDibGetColorsUsed:返回信息头中的bClrUse字段,表示用到的颜色数
如果没有颜色表,则该值为0
-------------------------------------------------------------*/
int PackedDibGetColorsUsed(BITMAPINFO* pPackedDib)
{
    if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
        return  0;
    else
        return pPackedDib->bmiHeader.biClrUsed;
}

/*------------------------------------------------------------------
PackedDibGetNumColors:颜色表中实际的条目数
------------------------------------------------------------------*/
int PackedDibGetNumColors(BITMAPINFO* pPackedDib)
{
    int iNumColors;

    iNumColors = PackedDibGetColorsUsed(pPackedDib);

    //iNumColor等于0时,说明实际使用的颜色由biBitCount计算出来
    //16、24、32位时获得的iNumColors的一般为0
    if (iNumColors == 0 && (PackedDibGetBitCount(pPackedDib) < 16))
        iNumColors = 1 << (PackedDibGetBitCount(pPackedDib)); //2^biBitCount个

    return iNumColors;
}

int PackedDibGetColorTableSize(BITMAPINFO* pPackedDib)
{
    if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
        return  PackedDibGetNumColors(pPackedDib)*sizeof(RGBTRIPLE);
    else
        return PackedDibGetNumColors(pPackedDib)*sizeof(RGBQUAD);
}

RGBQUAD* PackedDibGetColorTablePtr(BITMAPINFO* pPackedDib)
{
    if (PackedDibGetNumColors(pPackedDib) == 0)
        return NULL;

    return (RGBQUAD*)(((BYTE*)pPackedDib) +
                      PackedDibGetInfoHeaderSize(pPackedDib));
}

RGBQUAD* PackedDibGetColorTableEntry(BITMAPINFO* pPackedDib, int i)
{
    if (PackedDibGetNumColors(pPackedDib) == 0)
        return NULL;

    if (pPackedDib->bmiHeader.biSize == sizeof(BITMAPCOREHEADER))
        return  (RGBQUAD*)((RGBTRIPLE*)PackedDibGetColorTablePtr(pPackedDib) + i);
    else
        return PackedDibGetColorTablePtr(pPackedDib) + i;
}

/*----------------------------------
PackedDibGetBitsPtr:获取像素数据的指针
----------------------------------*/
BYTE* PackedDibGetBitsPtr(BITMAPINFO* pPackedDib)
{
    return (BYTE*)(pPackedDib)+PackedDibGetInfoHeaderSize(pPackedDib) +
        PackedDibGetColorTableSize(pPackedDib);
}

/*-----------------------------------------------------------------------
PackedDibGetBitsSize:
自动计算像素数据的空间大小(即使biSizeImage字段没有显式的指定)
-----------------------------------------------------------------------*/
int PackedDibGetBitsSize(BITMAPINFO* pPackedDib)
{
    if ((pPackedDib->bmiHeader.biSize != sizeof(BITMAPCOREHEADER)) &&
        (pPackedDib->bmiHeader.biSizeImage != 0))
        return pPackedDib->bmiHeader.biSizeImage;

    return PackedDibGetHeight(pPackedDib)* PackedDibGetRowLength(pPackedDib);
}

/*----------------------------------------------------------------
PackedDibCreatePalette:从紧缩型DIB中创建逻辑调色板
----------------------------------------------------------------*/

HPALETTE PackedDibCreatePalette(BITMAPINFO* pPackedDib)
{
    HPALETTE hPalette;
    int i, iNumColors;
    LOGPALETTE* plp;
    RGBQUAD*  prgb;

    iNumColors = PackedDibGetNumColors(pPackedDib);
    if (0 == iNumColors) //16、24、32位时获得的iNumColors的一般为0
        return NULL;

    plp = malloc(sizeof(LOGPALETTE)*(iNumColors - 1)*sizeof(PALETTEENTRY));
    plp->palVersion = 0x0300;
    plp->palNumEntries = iNumColors;

    for (i = 0; i < iNumColors; i++)
    {
        prgb = PackedDibGetColorTableEntry(pPackedDib, i);
        plp->palPalEntry[i].peRed = prgb->rgbRed;
        plp->palPalEntry[i].peGreen = prgb->rgbGreen;
        plp->palPalEntry[i].peBlue = prgb->rgbBlue;
        plp->palPalEntry[i].peFlags = 0;
    }

    hPalette = CreatePalette(plp);
    free(plp);

    return hPalette;
}

//ShowDib3.c

/*------------------------------------------------------------
SHOWDIB3.C -- Displays DIB with native palette
(c) Charles Petzold, 1998
------------------------------------------------------------*/

#include <windows.h>
#include "resource.h"
#include "PackedDIB.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static TCHAR szAppName[] = TEXT("ShowDib3");

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX   wndclass;
    HACCEL       hAccel;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;

    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                  // window class name
                        TEXT("Show DIB #3:Native Palette"), // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    hAccel = LoadAccelerators(hInstance, szAppName);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(hwnd, hAccel, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static BITMAPINFO* pPackedDib;
    static HPALETTE hPalette;

    HDC         hdc;
    PAINTSTRUCT ps;

    static OPENFILENAME ofn;
    static TCHAR szFilter[] = TEXT("Bitmap Files(*.BMP)\0*.bmp\0")
        TEXT("All Files(*.*)\0*.*\0\0");
    static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
    static int cxClient, cyClient;


    switch (message)
    {
    case WM_CREATE:
        memset(&ofn, 0, sizeof(OPENFILENAME));
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = hwnd;
        ofn.lpstrFilter = szFilter;
        ofn.lpstrFile = szFileName;
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szTitleName;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrDefExt = TEXT("bmp");
        return 0;

    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDM_FILE_OPEN:

            //显示打开文件对话框
            if (!GetOpenFileName(&ofn))
                return 0;

            //如果图像己经存在,则释放内存
            if (pPackedDib)
            {
                free(pPackedDib);
                pPackedDib = NULL;
            }

            //如果逻辑调色板己经存在,则删除
            if (hPalette)
            {
                DeleteObject(hPalette);
                hPalette = NULL;
            }


            //加载紧缩型DIB到内存中
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            ShowCursor(TRUE);

            pPackedDib = PackedDibLoad(szFileName);

            ShowCursor(FALSE);
            SetCursor(LoadCursor(NULL, IDC_ARROW));

            if (pPackedDib)
            {
                //创建逻辑调色板
                hPalette = PackedDibCreatePalette(pPackedDib);
            } else
            {
                MessageBox(hwnd, TEXT("Cannot load DIB file."), szAppName, 0);
            }

            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
        }
        break;

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        if (hPalette) //16、24、32位的DIB没有颜色表,在8位视频模式下,只显示20种保留色
        {
            SelectPalette(hdc, hPalette, FALSE);
            RealizePalette(hdc);
        }

        if (pPackedDib)
        {
            SetDIBitsToDevice(hdc,
                              0, 0,
                              PackedDibGetWidth(pPackedDib),
                              PackedDibGetHeight(pPackedDib),
                              0, 0,
                              0,
                              PackedDibGetHeight(pPackedDib),
                              PackedDibGetBitsPtr(pPackedDib),
                              pPackedDib,
                              DIB_RGB_COLORS);
        }
        EndPaint(hwnd, &ps);
        return 0;

    case WM_QUERYNEWPALETTE:
        if (!hPalette)
            return FALSE;

        hdc = GetDC(hwnd);
        SelectPalette(hdc, hPalette, FALSE);
        RealizePalette(hdc);
        InvalidateRect(hwnd, NULL, TRUE);

        ReleaseDC(hwnd, hdc);
        return TRUE;

    case WM_PALETTECHANGED:
        if (!hPalette || (HWND)wParam == hwnd)
            break;

        hdc = GetDC(hwnd);
        SelectPalette(hdc, hPalette, FALSE);
        RealizePalette(hdc);
        UpdateColors(hdc);

        ReleaseDC(hwnd, hdc);
        break;

    case WM_DESTROY:
        if (pPackedDib)
            free(pPackedDib);

        if (hPalette)
            DeleteObject(hPalette);

        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

//resource.c

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ 生成的包含文件。
// 供 ShowDIB3.rc 使用
//
#define  IDM_FILE_OPEN                 40001
// Next default values for new objects
// 
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        103
#define _APS_NEXT_COMMAND_VALUE         40004
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

//ShowDib3.rc

// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// 中文(简体,中国) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_CHS)
LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END

3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

SHOWDIB3 MENU
BEGIN
POPUP "&File"
BEGIN
MENUITEM "&Open...\tCtrl+O", IDM_FILE_OPEN
END
END


/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//

SHOWDIB3 ACCELERATORS
BEGIN
"^O", IDM_FILE_OPEN, ASCII, NOINVERT
END

#endif    // 中文(简体,中国) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED
16.3.2 通用调色板(247种自定义颜色,其中有些与系统保留色重复(这些会被匹配到相应的系统色上去))

(1)31种灰度色调

  0x00,0x09, 0x11,0x1A, 0x22, 0x2B, 0x33, 0x3C, 0x44, 0x4D, 0x55, 0x5E, 0x66, 0x6F,0x77, 0x80, 0x88, 0x91, 0x99, 0xA2, 0xAA,0xB3,0xBB, 0xC4, 0xCC, 0xD5, 0xDD, 0xE6, 0xEE, 0xF9, 0xFF(其中红色的为系统20种保留色之一)

(2)216种颜色,R、G、B分别由0x00、0x33、0x66、0x99、0xCC、0xFF的所有组合。(其中8种是系统20种保留色中的颜色,还有4种是前面灰度值的重复)。

 【ShowDib4程序】——效果图与ShowDib3相似,但细节上有差异,还有在8位视频模式下,该程序正常显示!
256色下效果

 技术分享

/*------------------------------------------------------------
SHOWDIB4.C -- Displays DIB with “all - purpose” palette
(c) Charles Petzold, 1998
------------------------------------------------------------*/

#include <windows.h>
#include "..\\ShowDib3\\resource.h"
#include "..\\ShowDib3\\PackedDIB.h"

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static TCHAR szAppName[] = TEXT("ShowDib4");

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX   wndclass;
    HACCEL       hAccel;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;

    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                  // window class name
                        TEXT("Show DIB #4:All-Purpose Palette"), // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    hAccel = LoadAccelerators(hInstance, szAppName);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(hwnd, hAccel, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return msg.wParam;
}

/*------------------------------------------------------------------------
CreateAllPurposePalette:
创建一个通用的调色板,该调色板共有247个颜色条目,其中15种是从20种保留色中
复出或匹配的。
------------------------------------------------------------------------*/
HPALETTE CreateAllPurposePalette(void)
{
    HPALETTE hPalette;
    LOGPALETTE* plp;
    int i, incr, R, G, B;

    plp = malloc(sizeof(LOGPALETTE) + 246 * sizeof(PALETTEENTRY));
    plp->palVersion = 0x0300;
    plp->palNumEntries = 247;

    //创建31级的灰阶颜色,其中3种匹配系统的20种保留色
    for (i = 0, G = 0, incr = 8; G <= 0xFF; i++, G += incr)
    {
        plp->palPalEntry[i].peRed = (BYTE)G;
        plp->palPalEntry[i].peGreen = (BYTE)G;
        plp->palPalEntry[i].peBlue = (BYTE)G;
        plp->palPalEntry[i].peFlags = 0;
        incr = (incr == 9 ? 8 : 9);
    }

    //创建216种颜色,但其中有8种匹配系统的20种保留色,另外4种匹配以上产生的灰色
    for (R = 0; R < 0xFF; R += 0x33)
        for (G = 0; G < 0xFF; G += 0x33)
            for (B = 0; B < 0xFF; B += 0x33)
            {
                plp->palPalEntry[i].peRed = (BYTE)R;
                plp->palPalEntry[i].peGreen = (BYTE)G;
                plp->palPalEntry[i].peBlue = (BYTE)B;
                plp->palPalEntry[i].peFlags = 0;
                i++;
            }

    hPalette = CreatePalette(plp);
    free(plp);
    return hPalette;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static BITMAPINFO* pPackedDib;
    static HPALETTE hPalette;

    HDC         hdc;
    PAINTSTRUCT ps;

    static OPENFILENAME ofn;
    static TCHAR szFilter[] = TEXT("Bitmap Files(*.BMP)\0*.bmp\0")
        TEXT("All Files(*.*)\0*.*\0\0");
    static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
    static int cxClient, cyClient;


    switch (message)
    {
    case WM_CREATE:
        memset(&ofn, 0, sizeof(OPENFILENAME));
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = hwnd;
        ofn.lpstrFilter = szFilter;
        ofn.lpstrFile = szFileName;
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szTitleName;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrDefExt = TEXT("bmp");

        // 创建通用调色板
        hPalette = CreateAllPurposePalette();
        return 0;

    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDM_FILE_OPEN:

            //显示打开文件对话框
            if (!GetOpenFileName(&ofn))
                return 0;

            //如果图像己经存在,则释放内存
            if (pPackedDib)
            {
                free(pPackedDib);
                pPackedDib = NULL;
            }

            //如果逻辑调色板己经存在,则删除
            if (hPalette)
            {
                DeleteObject(hPalette);
                hPalette = NULL;
            }


            //加载紧缩型DIB到内存中
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            ShowCursor(TRUE);

            pPackedDib = PackedDibLoad(szFileName);

            ShowCursor(FALSE);
            SetCursor(LoadCursor(NULL, IDC_ARROW));

            if (!pPackedDib)
            {
                MessageBox(hwnd, TEXT("Cannot load DIB file."), szAppName, 0);
            }

            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
        }
        break;

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        if (pPackedDib)
        {
            SelectPalette(hdc, hPalette, FALSE);
            RealizePalette(hdc);
            SetDIBitsToDevice(hdc,
                              0, 0,
                              PackedDibGetWidth(pPackedDib),
                              PackedDibGetHeight(pPackedDib),
                              0, 0,
                              0,
                              PackedDibGetHeight(pPackedDib),
                              PackedDibGetBitsPtr(pPackedDib),
                              pPackedDib,
                              DIB_RGB_COLORS);
        }
        EndPaint(hwnd, &ps);
        return 0;

    case WM_QUERYNEWPALETTE:
        if (!hPalette)
            return FALSE;

        hdc = GetDC(hwnd);
        SelectPalette(hdc, hPalette, FALSE);
        RealizePalette(hdc);
        InvalidateRect(hwnd, NULL, TRUE);

        ReleaseDC(hwnd, hdc);
        return TRUE;

    case WM_PALETTECHANGED:
        if ((HWND)wParam == hwnd)
            break;

        hdc = GetDC(hwnd);
        SelectPalette(hdc, hPalette, FALSE);
        RealizePalette(hdc);
        UpdateColors(hdc);

        ReleaseDC(hwnd, hdc);
        break;

    case WM_DESTROY:
        if (pPackedDib)
            free(pPackedDib);

        DeleteObject(hPalette);

        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

16.3.3 半色调调色板——使用抖动模式,来更好地在8位视频上模拟原始图像的颜色。

(1)系统提供API来创建半色调的调色板

hPalette= CreateHalftonePalette(hdc);

(2)当使用SetDIBitsToDevice来显示DIB时,效果与ShowDib4程序差不多

(3)使用StretchDIBits效果会很明显,但须先设置

        SetStretchBltMode(hdc,HALFTONE);

        SetBrushOrgEx(hdc,x,y,NULL);//x、y是DIB左上角的设备坐标。
【ShowDib5程序】
256色下的效果(要比通用调色板效果好得多)

技术分享

/*------------------------------------------------------------
   SHOWDIB5.C -- Displays DIB with halftone palette
                 (c) Charles Petzold, 1998
------------------------------------------------------------*/

#include <windows.h>
#include "..\\ShowDib3\\resource.h"
#include "..\\ShowDib3\\PackedDIB.h"

  LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
static TCHAR szAppName[] = TEXT("ShowDib5");

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                   PSTR szCmdLine, int iCmdShow)
{
    HWND         hwnd;
    MSG          msg;
    WNDCLASSEX   wndclass;
    HACCEL       hAccel;

    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    wndclass.cbSize = sizeof(WNDCLASSEX);
    wndclass.lpfnWndProc = WndProc;
    wndclass.cbClsExtra = 0;
    wndclass.cbWndExtra = 0;
    wndclass.hInstance = hInstance;
    wndclass.hIcon = LoadIcon(hInstance, szAppName);
    wndclass.hIconSm = LoadIcon(hInstance, szAppName);
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wndclass.lpszMenuName = szAppName;
    wndclass.lpszClassName = szAppName;

    if (!RegisterClassEx(&wndclass))
    {
        MessageBox(NULL, TEXT("This program requires Windows NT!"),
                   szAppName, MB_ICONERROR);
        return 0;
    }

    hwnd = CreateWindow(szAppName,                  // window class name
                        TEXT("Show DIB #5:Halftone Palette"), // window caption
                        WS_OVERLAPPEDWINDOW,        // window style
                        CW_USEDEFAULT,              // initial x position
                        CW_USEDEFAULT,              // initial y position
                        CW_USEDEFAULT,              // initial x size
                        CW_USEDEFAULT,              // initial y size
                        NULL,                       // parent window handle
                        NULL,                       // window menu handle
                        hInstance,                  // program instance handle
                        NULL);                     // creation parameters

    ShowWindow(hwnd, iCmdShow);
    UpdateWindow(hwnd);
    hAccel = LoadAccelerators(hInstance, szAppName);
    while (GetMessage(&msg, NULL, 0, 0))
    {
        if (!TranslateAccelerator(hwnd, hAccel, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    static BITMAPINFO* pPackedDib;
    static HPALETTE hPalette;

    HDC         hdc;
    PAINTSTRUCT ps;

    static OPENFILENAME ofn;
    static TCHAR szFilter[] = TEXT("Bitmap Files(*.BMP)\0*.bmp\0")
        TEXT("All Files(*.*)\0*.*\0\0");
    static TCHAR szFileName[MAX_PATH], szTitleName[MAX_PATH];
    static int cxClient, cyClient;


    switch (message)
    {
    case WM_CREATE:
        memset(&ofn, 0, sizeof(OPENFILENAME));
        ofn.lStructSize = sizeof(OPENFILENAME);
        ofn.hwndOwner = hwnd;
        ofn.lpstrFilter = szFilter;
        ofn.lpstrFile = szFileName;
        ofn.nMaxFile = MAX_PATH;
        ofn.lpstrFileTitle = szTitleName;
        ofn.nMaxFileTitle = MAX_PATH;
        ofn.lpstrDefExt = TEXT("bmp");

        // 创建通用调色板
        hdc = GetDC(hwnd);
        hPalette = CreateHalftonePalette(hdc);  //半色调调色板
        ReleaseDC(hwnd, hdc);
        return 0;

    case WM_SIZE:
        cxClient = LOWORD(lParam);
        cyClient = HIWORD(lParam);
        return 0;

    case WM_COMMAND:
        switch (LOWORD(wParam))
        {
        case IDM_FILE_OPEN:

            //显示打开文件对话框
            if (!GetOpenFileName(&ofn))
                return 0;

            //如果图像己经存在,则释放内存
            if (pPackedDib)
            {
                free(pPackedDib);
                pPackedDib = NULL;
            }

            //如果逻辑调色板己经存在,则删除
            if (hPalette)
            {
                DeleteObject(hPalette);
                hPalette = NULL;
            }


            //加载紧缩型DIB到内存中
            SetCursor(LoadCursor(NULL, IDC_WAIT));
            ShowCursor(TRUE);

            pPackedDib = PackedDibLoad(szFileName);

            ShowCursor(FALSE);
            SetCursor(LoadCursor(NULL, IDC_ARROW));

            if (!pPackedDib)
            {
                MessageBox(hwnd, TEXT("Cannot load DIB file."), szAppName, 0);
            }

            InvalidateRect(hwnd, NULL, TRUE);
            return 0;
        }
        break;

    case WM_PAINT:
        hdc = BeginPaint(hwnd, &ps);

        if (pPackedDib)
        {
            //设置半色板模式
            SetStretchBltMode(hdc, HALFTONE);
            SetBrushOrgEx(hdc, 0, 0, NULL);

            //选择并实现调色板
            SelectPalette(hdc, hPalette, FALSE);
            RealizePalette(hdc);

            //用StretchDIBits而不是SetDIBitsToDevice函数
            StretchDIBits(hdc,
                          0, 0,
                          PackedDibGetWidth(pPackedDib),
                          PackedDibGetHeight(pPackedDib),
                          0, 0,
                          PackedDibGetWidth(pPackedDib),
                          PackedDibGetHeight(pPackedDib),
                          PackedDibGetBitsPtr(pPackedDib),
                          pPackedDib,
                          DIB_RGB_COLORS,
                          SRCCOPY);
        }
        EndPaint(hwnd, &ps);
        return 0;

    case WM_QUERYNEWPALETTE:
        if (!hPalette)
            return FALSE;

        hdc = GetDC(hwnd);
        SelectPalette(hdc, hPalette, FALSE);
        RealizePalette(hdc);
        InvalidateRect(hwnd, NULL, TRUE);

        ReleaseDC(hwnd, hdc);
        return TRUE;

    case WM_PALETTECHANGED:
        if ((HWND)wParam == hwnd)
            break;

        hdc = GetDC(hwnd);
        SelectPalette(hdc, hPalette, FALSE);
        RealizePalette(hdc);
        UpdateColors(hdc);

        ReleaseDC(hwnd, hdc);
        break;

    case WM_DESTROY:
        if (pPackedDib)
            free(pPackedDib);

        DeleteObject(hPalette);

        PostQuitMessage(0);
        return 0;
    }
    return DefWindowProc(hwnd, message, wParam, lParam);
}

 

第16章 调色板管理器_16.3 调色板和现实世界中的图像

标签:

原文地址:http://www.cnblogs.com/5iedu/p/4701023.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!