每个点的颜色信息用R、G、B三个分量表示,占用3Byte的空间。我是将图片文件用LoadPicture函数Load到一个StdPicture里面,
然后试过用GetDIBits,但会弄得VB非法操作
用GetBitmapBits又和文件的格式有关,不一定是3Byte表示一个象素请问这个问题如何解决?
谢谢!!

解决方案 »

  1.   

    事情好像没有你想象的那样简单,首先StdPicture是个类,里面的数据怎么存放恐怕不是那么容易弄明白的,你要使用GetBitmapBits,大概应该将该图片先显示在某一个HDC里,然后再用
    (没用过,猜测而已)。因为GetBitmapBits是对HDC进行操作的。请问为什么要将将一幅图片每个象素点的颜色信息转存到数组里面?
      

  2.   

    谢谢!!GetBitmapBits 不是对hDC操作吧,它的参数是hBitmap啊。只要图片是24Bits的,这个函数就能正
    常工作。我把图片装载到数组中是要对它进行分析,
    总不能分析时每次要取某个点的颜色信息就用一次GetPixel吧,而且我的处理在未完成以前,不会将结果显示出来,要不然每次更新一个点的颜色就要用一次SetPixel了。。
      

  3.   

    GetBitmapBits或者GetDIBits,没错啊,关键是用法!
      

  4.   

    这样做,首先声明一个BITMAP结构,然后按照以下方式调用这个SetRedColor函数。。SetRedColor FrmMain.Pic2.Image,SvaluePublic Sub SetRedColor(hbm As Long, aValue As Long)
    '************************
    ' red颜色调整
    '************************status = GetObjectAPI(hbm, Len(bm), bm)wid = bm.bmWidthBytes
    hgt = bm.bmHeightReDim bytes(1 To wid, 1 To hgt)
    status = GetBitmapBits(hbm, wid * hgt, bytes(1, 1))......End Sub这样bytes数组中就是你想要得数据了
      

  5.   

    用GetDIBits要注意些什么啊?
    我按例子上面抄的都会弄到VB非法操作,
    但例子却不会我不知道我究竟在什么地方没有注意到会搞成这样。。
    真郁闷
      

  6.   

    to agua06(阿瓜) :你那个做法只有在bm.bmBitsPixel为24的时候才可以得到我想要的数据,
    若bm.bmBitsPixel 为8, 则每一个字节表示一个象素点
    若bm.bmBitsPixel 为16,则每两个字节表示一个象素点
    都无法得到用RGB三分量表示的颜色信息。。
      

  7.   


        Dim bmp As BITMAP
       GetObject Picture1.Image, Len(bmp), bmp
       Text1 = "图片象素位数:" + Str(bmp.bmBitsPixel) + vbCrLf
       Text1 = Text1 + "图片象素宽度:" + Str(bmp.bmWidth) + vbCrLf
       Text1 = Text1 + "图片象素长度:" + Str(bmp.bmHeight) + vbCrLf
       Text1 = Text1 + "图片颜色平面数:" + Str(bmp.bmPlanes) + vbCrLf
       Text1 = Text1 + "图片位图数据指针:" + Str(bmp.bmBits) + vbCrLf
       Text1 = Text1 + "一个象素所需字节数:" + Str(bmp.bmWidthBytes / bmp.bmWidth)
    以上所取的数据给图片框中加入的图片无关,好像只给系统颜色设置,和本身的大小相关      ReDim picBmp(Picture1.ScaleHeight * Picture1.ScaleWidth * 4) As Byte
          GetBitmapBits Picture1.Image, UBound(picBmp), picBmp(0)
          '可以加工数据       SetBitmapBits Picture1.Image, UBound(picBmp), picBmp(0)
      

  8.   

    http://www.zjonline.com.cn/vbbible/software/program/vb/ccw/htmapi35.htm
      

  9.   

    谢谢大家!但你们所说的都只是从图像中取出各个Byte的数据,
    可能是1Byte表示一个象素点,也可能是2Bytes表示一个象素点。
    但要进行分析,我必须得到每个象素点的RGB信息,由3Bytes表示。如何将这些由1Byte或2Bytes或4Bytes长度数据表示的的颜色信息转化为由RGB三个分量表示的颜色信息呢?
    或者怎样从图片中直接取出每个点的RGB颜色信息?
    这是我问题的关键。我看过GetDIBits函数的介绍,应该可以实现我的要求,
    但是,不知道我什么地方没有注意,每次使用后,会出现VB非法操作。
      

  10.   

    SizeImage?  图片的Width和Height吗?以下是我代码:
    麻烦大家看看究竟有什么我没有注意的地方Private Sub AnalyseTest_Click()
    Dim bm As BITMAP
    Dim bi24BitInfo As BITMAPINFO
    Dim imgDatas1() As Byte     '图像数据
    Dim iDC As LongIf p Is Nothing Then Exit SubGetObjectAPI p.handle, Len(bm), bmWith bi24BitInfo.bmiHeader
        .biBitCount = 24
        .biCompression = BI_RGB
        .biPlanes = 1
        .biSize = Len(bi24BitInfo.bmiHeader)
        .biWidth = bm.bmWidth
        .biHeight = bm.bmHeight
    End WithReDim imgDatas1(1 To bm.bmWidth * 3, 1 To bm.bmHeight)iDC = CreateCompatibleDC(0)
    SelectObject iDC, p.handleGetDIBits iDC, p.handle, 0&, bm.bmHeight, imgDatas1(1, 1), bi24BitInfo, DIB_RGB_COLORSEnd Sub其中p是一个全局的StdPicture对象,
    加载图片的代码:
    Private Sub Open_Click()
    Dim filSys As New FileSystemObject
    ComDlg1.Filter = "图片文件|*.bmp;*.jpg;*.gif"
    ComDlg1.ShowOpen
    If filSys.FileExists(ComDlg1.FileName) Then
        Set p = LoadPicture(ComDlg1.FileName)
        Picture1.Picture = p
    End IfEnd Sub
      

  11.   

    TO:canyqf() 
    不好意思,那一段代码我的确没有在16位分量下测试过,只用了256色位图和24色和32色位图做的测试不过16色位图是2Byte为一个象素,你必须需要写一段代码来转换你的分量得
    所以你在获取图像得时候可以通过bi24BitInfo.bmiHeader.biBitCount来判断一下。当然,你也可以以另外一种方法来获得颜色数组,就是直接读取文件(当然必须是bmp位图,jpg得话就要转一下了)
    例子如下:
    Option Explicit
    '//////////////// 设备无关位图 (DIB)的大小及颜色信息  (它位于 bmp 文件的开头处)
    Private Type BITMAPINFOHEADER
        biSize As Long                         '结构长度
        biWidth As Long                        '指定位图的宽度,以像素为单位
        biHeight As Long                       '位图高度
        biPlanes As Integer                    '指定目标设备的级数(必须为 1 )
        biBitCount As Integer                  '每一个像素的位(1,4,8,16,24,32)
        biCompression As Long                  '指定压缩类型(BI_RGB 为不压缩)
        biSizeImage As Long                    '指定图象的大小,以字节为单位
        biXPelsPerMeter As Long                '指定设备水平分辨率,以每米的像素为单位
        biYPelsPerMeter As Long                '垂直分辨率,其他同上
        biClrUsed As Long                      '在颜色表中实际使用的色彩索引的个数,用O表示全要使用
        biClrImportant As Long                 '指定认为重要的颜色索引个数,用 0 表示所有颜色均中药
    End Type
    '//////////////// 描述了由红、绿、蓝组成的调色板颜色组合
    Private Type RGBQUAD
        rgbBlue As Byte
        rgbGreen As Byte
        rgbRed As Byte
        rgbReserved As Byte    '保留,必须为 0
    End Type
    '//////////////// DIB 的大小及颜色信息
    Private Type BITMAPINFO
        bmiHeader As BITMAPINFOHEADER
        bmiColors(0 To 255) As RGBQUAD
    End Type
    '/////////////// DIB 的文件大小及结构信息
    Private Type BITMAPFILEHEADER
        bfType As Integer                       '指定文件类型,必须 BM
        bfSize As Long                          '指定位图文件大小,以字节为单位
        bfReserved1 As Integer                  '保留,必须设为0
        bfReserved2 As Integer                  '同上
        bfOffBits As Long                       '从此结构到位图数据位的字节偏移量
    End TypePrivate Type BITMAP
             bmType              As Long
             bmWidth             As Long
             bmHeight            As Long
             bmWidthBytes        As Long
             bmPlanes            As Integer
             bmBitsPixel         As Integer
             bmBits              As Long
    End Type
    Private Declare Function CloseHandle& Lib "kernel32" (ByVal hObject As Long)
    Private Declare Function CreateFile& Lib "kernel32" Alias "CreateFileA" (ByVal lpFileName As String, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long)
    Private Declare Function ReadFile& Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesTOread As Long, lpNumberOfBytesRead As Long, ByVal lpOverlapped As Long)
    Private Declare Function WriteFile& Lib "kernel32" (ByVal hFile As Long, lpBuffer As Any, ByVal nNumberOfBytesToWrite As Long, lpNumberOfBytesWritten As Long, ByVal lpOverlapped As Long)Private Const RASTERCAPS = 38
    Private Const RC_DIBTODEV = &H200
    Private Const DIB_RGB_COLORS = 0
    Private Const SRCCOPY& = &HCC0020
    Private Const CBM_INIT& = &H4
    Private Const GENERIC_READ& = &H80000000
    Private Const GENERIC_WRITE& = &H40000000
    Private Const CREATE_NEW& = 1
    Private Const OPEN_EXISTING& = 3
    Private Const FILE_ATTRIBUTE_NORMAL& = &H80
    Dim m_BMInfo As BITMAPINFO
    Dim m_BitData() As Byte
    Dim m_BMFileHeader As BITMAPFILEHEADER
    Dim m_FadeBMInfo() As BITMAPINFO
    Dim bm As BITMAP
    Dim m_FilePointer As Long
    Dim m_ReadFileName As String
    Dim m_WriteFileName As String
    Dim n As Long
    Dim dl&
    Dim DIBCont As LongPrivate Sub Command1_Click()   
    m_ReadFileName = "c:\1.bmp"m_FilePointer = CreateFile(m_ReadFileName, GENERIC_READ Or GENERIC_WRITE, 0&, 0&, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0&)
     
     
     dl& = ReadFile(m_FilePointer, m_BMFileHeader.bfType, Len(m_BMFileHeader.bfType), n, 0&)
     
     dl& = ReadFile(m_FilePointer, m_BMFileHeader.bfSize, Len(m_BMFileHeader.bfSize), n, 0&) dl& = ReadFile(m_FilePointer, m_BMFileHeader.bfReserved1, Len(m_BMFileHeader.bfReserved1), n, 0&) dl& = ReadFile(m_FilePointer, m_BMFileHeader.bfReserved2, Len(m_BMFileHeader.bfReserved2), n, 0&) dl& = ReadFile(m_FilePointer, m_BMFileHeader.bfOffBits, Len(m_BMFileHeader.bfOffBits), n, 0&) dl& = ReadFile(m_FilePointer, m_BMInfo.bmiHeader.biSize, Len(m_BMInfo.bmiHeader), n, 0&)
     
    If m_BMFileHeader.bfOffBits > 54 Then
     dl& = ReadFile(m_FilePointer, m_BMInfo.bmiColors(0), Len(m_BMInfo.bmiColors(0)) * 256, n, 0&)
    End IfIf m_BMInfo.bmiHeader.biSizeImage = 0 Then
       DIBCont = m_BMFileHeader.bfSize - m_BMFileHeader.bfOffBits
    Else
       DIBCont = m_BMInfo.bmiHeader.biSizeImage
    End If
     ReDim m_BitData(DIBCont)
     dl& = ReadFile(m_FilePointer, m_BitData(0), DIBCont, n, 0&)
     Debug.Print dl
     dl& = CloseHandle(m_FilePointer)
     MsgBox "Open OK"
     
    End Sub这样,m_BitData就是你的数据数组了,当然。颜色分量得分离还是需要自己分离一下才可以。没办法。毕竟16位图和一般的8位,24位不一样。就是windows自己读出来也是要分析转换得。所以我觉得提取数据这个算是最快的方法了。当然如果其他得朋友还有更好的办法也可以贴出来看看。
      

  12.   

    TO: thirdapple(陨落雕)
    楼上得楼上得代码?是说我的那一段嘛?
    我那一段代码可以运行的,这个我已经测试过了。顺便补充一下:我之前得那段代码可以用于8位位图得,因为8位位图使用的是调色版,所以取出来的数据其实就是调色版的索引。只需要再加一段判断并读取调色版的代码就成了。当时我忘记一起贴出来,在这里说句不好意思
      

  13.   

    这样你不觉得烦吗?楼上的
    你那段代码是针对24位的,没有实际意义,楼主用GetDIBits的方法是正确的,只是有地方要改而已
    With bi24BitInfo.bmiHeader
        .biBitCount = 24
        .biCompression = BI_RGB
        .biPlanes = 1
        .biSize = Len(bi24BitInfo.bmiHeader)
        .biWidth = bm.bmWidth
        .biHeight = bm.bmHeight
        .biSizeImage = ((.biWidth * 3 + 3) And &H7FFFFFFC) * .biHeight
        '必须要算SizeImage
    End With
    ReDim imgDatas1(1 To bm.bmWidth * 3, 1 To bm.bmHeight)
    最好别这么定义,如果要这么定义的话也应该
    ReDim imgDatas1(1 To bm.bmWidth * 3 + 3) And &H7FFFFFFC, 1 To bm.bmHeight)
    推荐定义为一维的
      

  14.   

    呵呵,GetDIBits我还真的很少用,GetBitmapBits也是自己摸索出来的,所以记忆比较深刻不过楼主得程序即使这样改,遇到16位图也是一样需要自己再做分量得嘛,而且上面那段程序中biBitCount = 24也规定了必须24位才可以使用,按照你的说法,和我的程序有什么区别嘛?
      

  15.   

    阿瓜,看看GetDIBits的说明,用GetDIBits是要按照bi24BitInfo的结构读入的,如果不是24位就会自动转换为24位读入
    其实你用GetBitmapBits的方法也不大对,用GetBitmapBits我一般是自己建一个与设备无关的位图和DC然后才使用:)
      

  16.   

    呵呵,你说的对,GetBitmapBits现在我也是使用TempDC来做的,这样方便一些:)
    那么顺便再问个问题:与GetDIBits对应的还有一个SetDIBits函数,那么如果将16位色的位图读入,再用SetDIBits得话,还可以保证原来的效果嘛?
    另外上面一句Redim中
    ReDim imgDatas1(1 To bm.bmWidth * 3 + 3) And &H7FFFFFFC, 1 To bm.bmHeight)
    后面的 And &H7FFFFFFC是什么意思?请指教
      

  17.   

    在BMP图象中,WidthBytes永远是4的倍数,而如果用三个字节表示一个象素就会有WidthBytes不是4的倍数的情况,And &H7FFFFFFC将WidthBytes补成4的倍数
      

  18.   

    第一个问题,显示应该结果是相同的,保存为文件可能就不同了(如果建的是与设备有关的位图,如PictureBox),
    所以写图象处理软件PictureBox只是起显示作用,在PictureBox上处理是不明智的,如果系统位深不高保存的文件效果很差
      

  19.   

    多谢thirdapple(陨落雕) !
    多谢大家!!