fangyukuan

永无止境的追求...追求卓越!!!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

高彩模式

除了8位的,还有16位、24位、32位等。高于8位的模式都不再采用调色板模式。下面介绍几种编码模式。

16位模式下有几种编码方案

Alpha.5.5.5:这种模式用D15位存储一个Alpha(透明度),其余15位均匀分配给红色5位,绿色5位,蓝色5位。

X5.5.5与Alpha.5.5.5类似,只是最高位没有使用。

5.6.5这个是16色彩最常用的模式。5位分配给红,6位分配给绿,5位分配给蓝

下面是构造他们的宏:

// this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)

#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))

 

// this builds a 16 bit color value in 5.6.5 format (green dominate mode)

#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))

 

源代码下载

// ------------------------------------------------------------------------- 
// 文件名 : 7_1.cpp
// 创建者 : 方煜宽
// 邮箱 : fangyukuan@gmail.com
// 创建时间 : 2010-12-9 0:52
// 功能描述 : 16位模式,RGB565
// 对于像素位深度大于8的页面,不需要使用调色板
// -------------------------------------------------------------------------
#define INITGUID

#include
<windows.h>
#include
<ddraw.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HWND main_window_handle
= NULL; // 全局的windows窗口句柄
LPDIRECTDRAW7 lpdd = NULL; // ddraw 接口指针
DDSURFACEDESC2 ddsd; // ddraw 显示表面 描述结构
LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; // ddraw 主显示表面
LPDIRECTDRAWSURFACE7 lpddsback = NULL; // ddraw 从显示表面

#define SCREEN_WIDTH 640 // 屏幕宽
#define SCREEN_HEIGHT 480 // 屏幕高
#define SCREEN_BPP 16 // 深度
 

#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct, 0, sizeof(ddstruct)); ddstruct.dwSize = sizeof(ddstruct);
}
 // this builds a 16 bit color value in 5.6.5 format (green dominate mode)
#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))
 // this builds a 16 bit color value in 5.5.5 format (1-bit alpha mode)
#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10))
 #define KEYDOWN(vk_code) ((::GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((::GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

 

/*
每个像素16位,用此函数前先锁住表面。
*/
inline
void Plot_Pixel_Faster16(int x, int y,
int red, int green, int blue,
USHORT
*video_buffer, int lpitch16)
{
USHORT pixel
= _RGB16BIT565(red,green,blue);
video_buffer[x
+ y*lpitch16] = pixel;
}
int Game_Init(void *parms = NULL, int num_parms = 0)
{
if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
return 0;

if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,
DDSCL_FULLSCREEN
| DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
return 0;

if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, 0, 0)))
return 0;

memset(
&ddsd,0,sizeof(ddsd));
ddsd.dwSize
= sizeof(ddsd);

ddsd.dwFlags
= DDSD_CAPS;
ddsd.ddsCaps.dwCaps
= DDSCAPS_PRIMARYSURFACE;

if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
return 0;

// 不需要调色板了
// 对于像素位深度大于8的页面,不需要使用调色板

return 1;
}
int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
if (lpddsprimary)
{
lpddsprimary
->Release();
lpddsprimary
= NULL;
}

