Bonsoir,

Je galère depuis plusieurs jours pour un problème très simple à priori : lire une image au format BMP en couleur, et à partir de cela en créer une en noir et blanc (pas en niveau de gris), travailler dessus et ensuite l'enregistrer. Ceci est juste un petit préalable à un programme de traitement d'image sur lequel je travaille

Après deux façons de procéder que j'ai abandonné, j'ai décidé de lire et d'écrire directement les fichiers en binaire, en stockant les données dans des tableaux, sans utiliser aucune fonction graphique. En fait ce n'est pas plus mal car mon programme n'a pas besoin d'afficher les images

Donc après une nouvelle fois de longues recherches et essais, je tombe encore sur un os. Ce code ne fonctionne pas, le fichier resultat est illisible (les logiciels comme paint ou la visionneuse windows me disent que le fichier est corrompu); je ne vois pas où est l'erreur

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
Imports System
Imports System.IO
Imports System.Security.Permissions
 
Public Class Form1
    Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click
        'Ici on va lire et écrire directement un fichier BMP sans passer par les fonctions graphiques
        Dim mes As String
 
        Dim FichierImageDepart As String
        Dim FichierImageResultat As String
 
        Dim tmpb As Byte
        Dim tmps As String
        Dim tmpi As UInt16
        Dim tmpl As UInt32
 
        Dim i As Integer
 
        Dim Largeur As UInt32
        Dim Hauteur As UInt32
        Dim nBitsParPixel As UInt16
        Dim tailleImageOctets As UInt32
 
        Dim nOctetsParLigne As UInt32
        Dim nOctetsParLigne2 As UInt32
        Dim x As UInt32
        Dim y As UInt32
 
        FichierImageDepart = My.Application.Info.DirectoryPath + "\ImageALire_GRIS.BMP"
        'FichierImageDepart = My.Application.Info.DirectoryPath + "\ImageALire_GRIS2.BMP"
        FichierImageResultat = My.Application.Info.DirectoryPath + "\ImageResultat4.BMP"
 
        Dim binReader As New BinaryReader(File.Open(FichierImageDepart, FileMode.Open))
        'Lecture de l'entête
        'Lecture des deux octets descripteur de type
        tmps = binReader.ReadChars(2)
        If tmps <> "BM" Then
            MsgBox("Le fichier " + FichierImageDepart + "n'est pas de type BMP")
            Exit Sub
        End If
        'Taille du fichier
        tmpl = binReader.ReadUInt32
        'Reservé
        tmpl = binReader.ReadUInt32
        'Offset de l'image
        tmpl = binReader.ReadUInt32
        'Taille de l'entête image
        tmpl = binReader.ReadUInt32
        'Dimenssions de l'Image
        Largeur = binReader.ReadUInt32
        Hauteur = binReader.ReadUInt32
        'Nombre de plan
        tmpi = binReader.ReadInt16
        'Nombre de bits par pixel
        nBitsParPixel = binReader.ReadInt16
        If nBitsParPixel <> 24 Then
            MsgBox("Le fichier " + FichierImageDepart + "n'est pas en couleurs 24 bits, abandon de la lecture")
            Exit Sub
        End If
        'Methode de compression
        tmpl = binReader.ReadUInt32
        If tmpl <> 0 Then
            MsgBox("Le fichier " + FichierImageDepart + "est compressé, abandon de la lecture")
            Exit Sub
        End If
        'Taille de l'image en octets
        tailleImageOctets = binReader.ReadUInt32
        'Résolution de l'image
        tmpl = binReader.ReadUInt32
        tmpl = binReader.ReadUInt32
        'Couleurs utilisées
        tmpl = binReader.ReadUInt32
        'Couleurs importantes :
        tmpl = binReader.ReadUInt32
        '
        'Lecture de l'image
        Dim dataImage() As Byte = binReader.ReadBytes(tailleImageOctets)
 
        binReader.Close()
 
        mes = "Résolution = " + Format(nBitsParPixel) + " bits/pixel" + vbCrLf
        mes = mes + "Largeur = " + Format(Largeur) + " pixels" + vbCrLf
        mes = mes + "Hauteur = " + Format(Hauteur) + " pixels" + vbCrLf
        mes = mes + "Nb pixels image utile = " + Format(Largeur * Hauteur) + " pixel" + vbCrLf
        mes = mes + "Nb octets image utile = " + Format(Largeur * Hauteur * 3) + " octets" + vbCrLf
        mes = mes + "Taille de l'image = " + Format(tailleImageOctets) + " octets" + vbCrLf
        MsgBox(mes)
 
        nOctetsParLigne = Fix((Largeur * 3 + 3) / 4) * 4
 
        'Génération de la nouvelle image :
        nOctetsParLigne2 = Fix((Largeur + 31) / 32) * 4 'nOctetsParLigne doit être multiple de 4
        MsgBox("nOctetsParLigne = " + Format(nOctetsParLigne2))
        Dim dataImage2(nOctetsParLigne2 * Hauteur) As Byte
 
        'calcul de l'image en N&B à partir de l'image en couleur:
        For y = 0 To Hauteur - 1
            i = 1
            tmpi = 0
            tmpb = 0
            For x = 0 To Largeur - 1
                If i = 256 Then
                    i = 1
                    tmpb = 0
                    dataImage2(tmpi + nOctetsParLigne2 * y) = tmpb
                    tmpi = tmpi + 1
                End If
                'Calcul basique, juste une des trois couleurs RBV
                If dataImage(y * nOctetsParLigne + x * 3) > 128 Then
                    'On allume le pixel 
                    tmpb = tmpb + i
                End If
                i = 2 * i
            Next
            'Le dernier octet :
            dataImage2(tmpi + nOctetsParLigne2 * y) = tmpb
            'Les octets à 0 pour avoir une ligne multiple de 4 octets :
            If tmpi < nOctetsParLigne2 - 1 Then
                For i = tmpi + 1 To nOctetsParLigne2 - 1
                    dataImage2(i + nOctetsParLigne2 * y) = 0
                Next
            End If
        Next
 
        Dim binWriter As New BinaryWriter(File.Open(FichierImageResultat, FileMode.Create))
        'Ecriture de l'entête
        tmpi = &H4D42 : binWriter.Write(tmpi)
        'Taille du fichier
        tmpl = 54 + 1 + nOctetsParLigne2 * Hauteur
        binWriter.Write(tmpl)
        'Reservé
        tmpl = 0 : binWriter.Write(tmpl)
        'Offset de l'image
        tmpl = 54 : binWriter.Write(tmpl)
        'Taille de l'entête image
        tmpl = 40 : binWriter.Write(tmpl)
        'Dimenssions de l'Image
        binWriter.Write(Largeur)
        binWriter.Write(Hauteur)
        'Nombre de plan
        tmpi = 1 : binWriter.Write(tmpi)
        'Nombre de bits par pixel
        tmpi = 1 : binWriter.Write(tmpi)
        'Methode de compression
        tmpl = 0 : binWriter.Write(tmpl)
        'Taille de l'image en octets
        tmpl = nOctetsParLigne2 * Hauteur
        binWriter.Write(tmpl)
        'Résolution de l'image
        tmpl = 3780 : binWriter.Write(tmpl) : binWriter.Write(tmpl)
        'Couleurs utilisées
        tmpl = 0 : binWriter.Write(tmpl)
        'Couleurs importantes :
        tmpl = 0 : binWriter.Write(tmpl)
 
        'Les données
        binWriter.Write(dataImage2)
 
        binWriter.Close()
 
        MsgBox("Traitement terminé")
    End Sub
End Class
j'ai passer les fichiers à la loupe dans un éditeur hexadécimal et pareil, je ne comprends pas où est le problème, les entêtes sont correctes, les données au bon endroit et de bonne longueur :

Nom : hexa.jpg
Affichages : 1408
Taille : 419,0 Ko

NB : le fait que les données n'aient pas la bonne valeur est encore un autre problème mais pour le moment ce qui est important est de pouvoir générer un BMP valide, histoire de ne plus travailler en aveugle...

merci

A+