SDL第四课色彩键控

来源:互联网 发布:淘宝猪哼少焦点访谈 编辑:程序博客网 时间:2024/06/02 05:29

色彩键控

 

最后更新2008/06/25

接下来我们将学习色彩键控。通俗的讲,就是教你在显示画面的时候,如何去掉背景颜色。SDL_Surface结构体中有一个成员叫做色键。色键就是当位图传输时,你不想在画面中显示出来的颜色,也就是用来控制背景透明。假设你想把这个名字为Foo.png的图片,

 

粘贴到下面这个背景上:

 

但是你不想让粘贴的图片中带有蓝绿色的背景:

 

为了不显示蓝绿色的背景,你需要将背景的颜色(这里背景颜色为:Red 0Green FF Blue FF)设置为画面的色键。

 

色键的典型用法是在当加载图片时设置。

SDL_Surface *load_image( std::string filename )

{

    //The image that's loaded

    SDL_Surface* loadedImage = NULL;

   

    //The optimized image that will be used

    SDL_Surface* optimizedImage = NULL;

   

    //Load the image

    loadedImage = IMG_Load( filename.c_str() );

   

    //If the image loaded

    if( loadedImage != NULL )

    {

        //Create an optimized image

        optimizedImage = SDL_DisplayFormat( loadedImage );

       

        //Free the old image

        SDL_FreeSurface( loadedImage );

/*因此,在这里我们将修改图片的加载函数。首先和之前一样载入和优化图片*/

 

        //If the image was optimized just fine

        if( optimizedImage != NULL )

        {

            //Map the color key

            Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF );

     /*然后,检查图片是否已经优化。如果优化完毕,我们需要绘制出来我们要设置为色键的色彩。调用SDL_MapRGB()函数,输入红、绿、蓝三基色的值,指定与画面相同的格式。关于像素,本章后有更详细的说明。*/

 

            //Set all pixels of color R 0, G 0xFF, B 0xFF to be transparent

            SDL_SetColorKey( optimizedImage, SDL_SRCCOLORKEY, colorkey );

        }

/*开始实际的色彩键控。第一个参数是我们要进行键控的画面。第二个参数我们放置的标志位。SDL_SRCCOLORKEY标志位,确保当我们传输这个画面到另一个画面上时能够使用色键。第三个参数是我们设置的色键的颜色。就是我们刚刚绘制的颜色。*/

 

    //Return the optimized image

    return optimizedImage;

}

/*然后,画面加载函数返回优化并进行色彩键控后的画面。*/

 

    //Apply the surfaces to the screen

    apply_surface( 0, 0, background, screen );

    apply_surface( 240, 190, foo, screen );

   

    //Update the screen

    if( SDL_Flip( screen ) == -1 )

    {

        return 1;   

    }

    /*现在传输背景位图,再传要粘贴的输色彩键控后的图片。*/

 

这样,粘贴的图片就没有蓝绿色的背景了。那些你使用的透明的PNG图片,IMG_Load()函数会自动处理透明图片。试着色彩键控一个透明背景的图片,会得到一个蛮特别的结果。如果你用SDL_DisplayFormat()函数代替SDL_DisplayFormatAlpha()函数,你也会有alpha颜色透明失真。只要不去色彩键控它就能够保留PNG图片上的透明背景。IMG_Load()函数也能够处理TGA图片的alpha颜色。查看SDL文档,获得更多关于颜色键控的信息。

 

 

 

什么是像素?

最后更新时间2009/12/15

也许你知道图片是由像素构成的,但是知道像素是由什么构成的么?

            //Map the color key

            Uint32 colorkey = SDL_MapRGB( optimizedImage->format, 0, 0xFF, 0xFF );

这是色彩键控教程里的一行代码。我说过SDL_MapRGB()返回一个像素,但是怎样构成一个“Uint32”的一个像素?

Uint32是一个:无符号的32位长度的整型数据。

