http://www.lihuasoft.net/news/show.php?id=4395

                                                             将RGB值转换为灰度值的简单算法

[转贴] 出处:  http://www.lihuasoft.net/news/show.php?id=4395

  使场景或精灵以灰度的形式显示,这是一般游戏制作中常常用到的效果,如:战棋游戏中当一个角色被使用过后,通常就会变成灰色,代表本回合已不能行动了;《仙剑》中回忆彩蝶的部分是用整屏的灰色来表现的?(记的不太清楚,太久了^_^);还有很多很多例子……

  将RGB值转换为灰度的过程应该是在程序中实现的(至少我是这么认为的)。其实这是非常简单的,基本原理就是将一个点的RGB值分开来求和,然后除以3,把得到的值再分别付给RGB,用公式表示如下:

R = G = B = 0.3R + 0.6G + 0.1B; //第二版改正后的公式

//第一版中的错误公式是 R = G = B = ( R + G + B ) / 3;

 

  在实际编程应用中又可分为8位、16位和24位三种情况,下面进行一一介绍:

  一、首先说最简单的24位点的转换,24位点的RGB均匀分布,所以分离和合成都较为简单,代码如下:

 

 

//=======24位转换============

int gMask=0x00ff00; //绿色掩码

int bMask=0x0000ff; //兰色掩码

 

int RGB24toGray(int sour)

{

    int r,g,b,t; //临时变量

 

    r=(sour>>16);

    g=(sour & gMask) >>8;

    b=sour & bMask;

    t=(r*3+g*6+b)/10; //第二版改正的地方

 

    return (t<<16)|(t<<8)|t;

}

 

  二、16位点的转换要麻烦一些,因其涉及到555和565两种色码格式,所以在转换前需要我们进行一些初始工作:

 

//=======16位转换============

BYTE RMove, GMove; //R和G移动到最低位需要的步数

 

//初始化数据,本函数在游戏初始时执行,仅执行一次

void Init()

{

    if( Is555 ) //555模式 0rrrrrgggggbbbbb

    {

        RMove=10;

        GMove=5;

    }

    else //565模式 rrrrrggggggbbbbb

    {

        RMove=11;

        GMove=6;

        /*注意:为什么这里GMove=6,因为565模式下G值有6位,如果用一个6位值和两个5位值相加除以3,得到的结果可能使5位溢出,所以我们要多移动一位即除以2*/

    }

}

 

//16位点转换

WORD RGB16toGray(WORD sour)

{

    WORD t;

    WORD r, g, b;

    r= sour >> RMove;

    g= (GMask & sour) >> GMove;

    b= BMask & sour;

    t = (r*3+b*6+g)/10; //第二版改正的地方

    return (t<<RMove)|(t<<GMove)|t;

}

 

  三、8位点的转换和上面两种有比较大的差异,因为它的颜色是由调色板决定的,我们只有通过改变调色板来进行转换,先用lpDDPal->GetEntries()获得调色板,然后分别转换需要的调色板值,完成后用lpDDPal->SetEntries()更新即可,程序如下:

 

//===========8位转换(注:本函数只适用于全屏转换)===========

void RGB8_to_Gray()

{

    int t; //临时变量

    LPPALETTEENTRY Pal = (LPPALETTEENTRY) LocalAlloc( LPTR, sizeof( PALETTEENTRY ) * 256 );

 

    //获取调色板

    lpDDPal->GetEntries(0,0,256,Pal);

 

    //转换

    for(int i=0; i<256; i++)

    {

        t=( Pal[i].peRed * 3 + Pal[i].peGreen *6 + Pal[i].peBlue ) / 10; //第二版改正的地方

        Pal[i].peRed=Pal[i].peGreen=Pal[i].peBlue=t;

    }

 

    //更新调色板

    lpDDPal->SetEntries(0,0,256,Pe);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值