Salve a tutti. Ho questo problema: devo estrarre una matrice dei dati relativi ai livelli di colore di immagini di tipo bitmap al fine di effettuare su questi analisi successive. Ho preparato le macro per l'estrazione dati da matrice e per l'analisi degli stessi perchè ho esperienza di programmazione Fortran. Purtroppo, sulla gestione delle immagini e sul VBA sono neofita. Dopo aver studiato il problema (Loadimage con LR-CreateDIBSection+GetObject dal DIBSection) anche su questo sito ed altrove, senza riuscire, ho trovato il cosice allegato che funziona ma non riesce a gestire le mie immagini BMP che hanno più di 100 livelli di grigio: qualcuno può aiutarmi?
Grazie
Gaetano
codice:Option Explicit '################################################################### ' Full Credit to Gary Simmons for this BMP loader code ' Demonstration/tutorial of reading and manually drawing an ' uncompressed (most) bitmap Free for any use: ' see included file (BMP.TXT) for Bitmap file info reference. ' ' Please email me at gary.simmons@optushome.com.au if you find this ' useful ' ' 21st December 2001 Gary Simmons '################################################################### Private Type BitMapFile 'bitmap file header structure bfType As String * 2 bfSize As String * 4 bfReserved1 As String * 2 bfreserved2 As String * 2 bfOffset As String * 4 End Type Private Type BitMapInfo 'bitmap info header structure biSize As String * 4 biWidth As String * 4 biHeight As String * 4 biPlanes As String * 2 biBitCount As String * 2 biCompression As String * 4 biSizeImage As String * 4 biXPelsPerMeter As String * 4 biYPelsPerMeter As String * 4 biClrUsed As String * 4 biClrImportant As String * 4 End Type Private Type RGBQuads 'RGBQuad structure (temporary) cBlue As String * 1 cGreen As String * 1 cRed As String * 1 cReserved As String * 1 End Type Private Type RGBQuad 'RGBQuad (used in index) Blue As Byte Green As Byte Red As Byte End Type Public Sub GetBmpValues(Filename As String, BMPData() As Long, Progress As MSForms.Label) ' show information about the bitmap and ' manually draw it in another Picturebox Dim bmf As BitMapFile Dim bmi As BitMapInfo Dim rgbqs As RGBQuads Dim rgbq(255) As RGBQuad Dim s1 As String * 1 Dim Dword As String * 4 Dim lngCol As Long Dim lngRow As Long Dim IWidth As Long Dim IBitCount As Integer Dim Pointer As Long Dim i As Integer Dim ClrInd As Integer Dim aMask As Long Dim z As Integer Dim ByteNum As Integer Dim ThisByte As Byte Dim ColoursFound As Integer Dim ThisRed As Byte Dim ThisGreen As Byte Dim ThisBlue As Byte Const MAX_WIDTH = 256 Const MAX_HEIGHT = 65536 Progress.Caption = "Reading BMP " & Filename DoEvents Open Filename For Binary As #1 Get #1, , bmf 'load the file header Get #1, , bmi 'info header follows If lVal(bmi.biSize) <> 40 Or bmf.bfType <> "BM" Then MsgBox "Not a compatible bitmap." Close #1 Exit Sub End If 'load the relevant colour tables If lVal(bmi.biBitCount) = 1 Then For i = 0 To 1 Get #1, , rgbqs rgbq(i).Red = lVal(rgbqs.cRed) rgbq(i).Green = lVal(rgbqs.cGreen) rgbq(i).Blue = lVal(rgbqs.cBlue) Next i ElseIf lVal(bmi.biBitCount) = 4 Then For i = 0 To 15 Get #1, , rgbqs rgbq(i).Red = lVal(rgbqs.cRed) rgbq(i).Green = lVal(rgbqs.cGreen) rgbq(i).Blue = lVal(rgbqs.cBlue) Next i ElseIf lVal(bmi.biBitCount) = 8 Then For i = 0 To 255 Get #1, , rgbqs rgbq(i).Red = lVal(rgbqs.cRed) rgbq(i).Green = lVal(rgbqs.cGreen) rgbq(i).Blue = lVal(rgbqs.cBlue) Next i End If ' show the properties of the bitmap ' some don't seem to be used ' MsgBox "Actual File Size:" & (Str(LOF(1))) & " bytes" & vbCrLf & _ ' "Bitmap File Size: " & lVal(bmf.bfSize) & " bytes" & vbCrLf & _ ' "Bitmap Width: " & lVal(bmi.biWidth) & " pixels" & vbCrLf & _ ' "Bitmap Height: " & lVal(bmi.biHeight) & " pixels" & vbCrLf & _ ' "Bitmap Offset: " & lVal(bmf.bfOffset) & vbCrLf & _ ' "Bitmap BitPlanes: " & lVal(bmi.biPlanes) & vbCrLf & _ ' "Bitmap BitCount: " & lVal(bmi.biBitCount) & " bit/pixel" & vbCrLf & _ ' "Bitmap Size: " & lVal(bmi.biSizeImage) & " bytes" & vbCrLf & _ ' "Bitmap ClrUsed: " & lVal(bmi.biClrUsed) & vbCrLf & _ ' "Bitmap ClrsImportant: " & lVal(bmi.biClrImportant) & vbCrLf & _ ' "Bitmap Compression: " & lVal(bmi.biCompression) If lVal(bmi.biCompression) <> 0 Then MsgBox "Its a compressed bitmap." Close #1 Exit Sub End If Close #1 If lVal(bmi.biBitCount) <= 8 Then ' the file is either: ' mono (1-bit/pixel) ' 16-color (4-bit/pixel) ' 256-color (8-bit/pixel) Open Filename For Binary As #1 lngCol = 0 'holds X position of pixel to draw lngRow = lVal(bmi.biHeight) '- 1 'holds Y position (Note: bitmap stored from lowest line to highest) IWidth = lVal(bmi.biWidth) 'width of bitmap ReDim BMPData(lngRow, IWidth) As Long IBitCount = lVal(bmi.biBitCount) ' bits/pixel (1,4,8) Get #1, lVal(bmf.bfOffset), s1 'move binary pointer to start of bitmap Do While Not EOF(1) Get #1, , Dword ' read 4-bytes at a time ByteNum = 1 ' start with first byte in double word Do While lngCol < IWidth And ByteNum < 5 'stop drawing if edge of bitmap encountered or processed every byte in dword ThisByte = lVal(Mid(Dword, ByteNum, 1)) 'get relevant byte Pointer = 8 ' start bit pointer Do If lngCol < IWidth Then 'only bother if edge of bitmap not reached aMask = 0 'reset bit-mask For z = Pointer To Pointer - IBitCount + 1 Step -1 'the best algorithm aMask = aMask + 2 ^ (z - 1) 'I could come up with to build a bit-mask Next z ClrInd = (ThisByte And (aMask)) / (2 ^ (Pointer - IBitCount)) ' mask of relevant bits and reduce to an appropriate index BMPData(lngRow, lngCol + 1) = RGB(rgbq(ClrInd).Red, rgbq(ClrInd).Green, rgbq(ClrInd).Blue) 'set the pixel the colour End If Pointer = Pointer - IBitCount 'move to the next appropriate bits lngCol = lngCol + 1 'move the X-position Loop Until Pointer = 0 'not more bits to process - exit ByteNum = ByteNum + 1 'point to the next byte in the dword Loop If lngCol >= IWidth Then 'if, after processing this dword, we have Progress.Caption = "Lines remaining " & lngRow DoEvents lngRow = lngRow - 1 'reached the end of a line then If lngRow = 0 Then Exit Do lngCol = 0 'get the next line and reset the X-position End If Loop Close #1 ElseIf lVal(bmi.biBitCount) = 24 Then ' 16Million-color (24-bit/pixel) Open Filename For Binary As #1 lngCol = 0 lngRow = lVal(bmi.biHeight) ' - 1 IWidth = lVal(bmi.biWidth) ReDim BMPData(lngRow, IWidth) As Long IBitCount = lVal(bmi.biBitCount) Get #1, lVal(bmf.bfOffset), s1 ColoursFound = 0 'need 3-colours to form a pixel Do While Not EOF(1) Get #1, , Dword 'get 4-bytes ByteNum = 1 Do While lngCol < IWidth And ByteNum < 5 ThisByte = lVal(Mid(Dword, ByteNum, 1)) If lngCol < IWidth Then ColoursFound = ColoursFound + 1 Select Case ColoursFound Case Is = 1 'first byte in three is blue (contradicts BMP.TXT) ThisBlue = ThisByte Case Is = 2 'second byte is green ThisGreen = ThisByte Case Is = 3 'third byte is red ThisRed = ThisByte 'got the colours we need 'draw the pixel and move on to next pixel BMPData(lngRow, lngCol + 1) = RGB(ThisRed, ThisGreen, ThisBlue) ColoursFound = 0 lngCol = lngCol + 1 End Select End If ByteNum = ByteNum + 1 Loop If lngCol >= IWidth Then Progress.Caption = "Lines remaining " & lngRow DoEvents lngRow = lngRow - 1 If lngRow = 0 Then Exit Do lngCol = 0 End If Loop Close #1 End If End Sub Function lVal(vStr As String) As Long 'convert little-endian string to long integer Dim i As Integer Dim t As Long t = 0 For i = 1 To Len(vStr) t = t + Asc(Mid(vStr, i, 1)) * (256 ^ (i - 1)) Next i lVal = t End Function Sub BMPToChart() frmBMPLoader.Show Unload frmBMPLoader End Sub

Rispondi quotando