if (lpdd)
{
lpdd
->Release();
lpdd
= NULL;
}
return 1;
}
int Game_Main(void *parms = NULL, int num_parms = 0)
{
if (KEYDOWN(VK_ESCAPE))
SendMessage(main_window_handle, WM_CLOSE,
0, 0);

DDRAW_INIT_STRUCT(ddsd);

if (FAILED(lpddsprimary->Lock(NULL, &ddsd,
DDLOCK_SURFACEMEMORYPTR
| DDLOCK_WAIT,
NULL)))
return 0;

int lpitch16 = (int)(ddsd.lPitch >> 1);
USHORT
*video_buffer = (USHORT *)ddsd.lpSurface;

for (int index=0; index < 1000; index++)
{
int red = rand() % 256;
int green = rand() % 256;
int blue = rand() % 256;
int x = rand() % 640;
int y = rand() % 480;

Plot_Pixel_Faster16(x, y, red, green, blue, video_buffer, lpitch16);
}

if (FAILED(lpddsprimary->Unlock(NULL)))
return 0;

return 1;
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
HWND hwnd;
MSG msg;
TCHAR lpszClassName[]
= TEXT("kuan");

WNDCLASS wc;
wc.style
= CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc
= WndProc;
wc.cbClsExtra
= 0;
wc.cbWndExtra
= 0;
wc.hInstance
= hInstance;
wc.hIcon
= ::LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor
= ::LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground
= (HBRUSH)::GetStockObject(BLACK_BRUSH);
wc.lpszMenuName
= NULL;
wc.lpszClassName
= lpszClassName;

RegisterClass(
&wc);

hwnd
= CreateWindow(lpszClassName,
TEXT(
"fangyukuan"),
WS_POPUP
| WS_VISIBLE,
0,0,SCREEN_WIDTH,SCREEN_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
main_window_handle
= hwnd;

Game_Init();
while(TRUE)
{
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;

::TranslateMessage(
&msg);
::DispatchMessage(
&msg);
}
Game_Main();

}
Game_Shutdown();

return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch(message)
{
case WM_LBUTTONDOWN:
{
::MessageBeep(
0);
}
break;
case WM_DESTROY:
::PostQuitMessage(
0);
break;
default:
return ::DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}

32位模式下有几种编码方案

Alpha(8).8.8.8:用8位表示透明信息。红色、绿色、蓝色,各有用8位。每个像素都用32位来表示,这是奔腾处理器最快的内存寻址方式。

X(8).8.8:最高8位没有使用。其它的跟Alpha(8).8.8.8一样。

  

下面是构造他们的宏:

// this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)

#define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))

 

源代码下载

// ------------------------------------------------------------------------- 
// 文件名 : 7_3.cpp
// 创建者 : 方煜宽
// 邮箱 : fangyukuan@gmail.com
// 创建时间 : 2010-12-11 22:05
// 功能描述 : 32位真彩模式
//
// -------------------------------------------------------------------------
#define INITGUID

#include
<windows.h>
#include
<ddraw.h>


LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

HWND main_window_handle
= NULL; // 全局的windows窗口句柄
LPDIRECTDRAW7 lpdd = NULL; // ddraw 接口指针
DDSURFACEDESC2 ddsd; // ddraw 显示表面 描述结构
LPDIRECTDRAWSURFACE7 lpddsprimary = NULL; // ddraw 主显示表面
LPDIRECTDRAWSURFACE7 lpddsback = NULL; // ddraw 从显示表面

#define SCREEN_WIDTH 640 // 屏幕宽
#define SCREEN_HEIGHT 480 // 屏幕高
#define SCREEN_BPP 32 // 深度
 
  

#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
 // this builds a 32 bit color value in A.8.8.8 format (8-bit alpha mode)
#define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

inline void Plot_Pixel_32(int x, int y,
int alpha,int red, int green, int blue,
UINT
*video_buffer, int lpitch32)
{
UINT pixel
= _RGB32BIT(alpha,red,green,blue);
video_buffer[x
+ y*lpitch32] = pixel;
}
int Game_Init(void *parms = NULL, int num_parms = 0)
{
if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
return 0;

if (FAILED(lpdd->SetCooperativeLevel(main_window_handle,
DDSCL_FULLSCREEN
| DDSCL_ALLOWMODEX | DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT)))
return 0;

// set display mode to 640x480x16
if (FAILED(lpdd->SetDisplayMode(SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, 0, 0)))
return 0;

memset(
&ddsd,0,sizeof(ddsd));
ddsd.dwSize
= sizeof(ddsd);
ddsd.dwFlags
= DDSD_CAPS;
ddsd.ddsCaps.dwCaps
= DDSCAPS_PRIMARYSURFACE;

if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
return 0;

// 不需要调色板了
// 对于像素位深度大于8的页面,不需要使用调色板

return 1;

}
int Game_Shutdown(void *parms = NULL, int num_parms = 0)
{
// now the primary surface
if (lpddsprimary)
{
lpddsprimary
->Release();
lpddsprimary
= NULL;
}

// now blow away the IDirectDraw4 interface
if (lpdd)
{
lpdd
->Release();
lpdd
= NULL;
}
return 1;
}
int Game_Main(void *parms = NULL, int num_parms = 0)
{
if (KEYDOWN(VK_ESCAPE))
SendMessage(main_window_handle, WM_CLOSE,
0, 0);

DDRAW_INIT_STRUCT(ddsd);

if (FAILED(lpddsprimary->Lock(NULL, &ddsd,
DDLOCK_SURFACEMEMORYPTR
| DDLOCK_WAIT,
NULL)))
return 0;

int lpitch32 = (int)(ddsd.lPitch >> 2);
UINT
*video_buffer = (UINT *)ddsd.lpSurface;

for (int index=0; index < 1000; index++)
{
int red = rand() % 256;
int green = rand() % 256;
int blue = rand() % 256;
int x = rand() % 640;
int y = rand() % 480;

Plot_Pixel_32(x, y,
0, red, green, blue, video_buffer, lpitch32);
}

if (FAILED(lpddsprimary->Unlock(NULL)))
return 0;

return 1;
}
int WINAPI WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nShowCmd)
{
HWND hwnd;
MSG msg;
TCHAR lpszClassName[]
= TEXT("kuan");

WNDCLASS wc;
wc.style
= CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc
= WndProc;
wc.cbClsExtra
= 0;
wc.cbWndExtra
= 0;
wc.hInstance
= hInstance;
wc.hIcon
= ::LoadIcon(NULL,IDI_APPLICATION);
wc.hCursor
= ::LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground
= (HBRUSH)::GetStockObject(BLACK_BRUSH);
wc.lpszMenuName
= NULL;
wc.lpszClassName
= lpszClassName;

RegisterClass(
&wc);

hwnd
= CreateWindow(lpszClassName,
TEXT(
"fangyukuan"),
WS_POPUP
| WS_VISIBLE,
0,0,SCREEN_WIDTH,SCREEN_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
main_window_handle
= hwnd;

Game_Init();
while(TRUE)
{
if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT)
break;

::TranslateMessage(
&msg);
::DispatchMessage(
&msg);
}
Game_Main();

}
Game_Shutdown();

