这几天老是有人问小弟我图像获取的有关问题,其实这个有关问题很多人都回答过,小弟我也总结过,可能没有写在CSDN的博客下,这里在转发一上,希望大家不要在为这个有关问题加小弟我了

这几天老是有人问我图像获取的问题,其实这个问题很多人都回答过,我也总结过,可能没有写在CSDN的博客上,这里在转发一下,希望大家不要在为这个问题加我了。
本帖最后由 laviewpbt 于 2010-05-27 22:32:57 编辑 我在博客园上发表过的,可能那里用VB的人不多

http://www.cnblogs.com/laviewpbt/archive/2009/05/31/1493222.html
http://www.cnblogs.com/laviewpbt/archive/2009/05/31/1492878.html


一:利用GDI快速获取图像数据及处理中需注意的问题
示例工程:http://files.cnblogs.com/laviewpbt/GetDibits.rar

说明:本文中大部分资料亦适合于VC或其他编程语言。

谈起VB中的图像,很多人觉得VB对图像的支持太弱了,实际上,我觉得,比起VC,VB对图像的编程要方便很多。神奇的AutoRedraw,多格式的图像文件支持,AutoSize让你少去不少麻烦等等,而这些在VC中都是需要不少额外的代码的,并且VB内部用底层函数对这些功能的封装,使得其执行效率亦是相当高的。那么,今天,我要给大家用一个简单的反色程序说明如何用VB实现对各种色深的图片的处理,让你对VB信心十足。

一、打开图像。

这个很简单,直接使用 LoadPicture(其实就是对OleLoadPicture这个函数的封装),其支持BMP,JPG,GIF,ICO,WMF,EMF格式。这里说明一下,对于由柯达控件生成的BMP,部分GIF和JPEG2000,以及32位的ICO这个函数似乎会产生一些未知的错误。JPG格式加载后,无论原始的JPG是否是8位的,在内存中VB是以24位的DIB格式图像保存的,而GIF则以8位索引色放置于内存。至于BMP格式,则可以按照原始的文件位数加载。我们可以用下面的函数来认证。

Private Function GetBitmapColorDepth(Pic As StdPicture) As Long
        Dim Bmp As Bitmap
        GetGDIObject Pic.Handle, Len(Bmp), Bmp
        GetBitmapColorDepth = Bmp.bmBitsPixel
    End Function

二、保存图像。

这个也很简单,SavePicture函数,注意,对于BMP、ICO、WMF、EMF格式,SavePicture函数能以原始格式保存,而对于加载的GIF和 JPG格式,只能将图像保存为BMP格式,无论你给他的路径参数的后缀是什么(看到有些VB的书上居然说将后缀改为JPG就能保存为JPG格式,真是傻)。并且该函数能保留原始的位深,这对我们来说是个好消息。那么这个函数的实现在我看来也很简单,用VB内部的语言来表达就是:
    Put #FileNum, , BmpInfoHeader          'BMP文件头
    Put #FileNum, , mBmpInfo                '位图信息头
    If mBmpInfo.biBitCount <= 8 Then Put #FileNum, , ColorTable  '调色板
    Put #FileNum, , DibBytes                '位图数据

三、图像数据的获得

这个地方就是大家常常说VB慢的罪魁祸首,因为VB的自带了一个四不像的Point和Pset函数,而这两个函数可以得到和设置图像的颜色,因此,常常会作为初学者的最爱工具,而最终的结果就是让VB落得一个骂名:龟速。 

总结一下,在 VB中可以用来得到图像数据的常用API函数有:Point|Pset; 

GetPixel|SetPixel;  GetBitmapBits|SetBitmapBits; GetDIBits|SetDIBits ; SafeArray模拟指针等等。抛弃前两组不说,因为他们是一丘之貉。第三组函数因为是DDB函数,是设备相关的,个人认为不是很好,因为我体验过他莫名其妙的失败。最后一组因为其复杂性,不作为向大家推荐的函数。因此,我们重点谈谈 GetDIBits。
    Private Declare Function GetDIBits Lib "gdi32" Alias "GetDIBits" (ByVal aHDC As Long, ByVal hBitmap As Long, ByVal nStartScan As Long, ByVal nNumScans As Long, lpBits As Any, lpBI As BITMAPINFO, ByVal wUsage As Long) As Long

谈起GetDIBits,我们重点讲讲参数lpBits,这个参数表示存储图像数据的缓冲区首地址,编程时只需要将一个数组的第一个元素赋值给他就可以了, 而如何确定这个数组的大小是值得商榷的。我们知道,对于不同的位深每个像素所占用的字节数是不同的,既然VB保留了被加载的图像的位深,那么我们在对图像进行后续处理的时候就应该按照这个位深来给图像数据缓冲区分配内存。不过,也许大家在实际的应用中并没有这样做,而是统一把 BITMAPINFO.bmiHeader.biBitCount设置为32或者为24,那么这里其实GetDIBits 帮我们帮图像的原始格式的数据转换为我们所需要的数据了。 
    

好,下面给出一个简单的处理反色的函数。


------最佳解决方案--------------------
顶顶顶~
------其他解决方案--------------------


Option Explicit
Private Type BITMAPFILEHEADER
    bfType      As Integer
    bfSize      As Long
    bfReserved1 As Integer
    bfReserved2 As Integer