怎样用一个数表示一个像素?也许你知道一些HTML,设置颜色用30255数字组合:

<span style="color: rgb(Red,Green,Blue)">Text</span>

那么怎样用一个数字表示一个像素?上面你看到的HTML/CSS 代码在这里是用来改变文本的颜色的。红,绿,蓝值的组合可以得到所有你的计算机能显示的颜色,例如:

 

This Red 255, Green 255, and Blue 255构成。

This Red 255, Green 0, and Blue 0构成。

This Red 0, Green 0, and Blue 255构成。

ThisRed 0, Green 0, and Blue 0构成。

ThisRed 192, Green 192, and Blue 0构成。

This Red 0, Green 255, and Blue 255构成。

This Red 192, Green 128, and Blue 64构成。

This Red 186, Green 3, and Blue 207构成。

 

    我认为你已经了解了。Uint32只是一个数字。如果像素由一组数字构成,那么不是要表示成一个数组?事实上,确实如此。红,绿,蓝的值构成一个像素,取值范围是0255。要记得0也是一个数字,在编程时我们总是从0开始。那么就有256个值。25628次方,所以每个颜色值可以用一个8位的二进制数表示。一个Uint32就是这些二进数一个接一个的结合到一起形成的一个数。在内存中,基本像素看起来就像这样:
101010110010101101011011

既然它只是一个8位二进制数的数组,你所要做的就是从一个大的32位的二进制数中得到单独的颜色值构成一个8位二进制数的数组。

 

//Get the address of the pixel

Uint8 *colors = (Uint8*)&pixel;

 

//Get the individual colors

red = colors[ 0 ];

green = colors[ 1 ];

blue = colors[ 2 ];

 

但是你通常都不会这么做。为了得到单独的颜色值,应该使用SDL_GetRGB()函数。我将告诉你一点为什么?也许现在你有一点迷惑,每个颜色8位,3个颜色是24位,那么最后8位呢?那最后8为就是像素的alpha颜色(alpha通道)。Alpha颜色控制像素透明。255表示像素完全不透明,而0表示像素完全透明。下面是一个图片显示在白色背景上的例子。每一次alpha颜色的值都不同。

 

alpha值是255时,图片显示正常

 

Alpha值是192时。你可以看得出来,白色的背景开始显露来。

 

 

 

alpha 的值为128. 现在透明度大约是50%

 

alpha 的值是 0 ,图片完全看不到了。

 

这就是32位的RGBA像素的构成,但是不是所有的像素构成都相同。有不同的像素格式。颜色顺序不同,像BGRA的颜色顺序就是蓝,绿,红,alpha。像素也可以有不同的大小,像24位的BGR位图。也有16位的颜色,由5位红色,5位绿色,5位蓝色,以及1alpha颜色。除此之外还有许多像素的格式,在这里不准备细说。所有这些像素格式就是为什么要通过SDL_PixelFormat来调用绘制颜色函数SDL_MapRGB()和获取颜色函数SDL_GetRGB(),这样函数才能知道怎样处理像素。这也是为什么把颜色的各位直接组合起来不是一个好的方法,除非你能知道你处理的是哪一种像素格式。

像素格式的不同也是你不能一起传输两个画面的原因。如果你把ABGR格式的像素复制到RGBA格式的画面上,就会出错。SDL可以实时转化像素格式,但是像素转化会占用CPU。这就是为什么我们要把所有的画面通过load_image()函数转化为屏幕的格式。

像这样像素转换的工作特别多,不过你不必困扰,除非你工作在非常低的层面。到此,你知道所有建立图片区块的基础知识。

有一些值得想想是问题,因为所有的RGB都是3个数字的组合,可不可以通过遍历通过他们显示的每一种可能的颜色?如果图像是由像素合成的,可不可以遍历每一种像素的组合并显示每一个可能存在的图片?

迷糊了没有?*_#

 

原创粉丝点击