★搜Asp.net★(www.soAsp.net),为专业技术文档网站。
包括Asp.net开发技术文档·C#开发技术文档·Access/SQL Server数据库开发技术文档·VB.NET开发技术文档。
还包括·项目实战经验总结·开发经验技巧总结·项目开发心得。
DirectX与VB.NET实现色深理论与图片智能加载

    学到这里,DirectDraw的基础内容都已经差不多了,虽然还有Lock等内容没有讲,但那些内容已经没有任何应用价值,剩下几章就是进阶内容了,之后就要结束DirectDraw的学习了。
这次的内容分两个部分,色深理论与图片的智能加载
===============华丽的分割线===============

学习内容:
·掌握色深的理论知识
·了解获取显存剩余空间和图片尺寸的方法
·图片的智能加载

===============华丽的分割线===============

色深(Color Depth),或像素位(BitPerPixel)指的是屏幕像素点上每个点所能容纳的最大颜色数,显然,色深越高,画面所能显示的颜色也就越丰富。例如16色代表每个像素点只能显示16种颜色,而256色分别代表每个像素点上能够显示256种颜色,这显然就比16位色要好,但是它也会花费更多的储存空间,因此采用合适的色深至关重要,下面我将就色深概念进行大概的阐述,因为这方面可能涉及计算机图形学,本人并非该项专攻,如有疏漏,还望有高手批评指正。

===============华丽的分割线===============

色深的表示方法:和其它概念差不多,色深也有自己的表示方法,通常情况下,我们可以直呼起颜色数,例如16色、256色、65536色等,但是很显然,如果数字过大,就会不便于称呼,因此,人们引入了一个新的称呼方法,或一个新的单位:位(Bit),色数与位之间通过指数转换,因为计算机采用二进制,因此我们使用2作为底数,遵循如下公式:
色数=2^位,位=log2(色数)
因此,我们便可以称呼16色为4位色,256色为8位色,此外还有16位色、24位色。

===============华丽的分割线===============

色深之间的转换:既然有这么多的色深,很显然,因为他们的取值范围不同,他们之间肯定是无法互相兼容的,例如在16色中,15代表白色,而256色中,255才代表白色,而15可能只是很深灰色而已,甚至说255在256色中代表黑色,而在16色中根本就不存在这个颜色,系统只好用黑色代替。就好比是在二进制中,“11”代表3,而八进制中,“11”则代表9,大家可以看下图,左边是24位色的图片,右边则是它在256色环境下显示出来的样子:

因此,为了避免出现以上状况,我们在绘图时尽量选用同色深的图片,如果你获得的图片色深不符,可以使用各种工具进行转化,如ACDSee、Photoshop、ImageReady甚至Windows图画都有这些功能。跨色深调用是不可取的。

===============华丽的分割线===============

颜色的组成:凡是计算机所能显示的颜色,都是以三种颜色以不同比例混合而成的,这就是所谓的三原色理论(Tricolor),通常情况下,计算机采用最为普遍的红(Red)绿(Green)蓝(Blue)作为三原色来进行显示,我们称其为RGB模式,而RGB模式规定红、绿、蓝取值范围分别为0-255,也就是说,RGB模式所表示颜色为8*3=24位色,这也是我们人眼所能看到的最大颜色范围,因此我们称24位色为真彩色,后来,人们又在24位色的基础上加入了透明通道,用于表示像素的透明值,我们称这种颜色模式为ARGB(Alpha RGB),该模式规定额外用0-255来表示透明的程度,因此,ARGB的位数为8*4=32,也就是我们所说的32位色,这就是为什么32位色不能同其它位色进行转换的原因,如果需要转换,则必须先去除透明通道上的8位数。
除了颜色之外,颜色还有另外一个概念,即HLS(Hue色调、Lighteness亮度、Saturation饱和度),关于这之间的转换,可以参考微软的教程文章
http://support.microsoft.com/kb/29240(C++)。

===============华丽的分割线===============

图片的智能加载:
这里所说的智能加载也并非你想象的像人工智能那样高级,只是是指在显存不够用时将图片加载进内存以免显存溢出而已。要判断显存是否可以容纳图片,我们需要通过设备的HardwareCaps.VideoMemoryFree属性取到剩余显存的值,然后再加载图片到Bitmap对象中,获取其宽(Width)、高(Height)和色深(PixelFormat),把它们相乘就是图片占用显存的大小,最后和图片的大小进行比较,就可以作出判断了,这里的代码只贴出了背屏的处理代码,主屏依然放在显存中。代码如下:
Dim vSecondarySurface As Surface
Dim vSecondarySurfaceCaps As New SurfaceCaps
Dim vSecondarySurfaceDesc As SurfaceDescription

'取得图片大小
Dim vBitmap As New Bitmap(OpenFileDialog1.FileName)
Dim vSize As Integer = vBitmap.Width * vBitmap.Height * Convert(vBitmap.PixelFormat)

'取得剩余显存空间
Dim vVideoFree As Integer = vDevice.HardwareCaps.VideoMemoryFree

'比较显存是否足够
If vVideoFree > vSize Then
    '显存足够,使用显存进行存放
    MsgBox("显存空间足够,剩余显存:" + vVideoFree.ToString + " 图片大小:" + vSize.ToString)
    vSecondarySurfaceCaps.VideoMemory = True
Else
    '显存不足,使用内存进行存放
    MsgBox("显存空间不足,剩余显存:" + vVideoFree.ToString + " 图片大小:" + vSize.ToString)
    vSecondarySurfaceCaps.SystemMemory = True
End If

'初始化表面、加载图片并显示剩余显存
vSecondarySurfaceCaps.OffScreenPlain = True
vSecondarySurfaceDesc = New SurfaceDescription(vSecondarySurfaceCaps)
vSecondarySurface = New Surface(OpenFileDialog1.FileName, vSecondarySurfaceDesc, vDevice)
vVideoFree = vDevice.HardwareCaps.VideoMemoryFree
MsgBox("图片已加载,剩余显存:" + vVideoFree.ToString)

此外需要注意的是,Bitmap的PixelFormat属性取到的只是一些枚举,因此我们自己写一个函数需要将其转化为Integer类型:
Private Function Convert(ByVal EnumType As Drawing.Imaging.PixelFormat) As Integer
    Select Case EnumType
        Case Imaging.PixelFormat.Format16bppArgb1555
            Return 16
        Case Imaging.PixelFormat.Format16bppGrayScale
            Return 16
        Case Imaging.PixelFormat.Format16bppRgb555
            Return 16
        Case Imaging.PixelFormat.Format1bppIndexed
            Return 1
        Case Imaging.PixelFormat.Format24bppRgb
            Return 24
        Case Imaging.PixelFormat.Format32bppArgb
            Return 32
        Case Imaging.PixelFormat.Format32bppPArgb
            Return 32
        Case Imaging.PixelFormat.Format32bppRgb
            Return 32
        Case Imaging.PixelFormat.Format48bppRgb
            Return 48
        Case Imaging.PixelFormat.Format4bppIndexed
            Return 4
        Case Imaging.PixelFormat.Format64bppArgb
            Return 64
        Case Imaging.PixelFormat.Format64bppPArgb
            Return 64
        Case Imaging.PixelFormat.Format8bppIndexed
            Return 8
        Case Else
            Return 1
    End Select
End Function

===============华丽的分割线===============

限于篇幅,这次的内容就到这里,下次是图片文件的构造和截图。