return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch(message)
{
case WM_LBUTTONDOWN:
{
::MessageBeep(
0);
}
break;
case WM_DESTROY:
::PostQuitMessage(
0);
break;
default:
return ::DefWindowProc(hwnd,message,wParam,lParam);
}
return 0;
}

获取像素格式

想知道任意表面的像素格式,可以用下面函数获取
IDIRECTDRAWSURFACE7::GetPixelFormat(LPDDPIXELFORMAT lpDDPixelFormat);

对DDPIXELFORMAT结构我们感兴趣的有以下三个:

DWORD dwSize;          // 结构大小
DWORD dwFlags;         // 描述表面的标志,见下表
DWORD dwRGBBitCount;   // RGB的位数

DDPIXELFORMAT. dwFlags的有效标志 

描述

DDPF_ALPHA

像素格式描述一个只有alpha的表面

DDPF_ALPHAPIXELS

画面有alpha信息的像素格式

DDPF_LUMINANCE

像素格式中有单一透明或者透明alpha分量的画面

DDPF_PALETTEINDEXED1

画面是1位色彩索引

DDPF_PALETTEINDEXED2

画面是2位色彩索引

DDPF_PALETTEINDEXED4

画面是4位色彩索引

DDPF_PALETTEINDEXED8

画面是8位色彩索引

DDPF_PALETTEINDEXEDTO8

画面是1位、2位、4位色彩索引到8位调色板

DDPF_RGB

像素格式中的RGB数据有效

DDPF_ZBUFFER

像素格式 描述 一个Z缓冲画面

DDPF_ZPIXELS

画面在像素中含有Z信息

比较重要标志是:

DDPF_PALETTEINDEXED8:说明表面租用 8位调色板模式。

DDPF_RGB:说明表面采用RGB模式,其格式可以通过测试dwRGBBitCount值获得。

DDPIXELFORMAT ddpixel;
LPDIRECTDRAWSURFACE7 lpdds_primary;
memset(
&ddpixel, 0, sizeof(ddpixel));
ddpixel.dwSize
= sizeof(ddpixel);
lpdds_primary
->GetPixelFormat(&ddpixel);
if (ddpixel.dwFlags & DDPF_RGB)
{
switch(ddpixel.dwRGBBitCount)
{
case 15: // must be 5.5.5 mode
break;
case 16: // must be 5.6.5 mode
break;
case 24: // must be 8.8.8 mode
break;
case 32: // must be alpha(8).8.8.8 mode
break;
default:
break;
}
}
else if (ddpixel.dwFlags & DDPF_PALETTEINDEXED8)
{
// 256 color palettized mode
}
else
{

}

2011.05.22

转载请保留下面链接

标题 http://www.cnblogs.com/fangyukuan/archive/2011/05/22/2053556.html

posted on 2011-05-22 15:20  fangyukuan  阅读(3650)  评论(0编辑  收藏  举报