Bonjour,

je viens de me lancer dans la manipulation d'images avec Marshal en VB.NET

je suis en train de tester ce code (qui convertit une image en Noir et Blanc, c'est à dire bitmap 1bit) et je ne comprends pas où est le bug

voici l'image de départ :

Nom : ImageALire_GRIS.gif
Affichages : 423
Taille : 5,4 Ko

et l'image d'arrivée :

Nom : ImageResultat.gif
Affichages : 433
Taille : 3,9 Ko

et le code :

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
   Private Sub Button3_Click(sender As System.Object, e As System.EventArgs) Handles Button3.Click
        Dim FichierImageDepart As String
        Dim bm As Bitmap
        Dim bm2 As Bitmap
        Dim bmpDataOld As System.Drawing.Imaging.BitmapData
        Dim width As Integer
        Dim height As Integer
        Dim g As Graphics 'Variable temporaire
 
        Dim FichierImageEtape1 As String
 
        Dim FichierImageResultat As String
        Dim bitmap1Bit As Bitmap 'Image finale
        Dim bmpDataNew As System.Drawing.Imaging.BitmapData
 
        'tables de precalcul des multiplications pour le calcul du niveau de gris
        Dim tabBleu(256) As Integer
        Dim tabVert(256) As Integer
        Dim tabRouge(256) As Integer
        'le pattern à appliquer (il était à l'origine destiné à des niveaux de gris de 64)
        Dim pattern() As Byte = {0, 32, 8, 40, 34, 2, 10, 42 _
                                  , 0, 32, 8, 40, 34, 2, 10, 42 _
                                  , 48, 16, 56, 24, 50, 18, 58, 26 _
                                  , 12, 44, 4, 36, 14, 46, 6, 38 _
                                  , 60, 28, 52, 20, 62, 30, 54, 22 _
                                  , 3, 35, 11, 43, 1, 33, 9, 41 _
                                  , 51, 19, 59, 27, 49, 17, 57, 25 _
                                  , 15, 47, 7, 39, 13, 45, 5, 37 _
                                  , 63, 31, 55, 23, 61, 29, 53, 21}
 
        Dim pix, locOld, locNew, x, y As Integer
        Dim newpix As Byte
 
        'Les fichiers :
        FichierImageDepart = My.Application.Info.DirectoryPath + "\ImageALire_GRIS.BMP"
        FichierImageEtape1 = My.Application.Info.DirectoryPath + "\ImageEtape1.BMP"
        FichierImageResultat = My.Application.Info.DirectoryPath + "\ImageResultat.BMP"
 
        'Chargement de l'image de départ :
        bm2 = New Bitmap(FichierImageDepart)
        width = bm2.Width
        height = bm2.Height
 
        If bm2.PixelFormat <> System.Drawing.Imaging.PixelFormat.Format32bppArgb Then
            bm = New Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
            g = Graphics.FromImage(bm)
            g.DrawImage(bm2, 0, 0, width, height)
        Else
            bm = bm2
        End If
        bm2.Dispose()
 
        MsgBox(bm.PixelFormat.ToString) 'C'est OK
        Call SauverImage(bm, FichierImageEtape1) 'L'image est OK
 
        bitmap1Bit = New Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format1bppIndexed)
 
        bmpDataOld = bm.LockBits(New Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        bmpDataNew = bitmap1Bit.LockBits(New Rectangle(0, 0, width, height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format1bppIndexed)
 
        Dim oldPixel(width * height * 4 - 1) As Byte
        System.Runtime.InteropServices.Marshal.Copy(bmpDataOld.Scan0, oldPixel, 0, oldPixel.Length)
 
        Dim newPixel(bmpDataNew.Stride * height - 1) As Byte
        'Pas necessaire de recuperer les donnees de l'image vierge par un Marshal.Copy
 
        'tables de precalcul des multiplications pour le calcul de localisation des pixels de l'ancienne image et de la nouvelle.
        Dim multiOld(height) As Integer
        Dim multiNew(height) As Integer
        For y = 0 To height - 1
            multiOld(y) = width * y
            multiNew(y) = bmpDataNew.Stride * y
        Next
        'Initialisation
        For y = 0 To 255
            tabBleu(y) = 76 * y
            tabVert(y) = 151 * y
            tabRouge(y) = 28 * y
        Next
 
        For y = 0 To height - 1
            For x = 0 To width - 1
                'on récupère le niveau de gris sur 255
                locNew = multiNew(y) + (x / 8)
                locOld = (multiOld(y) + x) * 4
                'Formule ci-dessous en commentaires, à éviter car coûteuse
                'pix = CByte(0.3 * oldPixel(locOld) + 0.59 * oldPixel(locOld + 1) + 0.11 * oldPixel(locOld + 2))
                pix = (tabBleu(oldPixel(locOld)) + tabVert(oldPixel(locOld + 1)) + tabRouge(oldPixel(locOld + 2))) >> 8
 
                If ((pix >> 2) > pattern(((x And 7) << 3) + (y And 7))) Then
                    'On allume le pixel
                    newpix = newpix Or (1 << (7 - (x Mod 8)))
                End If
                If (x Mod 8 = 0) Then
                    'quand on a rempli 8 bits
                    'on écrit le byte dans l'image
                    newPixel(locNew) = newpix
                    'on éteint tous les pixels
                    'pour le nouveau cycle de 8 bits
                    newpix = 0
                End If
            Next
        Next
 
        'on recopie notre nouveau tableau dans la nouvelle image
        System.Runtime.InteropServices.Marshal.Copy(newPixel, 0, bmpDataNew.Scan0, newPixel.Length)
 
        bitmap1Bit.UnlockBits(bmpDataNew)
        bm.UnlockBits(bmpDataOld)
 
        'Mauvaise image avec cette méthode de sauvegarde :
        'Call SauverImage(bitmap1Bit, FichierImageResultat) 
 
        'Mauvaise image avec cette méthode de sauvegarde aussi - le bug est dans le code de calcul :
        bm2 = New Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppArgb)
        g = Graphics.FromImage(bm2)
        g.DrawImage(bitmap1Bit, 0, 0, width, height)
        Call SauverImage(bm2, FichierImageResultat)
 
        MsgBox("Traitement terminé")
 
    End Sub
    Private Sub SauverImage(B As Bitmap, F As String)
        Try
            If Dir(F) <> "" Then My.Computer.FileSystem.DeleteFile(F)
            B.Save(F)
        Catch
        End Try
    End Sub
C'est nouveau pour moi... je suis un peu perdu... le code original vient d'un autre site.

Merci A+